Spring Boot集成Azure B2C与Swagger认证问题排查
问题:Swagger UI 对接 Azure AD B2C 认证报错
问题现象
- 初始报错:使用Swagger UI通过Azure B2C进行认证时,提示缺少
code_challenge参数,但无法在Azure或Swagger配置中手动添加该参数。 - 后续报错:参考Azure文档尝试添加
code_challenge后,出现新错误:AADB2C90184:提供的code_challenge_method不被支持,支持的值为plain或S256。
Swagger 配置代码
@Bean public OpenAPI openApi() { return new OpenAPI() .info(new Info() .title("API") .version("1.0.0")) .addServersItem(new Server().url("http://localhost:8080")) .components(new Components() .addSecuritySchemes("oauth2", new SecurityScheme() .type(OAUTH2) .description("Sign in with Azure AD B2C OAuth2") .flows(new OAuthFlows() .authorizationCode(new OAuthFlow() .authorizationUrl("https://costcoapp.b2clogin.com/costcoapp.onmicrosoft.com/B2C_1_signupsignin1/oauth2/v2.0/authorize") .tokenUrl("https://costcoapp.b2clogin.com/costcoapp.onmicrosoft.com/B2C_1_signupsignin1/oauth2/v2.0/token") .scopes(new Scopes() .addString("https://costcoapp.onmicrosoft.com/f342g5-5a6b-4341-a4fc-3674gr52779/read", "Read access to demo API") ) ) ) ) .addSecuritySchemes("bearerToken", new SecurityScheme() .type(HTTP) .description("Use Access Token obtained from Azure AD B2C OAuth2") .scheme("bearer") .bearerFormat("JWT") ) ); }
Security 配置代码
@Configuration @EnableMethodSecurity @RequiredArgsConstructor public class SecurityConfiguration { private final AadB2cOidcLoginConfigurer configurer; private final JwtClaimResolver jwtClaimResolver; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeRequests(config -> config .requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll() .anyRequest().authenticated()) .oauth2ResourceServer(config -> config .jwt() .jwtAuthenticationConverter(jwtAuthenticationConverter())) .formLogin(AbstractHttpConfigurer::disable) .logout(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable) .httpBasic(AbstractHttpConfigurer::disable); http.sessionManagement($ -> $.sessionCreationPolicy(STATELESS)); http.apply(configurer); return http.build(); } private JwtAuthenticationConverter jwtAuthenticationConverter() { JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwt -> jwtClaimResolver.getUserGroups(jwt) .stream() .map(this::mapToGrantedAuthority) .toList()); return jwtAuthenticationConverter; } private GrantedAuthority mapToGrantedAuthority(String userGroup) { return new SimpleGrantedAuthority("ROLE_" + userGroup); } }
application.yaml 配置代码
spring: cloud: azure: active-directory: b2c: enabled: true profile: tenant-id: <my-tenant-id> credential: client-id: <my-client-id> client-secret: <my-secret> base-uri: https://costcoapp.b2clogin.com/costcoapp.onmicrosoft.com user-flows: sign-up-or-sign-in: B2C_1_signupsignin1 springdoc: api-docs: enabled: true swagger-ui: oauth: client-id: <my-client-id> client-secret: <my-secret> oauth2-redirect-url: http://localhost:8080/swagger-ui/oauth2-redirect.html
更新:尝试添加 code_challenge 的代码
@SneakyThrows private String generateChallenge() { SecureRandom secureRandom = new SecureRandom(); int cvLength = secureRandom.nextInt(85) + 43; String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"; StringBuilder codeVerifier = new StringBuilder(cvLength); for (int i = 0; i < cvLength; i++) { codeVerifier.append(chars.charAt(secureRandom.nextInt(chars.length()))); } MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] encodedHash = digest.digest(codeVerifier.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8)); return Base64.getUrlEncoder().withoutPadding().encodeToString(encodedHash); } @SneakyThrows private URL buildAuthUrl() { String challenge = generateChallenge(); String baseUrl = "https://costcoapp.b2clogin.com/costcoapp.onmicrosoft.com/b2c_1_signupsignin1/oauth2/v2.0/authorize"; UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(baseUrl) .queryParam("client_id", "f342g5-5a6b-4341-a4fc-3674gr52779") .queryParam("response_type", "code") .queryParam("redirect_uri", "http://localhost:8080/swagger-ui/oauth2-redirect.html") .queryParam("response_mode", "query") .queryParam("scope", "openid") .queryParam("code_challenge", challenge) .queryParam("code_challenge_method", "plain"); return uriBuilder.build().toUri().toURL(); }
内容的提问来源于stack exchange,提问作者Danil Tk
相关产品推荐
相关产品推荐

