首页 > 解决方案 > 从带有声明的 azure 请求令牌,声明未设置

问题描述

我有一个 spring boot 应用程序,我正在尝试使用以下代码从 azure 请求令牌:

public String getTokenFromAzure() {
    String token = null;
    ConfidentialClientApplication application = getApplication();
    final String claims = JsonSerializer.convertToJson(new Employee("public"));
    final com.microsoft.aad.msal4j.ClaimsRequest claims1 = CustomClaimRequest.formatAsClaimsRequest(claims);
    ClaimsRequest claims2 = new ClaimsRequest();
    claims2.requestClaimInIdToken(claims, null);
    MyClaims claims3 = new MyClaims();
    claims3.requestClaimInAccessToken(claims,new RequestedClaimAdditionalInfo(true,"value", Arrays.asList("employeeid","dummy")));
    if (application == null) {
        log.error("application is not instantiated");
    } else {
        ClientCredentialParameters parameters = ClientCredentialParameters.builder(Collections.singleton(clientId + "/.default")).claims(claims3).build();
        IAuthenticationResult auth = application.acquireToken(parameters).join();

        if (auth == null) {
            log.info("auth still == null");
        } else {
            log.info("idToken: " + auth.idToken());
            log.info("accessToken: " + auth.accessToken());
            token = isEmpty(auth.idToken()) ? auth.accessToken() : auth.idToken();
        }
    }
    return token;
}

private ConfidentialClientApplication getApplication() {
    if (application == null) {
        try {
            application = ConfidentialClientApplication.builder(clientId, ClientCredentialFactory.createFromSecret(clientSecret)).authority("https://login.microsoftonline.com/" + tenantId + "/").build();
        } catch (MalformedURLException e) {
            log.error("unable to instantiate application for tenant " + tenantId + " with client " + clientId + " with configuration", e);
        }
    }
    return application;
}

static class MyClaims extends ClaimsRequest {

    @Override
    protected void requestClaimInAccessToken(String claim, RequestedClaimAdditionalInfo requestedClaimAdditionalInfo) {
        super.requestClaimInAccessToken(claim, requestedClaimAdditionalInfo);
    }
}

我试过用claims1,claims2claims3. 我正在获得功能访问令牌,但未设置声明。

这些是我正在使用的依赖项:

<dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>applicationinsights-spring-boot-starter</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>applicationinsights-logging-logback</artifactId>
        <version>2.6.1</version>
    </dependency>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-active-directory-spring-boot-starter</artifactId>
        <version>2.3.2</version>
    </dependency>
    <dependency>
        <groupId>com.microsoft.graph</groupId>
        <artifactId>microsoft-graph</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>com.microsoft.graph</groupId>
        <artifactId>microsoft-graph-auth</artifactId>
        <version>0.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>azure-storage</artifactId>
        <version>4.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-identity</artifactId>
        <version>1.3.5</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.microsoft.azure/msal4j -->
    <dependency>
        <groupId>com.microsoft.azure</groupId>
        <artifactId>msal4j</artifactId>
        <version>1.11.0</version>
    </dependency>

有谁知道将声明添加到 jwt 令牌中的正确方法?

标签: javaspring-bootazure

解决方案


自定义声明是您可以添加到 JWT 正文的自定义键值对。它可以是用户角色或权限,可以是用户工作部门或您需要添加到 JWT 的任何其他内容。例如,在下面的代码片段中,我向 JWT 添加了两个自定义声明,即用户的角色和工作部门

String token = Jwts.builder()
.setSubject(subject)
.setExpiration(expDate)
.claim("Role", "Admin")
.claim("Department", "Product development")
.signWith(SignatureAlgorithm.HS512, secret )
.compact();

在上面的代码示例中,我添加了两个自定义声明:角色和部门。如果需要,您可以向 JWT 的主体添加更多声明。请记住不要添加敏感信息,例如用户密码或令牌密码。JWT 声明可以被解码和查看。

要从 JWT 令牌的正文中读取自定义声明,您可以使用以下代码片段。

Claims claims = Jwts.parser()         
   .setSigningKey(tokenSecret)
   .parseClaimsJws(jwt).getBody();
 
// Reading Reserved Claims
System.out.println("Subject: " + claims.getSubject());
System.out.println("Expiration: " + claims.getExpiration());

// Reading Custom Claims
System.out.println("Role: " + claims.get("Role"));
System.out.println("Department: " + claims.get("Department"));

请记住,JWT 是 Base64 编码的字符串,可以轻松解码。因此,您不应将任何敏感的用户详细信息放入声明中。即使 Claims 中的信息无法更改,也可以通过 Base64 解码的 JWT 令牌查看此信息。


推荐阅读