Repository navigation
Conversation
The id_token was trusted after base64-decoding: no exp, aud or iss checks, and the OIDC nonce generated at login was carried in the signed state but never sent to the provider nor checked on return. OIDC Core 3.1.3.7 keeps several claim checks mandatory even when the token arrives over the token-endpoint back channel (which is why the JWS signature is not re-verified here). - id_token: exp must be current, aud must carry our client id (string or single-element array), iss must match the provider's issuer (canonical for google/apple; new optional per-provider issuer setting for generic oidc), and the nonce sent with the authorization request must come back. - login now sends the nonce; verify_state_token returns it alongside the provider tag and redirect. - docs/config.md documents the issuer setting; API_CHANGELOG.md records the behavior change. Follow-up worth considering: PKCE (S256) on the authorization-code flow. Found by the 2026-11-01 security audit.
mptfire
force-pushed
the
audit/oauth-idtoken-validation
branch
from
November 1, 2026 22:50
6cc759d to
e59a2aa
Compare
mptfire
added a commit
to mptfire/api
that referenced
this pull request
Nov 2, 2026
Follow-up to the id_token hardening (LNVPS#431). Every authorization request now carries a code_challenge and the token exchange presents the code_verifier (RFC 7636, S256). The verifier rides the signed, short-lived state token, so the flow stays stateless; states minted before PKCE simply carry no verifier and the token request omits it. Mitigates authorization-code interception (RFC 9700 section 4.6): a code stolen from redirects, referrers or logs is useless without the verifier, which never leaves the server and the provider's browser session. docs/config.md documents the behavior; API_CHANGELOG.md records it. Found by the 2026-11-01 security audit (LNVM-013 follow-up).
v0l
requested changes
Nov 2, 2026
v0l
left a comment
Contributor
There was a problem hiding this comment.
Validation logic and tests look right. A few things before merge:
- Google is not covered.
expected_issreturnshttps://accounts.google.comfor Google, but Google'ssubject_source()is userinfo, sovalidate_id_token_claimsnever runs for it and the nonce is never checked. Google also issuesiss: accounts.google.com(no scheme) in some tokens; if you later route Google through the id_token path, accept both. Either drop Google fromexpected_issor validate the id_token on the userinfo path too. audarray withazp. OIDC Core 3.1.3.7 step 4/5: whenaudhas multiple entries,azpshould be present and equal the client id. Cheap to add while you're here.- No clock skew allowance on
exp. Apple tokens are 10 minutes; a worker a few seconds fast will reject at the edge. Allow ~60s. - A login that fails validation returns 500 (
ApiError::internal). That's a client/provider fault, so 400/401 would be more accurate and keeps it out of 5xx alerting. - Doc comments on new items: we keep comments out of new code (
docs/agents/code-style.md), please trim them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Found by an independent security audit of the tree at
e5d95b0(2026-11-01).Problem
The
id_tokenwas trusted straight after base64-decoding (decode_id_token): noexp,audorisschecks. The OIDCnoncegenerated at login was carried inside the signedstatebut never sent to the provider and never checked on return. OIDC Core §3.1.3.7 keeps several claim checks mandatory even when the token arrives over the TLS-protected token-endpoint back channel (which is the documented reason the JWS signature is not re-verified here): issuer identifier match, audience check, expiry check — and the nonce check binds the response to the request.Without these, a misconfigured or multi-tenant IdP (generic
oidcproviders) could hand back a token minted for another client/issuer, and a code-injected login could not be distinguished;exp-stale tokens from a provider glitch would be accepted.Fix
validate_id_token_claims(in theIdTokensubject-source path):expmust be in the future,audmust contain our client id (string or single-element array form),issmust equal the provider's expected issuer, and thenoncesent with the authorization request must be echoed by the token.google/apple; new optional per-providerissuersetting for genericoidcproviders (documented indocs/config.md). Providers without anid_tokenidentity source (GitHub/Facebook userinfo flow) skip theisscheck by design.nonce;verify_state_tokenreturns it (alongside the provider tag and redirect) so the callback can compare.Validation
lnvps_apilib 16 oauth tests,lnvps_api_common638).Audit reference: LNVM-013 (Low; hardening per OIDC Core §3.1.3.7 / RFC 9700).