You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用id_token保护对接Azure AD B2C的Java Spring Boot 3 API?

解决方案思路与实现步骤

首先明确:Azure AD B2C的id_token是标准JWT令牌,尽管它的设计初衷是用户身份认证凭证而非API授权凭证,但我们可以通过验证其签名、核心声明(如受众、签发者、有效期)来实现API保护,完全不需要依赖access_token或OBO(On-Behalf-Of)流程。

步骤1:Azure AD B2C应用注册配置

  • 确保你的API应用注册已启用ID令牌支持:在API应用的「身份验证」设置中,勾选「ID令牌」选项(用于让B2C的密钥服务能为id_token提供验证依据)
  • 记录三个关键信息:API应用的客户端ID(对应id_token的aud声明)、B2C租户ID、用户流/自定义策略名称(用于构造JWKS验证端点)

步骤2:Spring Boot 3 依赖与配置(Java 17)

依赖配置(pom.xml)

引入Spring Security OAuth2资源服务器依赖,它原生支持JWT验证:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>

应用配置(application.yml)

配置JWT验证的核心参数,确保与id_token的声明匹配:

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          audience: <你的API应用客户端ID>
          issuer-uri: https://<你的B2C租户名>.b2clogin.com/<你的B2C租户ID>/<用户流/自定义策略名称>/v2.0/
          jwk-set-uri: https://<你的B2C租户名>.b2clogin.com/<你的B2C租户ID>/<用户流/自定义策略名称>/discovery/v2.0/keys

注意:issuer-uri必须和id_token里的iss声明完全一致,audience必须匹配id_token的aud声明(即API应用的客户端ID)

步骤3:Spring Security 安全规则配置

创建安全配置类,保护API端点并启用JWT验证:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt
                    // 可选:自定义身份转换,从id_token提取用户信息
                    .jwtAuthenticationConverter(new CustomJwtAuthConverter())
                )
            );
        return http.build();
    }
}

可选:自定义用户身份提取

如果需要从id_token中提取用户信息(如邮箱、用户名)用于业务逻辑,可自定义转换器:

import org.springframework.core.convert.converter.Converter;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
import org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;

import java.util.Collections;

public class CustomJwtAuthConverter implements Converter<Jwt, AbstractAuthenticationToken> {

    private final JwtGrantedAuthoritiesConverter defaultConverter = new JwtGrantedAuthoritiesConverter();

    @Override
    public AbstractAuthenticationToken convert(Jwt jwt) {
        var authorities = defaultConverter.convert(jwt);
        // 从id_token的声明中提取用户名,这里用email示例
        String username = jwt.getClaim("email");
        return new JwtAuthenticationToken(jwt, authorities != null ? authorities : Collections.emptySet(), username);
    }
}

关键注意事项

  • 受众声明必须匹配:如果Web应用获取的id_token的aud是Web应用的客户端ID,需要在B2C用户流/自定义策略中修改id_token的aud为API的客户端ID,或者在API配置中允许多个受众(将spring.security.oauth2.resourceserver.jwt.audiences设为数组)
  • 细粒度授权处理:id_token默认不包含API权限信息,如果需要按角色/权限控制访问,可在B2C中为id_token添加自定义声明(如roles),然后在Security配置中基于这些声明做权限校验
  • 确保令牌未被篡改:Web应用必须原样转发id_token,不能修改任何内容,否则签名验证会失败
  • 自动验证核心声明:Spring Security会自动验证JWT的签名、过期时间(exp)、生效时间(nbf)等,无需手动处理

为什么user_impersonation和OBO流程不适用?

  • user_impersonation权限是用于申请access_token的前置条件,而你的场景无法获取access_token,因此该权限无效
  • OBO流程需要以access_token为输入,用于中间层API向下游API申请新的access_token,你只有id_token,不符合该流程的触发条件

内容的提问来源于stack exchange,提问作者Martinsiyo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 23:55:08