Skip to content

fix: Cognito token verification checks client_id instead of aud#3786

Merged
jlowin merged 3 commits intomainfrom
fix/cognito-audience-validation
Apr 7, 2026
Merged

fix: Cognito token verification checks client_id instead of aud#3786
jlowin merged 3 commits intomainfrom
fix/cognito-audience-validation

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Apr 7, 2026

AWS Cognito access tokens don't include an aud claim; they use client_id instead. #3406 correctly added audience binding to prevent cross-client token reuse, but the implementation validated aud via the base JWTVerifier, which always failed for Cognito tokens since the claim doesn't exist.

AWSCognitoTokenVerifier now intercepts the audience parameter, passes None to the parent (disabling the aud check), and validates the client_id claim directly. The provider API is unchanged; get_token_verifier still passes audience=self.client_id exactly as before. The security intent (binding verification to the configured app client) is preserved; only the claim being checked changes.

Closes #3739

@marvin-context-protocol marvin-context-protocol Bot added auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. labels Apr 7, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b892808d60

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +58 to +59
kwargs.pop("audience", None)
super().__init__(audience=None, **kwargs)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve audience alias in Cognito verifier init

Dropping audience in AWSCognitoTokenVerifier.__init__ creates a silent security regression for callers that instantiate this class directly (instead of going through AWSCognitoProvider.get_token_verifier). Before this change, passing audience="client-a" enforced client binding via JWTVerifier; now audience is discarded and, unless expected_client_id is also set, no client binding is enforced at all, so tokens from other app clients can validate as long as issuer/signature/scope checks pass.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a6a5db1d56

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +60 to +62
if self._expected_client_id:
token_client_id = access_token.claims.get("client_id")
if token_client_id != self._expected_client_id:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Support list audience values in Cognito client_id check

AWSCognitoTokenVerifier.__init__ still accepts audience: str | list[str] | None, but verify_token now does a direct equality check between token_client_id (string claim) and self._expected_client_id. When callers pass multiple allowed audiences (a list), every valid token is rejected because a string can never equal that list, which is a regression from the base JWTVerifier behavior that supports list membership checks. This affects direct instantiations of AWSCognitoTokenVerifier and any future call path that forwards a list audience.

Useful? React with 👍 / 👎.

@jlowin jlowin merged commit e1ea133 into main Apr 7, 2026
8 checks passed
@jlowin jlowin deleted the fix/cognito-audience-validation branch April 7, 2026 22:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

auth Related to authentication (Bearer, JWT, OAuth, WorkOS) for client or server. bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AWSCognitoProvider: audience validation fails because Cognito access tokens use client_id, not aud

1 participant