Skip to content

first pass at draft/AUTHTOKEN support#2385

Open
slingamn wants to merge 16 commits intoergochat:masterfrom
slingamn:token.3
Open

first pass at draft/AUTHTOKEN support#2385
slingamn wants to merge 16 commits intoergochat:masterfrom
slingamn:token.3

Conversation

@slingamn
Copy link
Copy Markdown
Member

cc @whitequark @skizzerz

This implements the preliminary version of draft/AUTHTOKEN that I saw. The design here is the planned Ergo implementation: Ergo will GENERATE stateless JWTs, and implement VALIDATE over IRC C2S (and VALIDATE will pull some amount of additional live data to populate claims), but the intent is for Ergo-aware systems to parse and validate the token themselves without calling VALIDATE.

I wrote this code by hand, then had Claude Sonnet 4.6 review it against the spec. It didn't find any sharp edges with the JWT code, but it flagged some discrepancies with the spec:

  1. Will VALIDATE take the service as one of its arguments or not? (This implementation assumes VALIDATE with no service parameter, just the token; the service name is encoded in the token and signed.)
  2. Are GENERATE and SERVICELIST available before connection registration? GENERATE seems not useful in that context. SERVICELIST seems potentially useful but would introduce additional security considerations for Ergo (for example, on a password-protected or require-sasl deployment we would want to hide it).
  3. I implemented an IP whitelist for VALIDATE pre-registration (actually after registration too, but that's not really a concern). The user can enable 0.0.0.0/0 and ::/0 if they need to, but I wanted to make sure that restrictions on who can VALIDATE aren't going against the spirit of the spec.

Thanks!

Includes a backwards-incompatible change to the extjwt
configuration format; this is acceptable because we don't think
many people are using extjwt right now.
@slingamn slingamn added this to the v2.19 milestone Apr 17, 2026
@slingamn slingamn added the IRCv3 label Apr 17, 2026
@whitequark
Copy link
Copy Markdown

whitequark commented Apr 17, 2026

Thank you, that was pretty quick!

I haven't reviewed the implemenation (yet), this is just to answer the questions in the PR description:

  1. Will VALIDATE take the service as one of its arguments or not? (This implementation assumes VALIDATE with no service parameter, just the token; the service name is encoded in the token and signed.)

We've discussed this and concluded that VALIDATE should take the same service as a parameter as GENERATE to reduce the scope of possible token confusion vulnerabilities.

  • Are GENERATE and SERVICELIST available before connection registration? GENERATE seems not useful in that context. SERVICELIST seems potentially useful but would introduce additional security considerations for Ergo (for example, on a password-protected or require-sasl deployment we would want to hide it).

GENERATE is an authentication proxy in concept, so having it available before registration wouldn't make any sense.

We discussed the pros and cons of having SERVICELIST be available without reaching a definitive answer. The main argument in favor of that is that human users (e.g. connecting to the ircd via netcat) would find authenticating e.g. via SASL challenging. Personally, I think this isn't a very convincing use case but I don't find it invalid either. It may be the best option to leave this implementation-defined, since the downstream impact of this uncertainty seems pretty minimal.

I implemented an IP whitelist for VALIDATE pre-registration (actually after registration too, but that's not really a concern). The user can enable 0.0.0.0/0 and ::/0 if they need to, but I wanted to make sure that restrictions on who can VALIDATE aren't going against the spirit of the spec.

It is definitely the intent with VALIDATE that the ircd may ensure (via implementation-specific means) that only the intended service can validate a token generate for it. We don't think it is possible or desirable to exhaustively enumerate such means, but a netmask check is definitely acceptable.

Comment thread irc/jwt/authtoken.go
Comment thread irc/handlers.go Outdated
Comment thread irc/handlers.go Outdated
}

if len(msg.Params) < 2 {
rb.Add(nil, server.name, "FAIL", "TOKEN", "INVALID_PARAMS", "VALIDATE", client.t("No token to validate"))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also not a documented fail code for TOKEN.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, but I generally don't worry too much about standardizing responses for programming errors (as opposed to runtime errors). Clients should never get INVALID_PARAMS or the equivalent outside of a testing/debugging context, so there's not much point in standardizing it. (Similarly, I've gotten some complaints that Ergo sends ERR_NEEDMOREPARAMS in contexts where the spec technically requires FAIL with INVALID_PARAMS, but it's not something I worry about.)

Comment thread irc/handlers.go Outdated
Comment thread irc/handlers.go Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants