Skip to content

Fix SASL PLAIN using ident instead of nick as authcid - #121

Open
nbuechner wants to merge 1 commit into
matrix-org:masterfrom
nbuechner:pr-sasl-plain-authcid
Open

nbuechner wants to merge 1 commit into
matrix-org:masterfrom
nbuechner:pr-sasl-plain-authcid

Conversation

@nbuechner

Copy link
Copy Markdown

Summary

onAuthenticate()'s SASL PLAIN implementation builds the payload as
opt.userName + '\0' + opt.userName + '\0' + opt.password. Per the SASL PLAIN
mechanism, this payload should be authzid\0authcid\0password, where the
authcid is the account/nick being authenticated as - not opt.userName, which
is the separate IRC ident sent via the USER command.

On networks that validate the identity against the given account (e.g. Libera
Chat), this causes SASL to fail with err_saslfail even when the password is
correct, since the configured ident and the actual NickServ account name
essentially never match. The client falls back to registering without SASL,
so it isn't fully broken, but it never gets a successful SASL handshake (and
whatever the server grants for it, e.g. Libera's SASL-based cloak).

Fix

Use this.nick (backed by state.currentNick, which is set from the
requested nick before registration begins) for both the authzid and authcid
fields instead of opt.userName.

Testing

Confirmed against a live matrix-appservice-irc deployment connecting to
Libera Chat: before this fix, every connection logged err_saslfail and fell
back to unauthenticated registration; after this fix (with a valid stored
password), SASL succeeds on the first attempt (900/903 from
SaslServ/services, no err_saslfail).

yarn test:unit passes (one pre-existing, unrelated failure in
test-irc.spec.ts's "part reasons" test reproduces identically on master
without this change).

@nbuechner
nbuechner requested a review from a team as a code owner September 13, 2026 13:37
@progval

progval commented Sep 13, 2026

Copy link
Copy Markdown

It's also not correct to assume the nick and account name are the same. IMO the account name should be a new setting. The nick is probably the best default in general, though one might want to use the username here for compatibility with existing users of node-irc.

SASL PLAIN's payload is authzid\0authcid\0password. onAuthenticate()
was using opt.userName (the IRC ident sent via USER) for both identity
fields instead of the account being authenticated. Networks that
validate the account name (e.g. Libera Chat) reject this with
err_saslfail even when the password is correct, since the ident and
the NickServ account rarely match.

Default to this.nick (the connecting nick, backed by state.currentNick
which is set before registration) for both identity fields, since that
matches most networks/services. The nick and the account name aren't
guaranteed to be the same everywhere though, so add an optional
`saslAccount` opt to override it explicitly for setups where they
differ.
@nbuechner
nbuechner force-pushed the pr-sasl-plain-authcid branch from 81197ca to aa15946 Compare September 13, 2026 13:52
@nbuechner

Copy link
Copy Markdown
Author

Good point, thanks - updated to default to this.nick but added an optional saslAccount opt to override it explicitly for setups where the account name differs from the nick. Already using this in matrix-appservice-irc via a new !saslaccount admin command for exactly that case (fork: nbuechner/matrix-appservice-irc@c7335de).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants