Tip of the day: Don't like snomasks / server notices? Then configure logging to a channel.

Extjwt block

From UnrealIRCd documentation wiki
Jump to navigation Jump to search

EXTJWT is a mechanism that allows UnrealIRCd to issue signed tokens to users. These tokens are then presented to external web services to prove their identity and channel membership, without those webservices having to query the IRC server directly.

The typical use case is a web application integrated with your IRC network. A user runs the EXTJWT command, receives a token from the server, and passes it to the web service. The service verifies the token cryptographically and learns: who the user is, whether they are logged in to a services account, what their IRC operator status is, and — if a channel was specified — whether they are currently a member and what privileges they hold. The token has a short expiry time so it cannot be replayed indefinitely.

The tokens are standard JSON Web Tokens (JWT), so any JWT library in any language can verify them on the service side. EXTJWT is based on a proposed IRCv3 specification (work in progress).

(This documentation is a placeholder, generated by AI. We still need to manually go over these docs. The EXTJWT code isn't new, though, it has been in UnrealIRCd for years and recently was enhanced with tests and using the modern OpenSSL API)

Configuration

The module is loaded via:

loadmodule "extjwt";

Configuration lives in an extjwt { } block:

extjwt {
    method <method>;

    /* Required for HS* methods: */
    secret "<shared-secret>";

    /* Required for RS* and ES* methods: */
    key "<path-to-private-key.pem>";

    /* Optional: */
    expire-after <seconds>;
    verify-url 'https://example.com/verify?token=%s'; // be sure to use single quotes 'xx'

    /* Optional: one or more named service blocks */
    service "<name>" {
        method <method>;
        secret "<shared-secret>";  /* or key, depending on method */
        expire-after <seconds>;
        verify-url 'url';  // be sure to use single quotes 'xx'
    }
}

method

Required. The signing method to use:

Method Type Required option
NONE No signature (none)
HS256 / HS384 / HS512 HMAC with SHA-256/384/512 secret
RS256 / RS384 / RS512 RSA signature with SHA-256/384/512 key
ES256 / ES384 / ES512 ECDSA signature with SHA-256/384/512 key

NONE produces an unsigned token that any recipient has to trust on face value. Only use this for development or in environments where the transport itself guarantees integrity. For any real deployment, use at minimum an HMAC method.

HMAC methods (HS*) use a shared secret that both the IRC server and the web service must know. This is the simplest setup, but the secret has to be distributed to every service that verifies tokens.

Asymmetric methods (RS* / ES*) use a private key on the IRC server to sign, and the corresponding public key on the service side to verify. The private key never leaves the server. This is the better choice when multiple independent services need to verify tokens, or when you do not fully control all the verifying parties.

secret

The shared secret used for HMAC signing (HS* methods). Must be at least 4 characters. Must not be set when using asymmetric or NONE methods.

key

Path to a PEM-encoded private key file, relative to the UnrealIRCd conf/ directory. Required for RS* and ES* methods. Must not be set when using HMAC or NONE methods.

expire-after

Optional. How many seconds until the token expires. Valid range is 1–9999. Defaults to 30 seconds if not specified.

Keep this as short as practical — a token that has not yet expired remains valid even if the user has since left a channel or lost their operator status. 30 seconds is usually enough time for the client to receive the token and open the external service in a browser; non-webpage based services may need a longer value depending on their implementation.

verify-url

Optional. A URL template included in the token payload, telling the receiving service where it can verify the token. Must contain %s as a placeholder (which the service substitutes with the token) and must begin with http:// or https://. UnrealIRCd itself does not make any requests to this URL — it is purely informational for the receiving service.

IMPORTANT: Always put the URL in 'single quotes' in the configuration file, otherwise UnrealIRCd will process the URL which is not what you want.

service

Optional. Named service blocks allow you to configure different signing methods or secrets for different web services. A user requests a token for a specific service by passing the service name as the second argument to EXTJWT, for example EXTJWT * mywebsite.

Each service block supports the same options as the top-level block: method, secret, key, expire-after, and verify-url. The method is required per service and NONE is not permitted here. If expire-after is not set on a service it inherits the value from the top-level block.

Examples

Example 1: simple HMAC setup

extjwt {
    method HS256;
    secret "change-this-to-something-long-and-random";
}

Example 2: RSA key

First generate a private key:

openssl genrsa -out conf/extjwt_rsa.pem 2048

Then configure:

extjwt {
    method RS256;
    key "extjwt_rsa.pem";
}

The verifying service extracts the public key from the PEM and uses it with any standard JWT library.

Example 3: ECDSA key

Generate a P-256 key:

openssl ecparam -name prime256v1 -genkey -noout -out conf/extjwt_ec256.pem

Configure:

extjwt {
    method ES256;
    key "extjwt_ec256.pem";
}

Example 4: multiple services

extjwt {
    method NONE;

    service "mywebsite" {
        method HS256;
        secret "website-secret";
        expire-after 60;
    }

    service "mygameserver" {
        method RS256;
        key "extjwt_rsa.pem";
        verify-url 'https://game.example.com/auth/verify?token=%s';  // be sure to use single quotes 'xx'
    }
}

A user requesting a token for mywebsite would run:

EXTJWT * mywebsite