Spring集成jose4j时JWT多audience列表校验失败问题
JWT受众校验不匹配问题排查
问题复现代码
令牌生成端aud配置
JwtClaims claims = new JwtClaims(); claims.setIssuer(issuer); claims.setAudience(Lists.newArrayList(audiences)); claims.setExpirationTimeMinutesInTheFuture(60); claims.setJwtId(keyId); claims.setIssuedAtToNow(); claims.setNotBeforeMinutesInThePast(2); claims.setSubject(subject);
消费端校验配置
JwtConsumer jwtConsumer = new JwtConsumerBuilder() .setRequireExpirationTime() .setAllowedClockSkewInSeconds(30) .setRequireSubject() .setExpectedIssuer(issuer) .setExpectedAudience(String.valueOf(Lists.newArrayList(audiences))) .setVerificationKey(rsaJsonWebKey.getKey()) .build();
抛出的异常信息
Invalid JWT! org.jose4j.jwt.consumer.InvalidJwtException: JWT (claims->{"iss":"EXAMPLEISSUER","aud":["test1","test2","test3"],"exp":1657880599,"jti":"EXAMPLE_SHA1withRSA","iat":1657876999,"nbf":1657876879,"sub":"example"}) rejected due to invalid claims or other invalid content. Additional details: [[8] Audience (aud) claim [test1, test2, test3] doesn't contain an acceptable identifier. Expected [test1, test2, test3] as an aud value.]
根因分析
- 消费端
setExpectedAudience方法入参配置错误:String.valueOf(Lists.newArrayList(audiences))会将整个受众列表转换为单个字符串值(即内容为[test1, test2, test3]的普通字符串)传入,作为唯一的预期受众值。 - jose4j的aud claim校验规则为:只要令牌携带的aud数组中,包含任意一个配置的预期受众字符串,就判定aud校验通过。当前配置的预期值是一个格式为列表的整串,和JWT中存储的三个独立受众字符串
test1、test2、test3完全无法匹配,因此抛出校验失败异常。
修复方案
不要将受众列表转为单个字符串传入,直接传入多个独立的受众值即可。如果使用的是Guava的Lists生成的受众列表,可将其转为数组后传入可变参数重载方法,修正后的代码如下:
JwtConsumer jwtConsumer = new JwtConsumerBuilder() .setRequireExpirationTime() .setAllowedClockSkewInSeconds(30) .setRequireSubject() .setExpectedIssuer(issuer) // 直接传入受众列表转成的数组,不要做整列表的字符串转换 .setExpectedAudience(audiences.toArray(new String[0])) .setVerificationKey(rsaJsonWebKey.getKey()) .build();
注:如果audiences本身就是String数组类型,直接传入audiences即可,无需额外转换。
内容的提问来源于stack exchange,提问作者DiegoMG
相关产品推荐
相关产品推荐

