alibaba/nacos · error · AccessException

Token issuer mismatch

Error message

Token issuer mismatch

What it means

Thrown by validateClaims when the token's 'iss' claim does not equal the configured issuer-uri, even after normalizing a single trailing slash on both sides. This catches tokens issued by a different/stale authority.

Source

Thrown at plugin-default-impl/nacos-oidc-auth-plugin/src/main/java/com/alibaba/nacos/plugin/auth/impl/oidc/token/JwtTokenValidator.java:253

                    }
                }
            }
        }
        
        // Validate issuer
        String issuer = claims.getIssuer();
        String expectedIssuer = config.getIssuerUri();
        if (StringUtils.isNotBlank(expectedIssuer) && !expectedIssuer.equals(issuer)) {
            // Handle trailing slash difference
            String normalizedExpected = expectedIssuer.endsWith("/")
                ? expectedIssuer.substring(0, expectedIssuer.length() - 1)
                : expectedIssuer;
            String normalizedIssuer = issuer != null && issuer.endsWith("/")
                ? issuer.substring(0, issuer.length() - 1)
                : issuer;
            
            if (!normalizedExpected.equals(normalizedIssuer)) {
                throw new AccessException("Token issuer mismatch");
            }
        }
    }
    
    /**
     * Extract username from JWT claims.
     *
     * @param claims JWT claims
     * @return username
     */
    public String extractUsername(JWTClaimsSet claims) {
        String usernameClaim = config.getUsernameClaim();
        
        // Try configured claim first
        Object username = claims.getClaim(usernameClaim);
        if (username != null) {
            return username.toString();
        }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Set issuer-uri to exactly the IdP's canonical issuer (from /.well-known/openid-configuration 'issuer').
  2. Decode the token's 'iss' claim and compare verbatim with the configured issuer-uri.
  3. Ensure scheme (http/https) and host match exactly; only a single trailing slash is tolerated.
  4. If running multiple environments, use the correct issuer-uri per environment.
  5. Re-issue the token from the IdP whose issuer matches the config.

Example fix

# before
nacos.plugin.auth.oidc.issuer-uri=https://idp.example.com/auth/realms/test
# token iss = https://idp.example.com/auth/realms/prod

# after
nacos.plugin.auth.oidc.issuer-uri=https://idp.example.com/auth/realms/prod
Defensive patterns

Strategy: validation

Validate before calling

JWTClaimsSet preview = JWTClaimsSet.parse(new String(Base64.getUrlDecoder().decode(token.split("\\.")[1])));
String expected = config.getIssuerUri();
String iss = preview.getIssuer();
String norm(String s){ return s != null && s.endsWith("/") ? s.substring(0, s.length()-1) : s; }
if (expected != null && !expected.isBlank() && !norm(expected).equals(norm(iss))) {
    // fix issuer-uri or reject token before validate()
}

Try / catch

try {
    validator.validate(token);
} catch (AccessException e) {
    if ("Token issuer mismatch".equals(e.getMessage())) {
        // 403 wrong_issuer; verify issuer-uri matches IdP discovery 'issuer'
    }
    throw e;
}

Prevention

When it happens

Trigger: issuer-uri is non-blank, claims.getIssuer() differs from it, and normalizing trailing slashes on both does not make them equal.

Common situations: issuer-uri typo or wrong environment (e.g. test IdP token against prod issuer-uri); IdP changed its canonical issuer string; trailing-slash beyond the single-slash normalization; http vs https in the issuer.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/74155b07e2c2fc5b. Report an issue: GitHub.