Spring后端用Auth0 JWK库无法验证Azure Entra OIDC的Access Token
说明:本文中使用的值均为示例,例如:3d355765-XXX-47cd-9c7a-bf31179f5XXX
我有一个ReactJS应用和Spring后端应用,但后端无法验证token,抛出异常:"使用SHA256withRSA算法验证时,Token签名无效"。恳请帮忙排查原因。
Azure Entra配置
在Azure Entra中,我仅为ReactJS应用配置了如下"身份验证"设置:
ReactJS配置
ReactJS应用可成功从Azure OIDC获取access_token,使用的是react-oidc-context库,配置如下:

基于Auth0库的Spring后端配置
我在请求后端时,将access_token放在带有"Bearer"前缀的请求头中,示例:"Bearer eyJ0eXAiOiJKV1QiL...."。后端可解析该token,但无法用从JWK URL获取的publicKey完成验证。
依赖库
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.3</version> </dependency> <dependency> <groupId>com.auth0</groupId> <artifactId>jwks-rsa</artifactId> <version>0.22.1</version> </dependency>
实现代码
DecodedJWT jwt = JWT.decode(token); JwkProvider provider = new UrlJwkProvider(new URL("https://login.microsoftonline.com/3d355765-XXX-47cd-9c7a-bf31179f5XXX/discovery/v2.0/keys?appid=5b20cc33-a01b-XXX-be31-cd9ff3aa7XXX")); Jwk jwk = provider.get(jwt.getKeyId()); Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null); algorithm.verify(jwt);
库生成的公钥
Sun RSA public key, 2048 bits params: null modulus: 26737083189757907003055921442770314338988917140860165426744103322405302728616784576359656902377694864963514916366447987755596040063091127319443429395704125552922128507194605677562878395533638591796237899749004909932248262554836300040575758977279732502744063204426839357267389987189285837088487291113549843075686248327277545438158623612248961469127033882959503541559213717818450130719611600764540097268466124320654392000567544359397082999966622432696244505348004947998457969327542701030616111112222267178710534245286750373749139781560960689184289029103448294950355123548539876783713876691492097395497625781588902647221 public exponent: 65537
后端在algorithm.verify(jwt);步骤抛出如下错误:
我仍不清楚遗漏了什么配置。请问是Azure Entra、ReactJS应用还是Spring后端存在配置缺失?
补充信息
当我替换为jsonwebtoken库(而非Auth0库)时:
依赖库
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.5</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.5</version> </dependency>
后端实现代码
Jwts.parserBuilder() .setSigningKeyResolver(new SigningKeyResolverAdapter() { @Override public Key resolveSigningKey(io.jsonwebtoken.JwsHeader header, Claims claims) { String jwksUrl = "https://login.microsoftonline.com/3d355765-XXX-47cd-9c7a-bf31179f5XXX/discovery/v2.0/keys?appid=5b20cc33-a01b-XXX-be31-cd9ff3aa7XXX"; String kid = header.getKeyId(); log.info("kid value: {}", kid); try { String jwksJson = JWKSFetcher.getJWKS(jwksUrl); log.info("jwksJson value: {}", jwksJson); return PublicKeyExtractor.getPublicKeyFromJWKS(jwksJson, kid); } catch (Exception e) { throw new RuntimeException(e); } } }) .build() .parseClaimsJws(token) .getBody();
jsonwebtoken库抛出如下异常:
JWT签名与本地计算的签名不匹配,无法确认JWT有效性,不应信任该JWT。
更新:"Issuer不一致"(2024.08.06)
我发现存在Issuer不一致的问题,这是否是导致问题的原因?
我从https://login.microsoftonline.com/{{MY_TENANT_ID}}/v2.0获取token,但返回的token中的issuer是https://sts.windows.net//{{MY_TENANT_ID}}/,与预期不符。
检查.well-known/openid-configuration中的issuer为预期值:https://login.microsoftonline.com/{{MY_TENANT_ID}}//v2.0
JWKS端点返回的issuer同样为:https://login.microsoftonline.com/{{MY_TENANT_ID}}//v2.0
我更新了manifest文件:
但遗憾的是,获取到的token仍为v1.0版本:
更新:"无法验证Access_Token但Id_Token可验证"(2024.08.09)
这不符合预期且很奇怪:后端无法验证access_token,抛出"签名验证失败"异常,但可以正常验证id_token。
内容的提问来源于stack exchange,提问作者Ali

