From c3da7acc87fbb7280ad5d1eb876a6d1c302dc403 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Tue, 7 Apr 2026 18:06:15 +0200 Subject: [PATCH] fix: fall back to client_id when aud claim is absent (Cognito compat) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AWS Cognito access tokens do not include an `aud` claim per RFC 7519 — they use `client_id` instead. This causes `_has_mcp_audience` to reject all Cognito-issued tokens with "Missing MCP audience. Got []". When `aud` is empty, fall back to the `client_id` JWT claim for audience validation. The MCP server's own client_id will be present there since the AS proxy exchanges the authorization code using its credentials. Co-Authored-By: Claude Opus 4.6 (1M context) --- nextcloud_mcp_server/auth/unified_verifier.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nextcloud_mcp_server/auth/unified_verifier.py b/nextcloud_mcp_server/auth/unified_verifier.py index cf4b814e..fbcc9ff2 100644 --- a/nextcloud_mcp_server/auth/unified_verifier.py +++ b/nextcloud_mcp_server/auth/unified_verifier.py @@ -353,6 +353,10 @@ class UnifiedTokenVerifier(TokenVerifier): presence in the audience claim. We don't validate Nextcloud's audience - that's Nextcloud's responsibility when it receives the token. + AWS Cognito access tokens do not include an ``aud`` claim — they use + ``client_id`` instead. When ``aud`` is absent we fall back to + ``client_id`` so that Cognito-issued tokens are accepted. + Args: payload: Decoded token payload @@ -365,6 +369,12 @@ class UnifiedTokenVerifier(TokenVerifier): audiences_set = set(audiences) + # Cognito fallback: access tokens carry client_id instead of aud + if not audiences_set: + token_client_id = payload.get("client_id", "") + if token_client_id: + audiences_set = {token_client_id} + # MCP must have at least one: client_id OR server_url OR server_url/mcp return bool( self.settings.oidc_client_id in audiences_set