Skip to content

Update code to be tolerant of unknown authentication failure reasons. - #844

Merged
alexfish8 merged 7 commits into
mainfrom
afish/auth-codes
Sep 15, 2026
Merged

alexfish8 merged 7 commits into
mainfrom
afish/auth-codes

Conversation

@alexfish8

@alexfish8 alexfish8 commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Treat unrecognized rpc.SIPTrunkAuthenticationError values as an authentication failure instead of accepting the call. Also, map certain authentication error codes to ClientError rather than ServerError.

Today the adapter in pkg/service/psrpc.go handles only QUOTA_EXCEEDED and NO_TRUNK_FOUND. Any other non-zero code falls through the drop and password checks and is returned as AuthAccept with an empty trunk ID. This PR adds an AuthFailureUnknown result for that case. The INVITE is answered with 401 and recorded as ClientError("auth-unknown").

Also, update the switch statements to handle a new kind of authentication failure: ROUTE_NOT_ALLOWED.

Motivation: The auth service will start returning new enum values for rejections it currently reports as errors. Those errors make SIP end the call as ServerError("auth-error") with a 503, which should be reserved for availability failures. This change has to roll out before the auth service does, so a newer auth service talking to an older SIP rejects rather than admits.

NOTE: This depends on livekit/protocol#1798.

@alexfish8
alexfish8 requested a review from a team as a code owner September 11, 2026 21:48
devin-ai-integration[bot]

This comment was marked as resolved.

Comment thread pkg/service/psrpc.go
switch resp.ErrorCode {
case rpc.SIPTrunkAuthenticationError_SIP_TRUNK_AUTH_ERROR_QUOTA_EXCEEDED:
authResult = sip.AuthQuotaExceeded
case rpc.SIPTrunkAuthenticationError_SIP_TRUNK_AUTH_ERROR_NO_TRUNK_FOUND:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what's the difference between resp.ErrorCode with rpc.SIPTrunkAuthenticationError_SIP_TRUNK_AUTH_ERROR_NO_TRUNK_FOUND and psrpc.GetErrorCode(err) with psrpc.NotFound? both are not found 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The auth service might return errors in two different channels: (a) the RPC error itself and (b) the ErrorCode field in the response itself. The channels are mutually exclusive, and so if we receive an RPC error then we won't have a response and an ErrorCode, and if we have a response and an ErrorCode then we won't have an RPC error.

Comment thread pkg/sip/inbound.go
return psrpc.NewErrorf(psrpc.PermissionDenied, "auth failure")
case AuthRejectedAsError:
// Own metric reason so auth-service contract violations show up as their own series.
cmon.InviteErrorShort(stats.ClientError("auth-rejected-as-error"))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

do we know what kind of other errors could there be? are they all client errors?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Since you've last viewed the PR, I've added handling for a new kind of auth failure (ROUTE_NOT_ALLOWED, which is returned when anycast isn't enabled).

The other sorts of auth failure are related to trunk configuration issues (i.e. client errors).

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

3 flags not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)

Devin Review

Comment thread pkg/sip/inbound.go
case AuthRouteNotAllowed:
cmon.InviteErrorShort(stats.ClientError("route-not-allowed"))
log.Warnw("Rejecting inbound, route not allowed", nil)
cc.RespondAndDrop(sip.StatusServiceUnavailable, "Service temporarily unavailable")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Cached 503 blocks route failover

When AuthRouteNotAllowed causes same-server failover with the same Call-ID and From-tag, rejectedInvites replays the 503. The alternate origination URI receives no authentication check until callCacheTTL expires.

Learn more

RespondAndDrop caches every final response at or above 300 using only the SIP Call-ID and From-tag as its key. A carrier can reuse both values when retrying a 503 against another origination URI. The replay path runs before authentication and ignores the new request URI, so the second route inherits the first route's rejection. The entry remains active for one minute.

Example: A carrier sends Call-ID abc with From-tag t1 to sip-a.example.com and receives 503 for ROUTE_NOT_ALLOWED. It retries the same dialog identifiers against sip-b.example.com, which reaches the same SIP server. The server replays 503 instead of authorizing sip-b.example.com, although that route can be allowed.

Recommended fix: Do not add retryable 5xx responses to rejectedInvites, or include the destination route in the cache key. Preserve deduplication for terminal rejections while allowing a changed origination URI to run GetAuthCredentials again.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@alexfish8
alexfish8 merged commit 58cabd6 into main Sep 15, 2026
7 checks passed
@alexfish8
alexfish8 deleted the afish/auth-codes branch September 15, 2026 00:23
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