Spring Cloud Gateway集成微软OAuth2:自定义Scope与/userinfo兼容问题
解决Spring Cloud API Gateway + Microsoft OAuth2同时获取openid与自定义Scope的问题
问题背景
使用Spring Cloud API Gateway结合Microsoft OAuth2开发时,遇到矛盾场景:
- 调用
/userinfo端点必须携带openidscope,但同时配置openid和自定义custom-scope时,授权请求被Microsoft拒绝; - 仅保留
custom-scope,/userinfo调用会因权限不足失败。
解决方案
1. 检查Microsoft Azure AD应用权限配置
- 登录Azure门户,进入目标应用注册页面,依次进入「API权限」→「添加权限」:
- 先添加Microsoft Graph的委派权限
openid; - 再添加自定义API的
custom-scope权限,确保权限状态为「已授予管理员同意」(租户内应用需完成此步骤);
- 先添加Microsoft Graph的委派权限
- 注意:自定义scope必须是Azure AD中已注册的有效权限,不能随意填写。
2. 修改Spring Cloud Gateway OAuth2配置
同时配置openid和自定义scope,并完善Microsoft提供商的端点配置:
# Spring Cloud API Gateway OAuth2 client settings spring: security: oauth2: client: registration: my-client: provider: microsoft client-id: xxx client-secret: xxx authorization-grant-type: authorization_code redirect-uri: http://localhost:8080/login/oauth2/code/my-client scope: openid, custom-scope # 同时包含两个scope provider: microsoft: authorization-uri: https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/authorize token-uri: https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token user-info-uri: https://graph.microsoft.com/oidc/userinfo user-name-attribute: sub
替换
{tenant-id}为你的Azure AD租户ID,确保redirect-uri与Azure应用注册中配置的地址完全一致。
3. 自定义OAuth2令牌请求处理器(可选)
若仍存在请求被拒绝的情况,可自定义令牌请求客户端,确保scope参数正确传递:
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeTokenResponseClient; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; public class CustomTokenResponseClient implements OAuth2AuthorizationCodeTokenResponseClient { private final DefaultAuthorizationCodeTokenResponseClient delegate = new DefaultAuthorizationCodeTokenResponseClient(); @Override public OAuth2AccessTokenResponse getTokenResponse(OAuth2AuthorizationCodeGrantRequest authorizationCodeGrantRequest) { MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>(authorizationCodeGrantRequest.getAdditionalParameters()); parameters.put(OAuth2ParameterNames.SCOPE, authorizationCodeGrantRequest.getClientRegistration().getScopes()); OAuth2AuthorizationCodeGrantRequest customRequest = new OAuth2AuthorizationCodeGrantRequest( authorizationCodeGrantRequest.getClientRegistration(), authorizationCodeGrantRequest.getAuthorizationExchange(), parameters ); return delegate.getTokenResponse(customRequest); } }
在配置类中注册该客户端:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeTokenResponseClient; @Configuration public class OAuth2ClientConfig { @Bean public OAuth2AuthorizationCodeTokenResponseClient customTokenResponseClient() { return new CustomTokenResponseClient(); } }
4. 验证结果
获取令牌后,通过JWT解析工具(如jwt.io)检查令牌的scope字段,确认同时包含openid和custom-scope;同时验证/userinfo调用正常返回用户信息,自定义API可通过该令牌完成认证。
内容的提问来源于stack exchange,提问作者user5228754
相关产品推荐
相关产品推荐

