test(auth): drive JWKS bearer validation end-to-end; require sub, validate nbf#267
Open
smunini wants to merge 1 commit into
Open
test(auth): drive JWKS bearer validation end-to-end; require sub, validate nbf#267smunini wants to merge 1 commit into
smunini wants to merge 1 commit into
Conversation
…idate nbf Adds an RS256 + wiremock JWKS harness so the provider's accept/reject behavior is tested through authenticate(), not just the shape of the Validation struct (which would keep passing if a jsonwebtoken upgrade changed claim semantics). Also closes two gaps the harness made easy to cover: - sub is now a required claim, and a present-but-empty sub is rejected: the subject is what audit records and policy decisions are attributed to. - nbf is now validated, so a not-yet-valid token is rejected. It is enforced only when present, so tokens that omit nbf are unaffected. The non-string-aud case (e.g. "aud": 42) is also pinned: it fails to deserialize, and a failed parse was indistinguishable from an absent claim to the audience check, so it bypassed audience validation the same way an omitted aud did.
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.
Follow-up from the security review of #229. Stacked on #229 — base is
fix/206-audience-required-claim, so merge that first (or retarget this tomainafterwards).Tests that pin behavior, not struct fields
#229's tests assert on the fields of the
Validationstruct. They are real regression tests (they fail without the fix), but a futurejsonwebtokenupgrade that changed claim-validation semantics underneath us would leave them passing.This adds the RS256 +
wiremockJWKS harness the #229 description noted was missing, soauthenticate()is exercised with genuinely signed tokens against a served JWKS.wiremockwas already a dev-dependency; the only new fixture is a test RSA keypair.Each protection was mutation-checked — removing it turns exactly the expected tests red:
aud/issrequired-claims (pre-#229 code)token_without_audience_is_rejected,token_without_issuer_is_rejected,token_with_non_string_audience_is_rejectedsubrequirementtoken_without_subject_is_rejected,token_with_empty_subject_is_rejectedvalidate_nbfnot_yet_valid_token_is_rejectedvalid_token_is_acceptedandtoken_with_a_bad_signature_is_rejectedguard against the suite passing vacuously.Two gaps the harness made easy to close
subis now required. The subject is what audit records and policy decisions are attributed to (and what bulk export ties job ownership to), but a token without one previously yielded aPrincipalwith an empty-string subject. Note the required-claim check only asserts presence, so"sub": ""would satisfy it and still produce an anonymous principal —authenticate()rejects that explicitly as well.nbfis now validated. It defaults to off injsonwebtoken, so a not-yet-valid token was accepted. It is enforced only when the claim is present, so tokens that omitnbfare unaffected.Also pinned: the non-string-
audbypassWorth calling out because #229 closes it without mentioning it. A token with
"aud": 42fails to deserialize, and a failed parse was indistinguishable from an absent claim to the audience check — so it bypassed a configuredHFS_AUTH_AUDIENCEexactly the way an omittedauddid. It is now covered by a test, so it can't silently regress.Related: #266 (warn when
HFS_AUTH_AUDIENCEis unset).