首页 > 解决方案 > Azure 针对 Azure B2C 活动目录验证 JWT 令牌

问题描述

电话客户端向我发送从 Azure 中的 Active Directory B2C 获取的 access_token。我有一个服务器端 Spring Boot 应用程序,想检查令牌的来源是否是 Azure 的 Active Directory,并且不是手动操作的,它是否有效。

我期待类似的东西

        String validationUrl = "https://azure.microsoft/validate-token";
        // put token in header
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<String> entity = new HttpEntity<>(null, headers);
        String result = restTemplate.exchange(validationUrl, HttpMethod.GET,
                entity, String.class).getBody();

我尝试了类似于:

        try {
            provider = new UrlJwkProvider(new URL("https://login.microsoftonline.com/common/.well-known/openid-configuration"));
            jwk = provider.get(jwt.getKeyId());
            algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
            algorithm.verify(jwt);// if the token signature is invalid, the method will throw SignatureVerificationException
            return true;
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (JwkException e) {
            e.printStackTrace();
        } catch (SignatureVerificationException e) {
            System.out.println(e.getMessage());
        }

结果总是 com.auth0.jwk.SigningKeyNotFoundException: No keys found in

然后我尝试了另一种实现:

  HttpsJwks httpsJkws = new HttpsJwks(url);
        HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
        JwtConsumer jwtConsumer = new JwtConsumerBuilder()
                .setRequireExpirationTime() // the JWT must have an expiration time
                .setAllowedClockSkewInSeconds(3600) // allow some leeway in validating time based claims to account for clock skew
                .setVerificationKeyResolver(httpsJwksKeyResolver)
                .setRelaxVerificationKeyValidation()
                .build();

        try
        {
            //  Validate the JWT and process it to the Claims
            JwtClaims jwtClaims = jwtConsumer.processToClaims(accessToken);
            System.out.println("JWT validation succeeded! " + jwtClaims);
            return true;
        }
        catch (InvalidJwtException e)
        {
            // InvalidJwtException will be thrown, if the JWT failed processing or validation in anyway.
            // Hopefully with meaningful explanations(s) about what went wrong.
            System.out.println("Invalid JWT! " + e);
        }

结果总是无效的 JWT!org.jose4j.jwt.consumer.InvalidJwtException:JWT 处理失败。其他详细信息:[[17] 无法处理 JOSE 对象(原因:org.jose4j.lang.UnresolvableKeyException:无法为带有标头的 JWS 找到合适的验证密钥

我还尝试了以下 URL: https ://login.microsoftonline.com/MY_TENANT/.well-known/openid-configuration

https://login.microsoftonline.com/MY_TENANT/discovery/v2.0/keys?appid=APP_ID

https://login.microsoftonline.com/MY_TENANT/discovery/v2.0/keys

https://login.microsoftonline.com/common/.well-known/openid-configuration

https://login.microsoftonline.com/discovery/v2.0/keys

标签: javaazurespring-bootactive-directoryazure-active-directory

解决方案


Azure AD 的 access_token 是 JSON Web Token (JWT)。因此,您可以使用 Java 中的 JWKS 验证 JWT 令牌jwks_uri可以通过形成的链接获取/.well-known/openid-configuration,见这里

在此处输入图像描述

DecodedJWT jwt = JWT.decode(token);
JwkProvider provider = provider = new UrlJwkProvider("https://login.microsoftonline.com/common/discovery/keys");
Jwk jwk = provider.get(jwt.getKeyId());
Algorithm algorithm = Algorithm.RSA256((RSAPublicKey) jwk.getPublicKey(), null);
algorithm.verify(jwt);

您可以先在线测试您的令牌,https://jwt.io/


推荐阅读