React+Spring Boot集成Azure AD:认证成功但授权失败
React+Spring Boot集成Azure AD:认证正常但授权失效问题
问题概述
搭建React前端+Spring Boot后端应用,集成Azure Active Directory实现认证授权,认证功能正常,但授权失效。
前端MSAL认证状态
前端通过MSAL实现认证,已成功获取用户账户,控制台日志无异常。令牌请求/响应关键信息:
- 请求地址:
https://login.microsoftonline.com/{XX}/oauth2/v2.0/token - 令牌核心参数:
scope: "User.Read profile openid email" token_type: "Bearer"
后端错误详情
后端返回授权失败,日志显示核心问题:资源服务器未解析出用户权限范围,Granted Authorities为空数组:
Failed to authorize filter invocation [GET /api/document/list] with attributes [hasAuthority('SCOPE_User.Read')] using AffirmativeBased [DecisionVoters=[org.springframework.security.web.access.expression.WebExpressionVoter@470b5213], AllowIfAllAbstainDecisions=false] Sending JwtAuthenticationToken [Principal=org.springframework.security.oauth2.jwt.Jwt@43ebd8ff, Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=0:0:0:0:0:0:0:1, SessionId=null], Granted Authorities=[]] to access denied handler since access is denied
后端配置信息
Spring Security配置类
@Configuration public class SecurityConfig { @Bean SecurityFilterChain web(HttpSecurity http) throws Exception { http.authorizeRequests((authorize) -> authorize .mvcMatchers("/**").hasAuthority("SCOPE_User.Read") // .permitAll() .anyRequest().authenticated()) .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); return http.build(); } }
application.properties配置
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://login.microsoftonline.com/{XX}/v2.0
问题原因与解决方案
核心原因
Azure AD v2.0版本的JWT令牌中,委派权限默认存放在scp字段(而非Spring Security默认读取的scope字段),导致权限无法被自动解析。
解决方案
1. 配置JWT权限转换器,从scp字段提取权限
添加自定义转换器,指定从scp字段读取权限并保留SCOPE_前缀,与配置中的hasAuthority匹配:
@Configuration public class SecurityConfig { @Bean SecurityFilterChain web(HttpSecurity http) throws Exception { http.authorizeRequests((authorize) -> authorize .mvcMatchers("/**").hasAuthority("SCOPE_User.Read") .anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2 .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter()))); return http.build(); } private JwtAuthenticationConverter jwtAuthenticationConverter() { JwtGrantedAuthoritiesConverter grantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter(); // 指定从scp字段提取权限 grantedAuthoritiesConverter.setAuthoritiesClaimName("scp"); // 保持SCOPE_前缀,与hasAuthority参数一致 grantedAuthoritiesConverter.setAuthorityPrefix("SCOPE_"); JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(grantedAuthoritiesConverter); return jwtAuthenticationConverter; } }
2. 验证Azure AD应用注册配置
- 确保后端应用注册已添加Microsoft Graph的User.Read委派权限,并完成管理员同意(若涉及企业账户);
- 前端MSAL请求的
scope需使用完整格式(如https://graph.microsoft.com/User.Read),避免权限字段解析异常。
3. 校验JWT令牌有效性
用JWT解析工具解码前端传递的access token,确认:
scp字段存在且包含User.Read值;aud(受众)字段匹配后端应用注册的客户端ID或API ID,受众不匹配会导致权限解析被跳过。
内容的提问来源于stack exchange,提问作者Sol
相关产品推荐
相关产品推荐

