{"record":{"id":"c3da31c54139e002","repo":"alibaba/nacos","slug":"token-audience-validation-failed","errorCode":null,"errorMessage":"Token audience validation failed","messagePattern":"Token audience validation failed","errorType":"exception","errorClass":"AccessException","httpStatus":null,"severity":"error","filePath":"plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/token/JwtTokenValidator.java","lineNumber":230,"sourceCode":"            throw new AccessException(\"Token is not yet valid\");\n        }\n        \n        // Validate audience (if client ID is configured)\n        String clientId = config.getClientId();\n        if (StringUtils.isNotBlank(clientId)) {\n            List<String> audience = claims.getAudience();\n            if (audience != null && !audience.isEmpty() && !audience.contains(clientId)) {\n                // Check if 'azp' (authorized party) matches\n                String azp = (String) claims.getClaim(\"azp\");\n                if (!clientId.equals(azp)) {\n                    String message = String.format(\n                        \"Token audience mismatch. Expected: %s, Got: %s, azp: %s\",\n                        clientId, audience, azp);\n                    \n                    if (config.isStrictAudienceValidation()) {\n                        LOGGER.error(\"{} - Strict validation enabled, rejecting token. \"\n                            + \"This token may be intended for a different client.\", message);\n                        throw new AccessException(\"Token audience validation failed\");\n                    } else {\n                        LOGGER.warn(\"{} - Strict validation disabled, accepting token. \"\n                            + \"Set 'nacos.plugin.auth.oidc.strict-audience-validation=true' for better security.\",\n                            message);\n                    }\n                }\n            }\n        }\n        \n        // Validate issuer\n        String issuer = claims.getIssuer();\n        String expectedIssuer = config.getIssuerUri();\n        if (StringUtils.isNotBlank(expectedIssuer) && !expectedIssuer.equals(issuer)) {\n            // Handle trailing slash difference\n            String normalizedExpected = expectedIssuer.endsWith(\"/\")\n                ? expectedIssuer.substring(0, expectedIssuer.length() - 1)\n                : expectedIssuer;\n            String normalizedIssuer = issuer != null && issuer.endsWith(\"/\")","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/alibaba/nacos/blob/9b989acdf181d00898f2e8839257bb2b2a3cefe3/plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/token/JwtTokenValidator.java#L212-L248","documentation":"Thrown by validateClaims during strict audience validation: client-id is configured, the token's 'aud' does not contain it, and the 'azp' (authorized party) claim also does not match. Only fires when strict-audience-validation=true (the default).","triggerScenarios":"config.getClientId() is non-blank, claims.getAudience() is non-empty and excludes clientId, claims.getClaim('azp') != clientId, and config.isStrictAudienceValidation() is true.","commonSituations":"client-id is misconfigured (typo, wrong IdP client); the token was minted for a different audience/client; multi-audience token without the Nacos client in it; copying a client-id from one IdP environment to another.","solutions":["Set client-id to the exact value the IdP mints into aud/azp for the Nacos client.","Verify the IdP client configuration includes Nacos in the allowed audiences.","As a temporary/less-secure measure, set strict-audience-validation=false (the token will be accepted with only a WARN log).","Decode the token and confirm the actual aud and azp values, then align client-id.","Inspect the ERROR log 'Token audience mismatch. Expected: ... Got: ... azp: ...' for the exact mismatch."],"exampleFix":"# before\nnacos.plugin.auth.oidc.client-id=nacos-wrong\nnacos.plugin.auth.oidc.strict-audience-validation=true\n\n# after: align client-id with token aud/azp\nnacos.plugin.auth.oidc.client-id=nacos-client\n# (or, less secure) nacos.plugin.auth.oidc.strict-audience-validation=false","handlingStrategy":"validation","validationCode":"JWTClaimsSet preview = JWTClaimsSet.parse(new String(Base64.getUrlDecoder().decode(token.split(\"\\\\.\")[1])));\nString clientId = config.getClientId();\nList<String> aud = preview.getAudience();\nString azp = (String) preview.getClaim(\"azp\");\nboolean ok = aud == null || aud.isEmpty() || aud.contains(clientId) || clientId.equals(azp);\nif (!ok && config.isStrictAudienceValidation()) {\n    // fix client-id or disable strict mode before calling validate()\n}","typeGuard":null,"tryCatchPattern":"try {\n    validator.validate(token);\n} catch (AccessException e) {\n    if (\"Token audience validation failed\".equals(e.getMessage())) {\n        // 403 wrong_audience; align client-id with token aud/azp\n    }\n    throw e;\n}","preventionTips":["Set client-id to the exact value the IdP places in aud/azp.","Decode tokens during integration to verify audience values.","Keep strict-audience-validation=true in production; only relax with documented reason."],"tags":["oidc","jwt","audience","security","claims"],"backgroundTag":null,"analyzedSha":"9b989acdf181d00898f2e8839257bb2b2a3cefe3","analyzedAt":"2026-08-14T07:17:31.569Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}