ADFS是否有Token校验端点?Spring OAuth2集成问题咨询
嘿,我正好之前做过Spring OAuth2和ADFS的集成,碰到过一模一样的问题,给你捋捋解决方案:
你之前用的https://adfs.local/adfs/oauth2/check_token是错的,ADFS遵循OAuth2 Token Introspection规范,对应的端点是:https://adfs.local/adfs/oauth2/introspect
不过要注意,这个端点默认可能没启用,得去ADFS管理控制台开一下:
- 打开ADFS管理工具,依次点服务 -> OAuth -> 端点
- 在端点列表里找到
/adfs/oauth2/introspect,右键启用它(如果本来就是启用状态就忽略)
调用这个端点的规则也得注意:
- 必须用POST请求
- 要带上客户端凭证(client_id和client_secret),ADFS支持Basic Auth或者表单参数两种方式
- 请求里必须传
token参数,值就是你要校验的AccessToken或者RefreshToken
把你的security.oauth2.resource.token-info-uri改成正确的端点:
security.oauth2.resource.token-info-uri= https://adfs.local/adfs/oauth2/introspect
另外,ADFS对客户端认证的偏好是Basic Auth,所以建议把clientAuthenticationScheme改成basic,避免踩坑:
security.oauth2.client.clientAuthenticationScheme=basic
ADFS的introspect端点确实不返回OAuth2规范要求的active字段,这是它的一个“特色”。我们得在Spring这边做个适配,自定义一个TokenIntrospector来补上这个字段:
先写一个兼容ADFS的TokenIntrospector实现:
import org.springframework.security.oauth2.provider.token.DefaultTokenIntrospector; import org.springframework.security.oauth2.provider.token.TokenIntrospector; import java.util.Map; public class ADFSCompatibleTokenIntrospector implements TokenIntrospector { private final DefaultTokenIntrospector delegate = new DefaultTokenIntrospector(); @Override public Map<String, Object> introspect(String token) { Map<String, Object> result = delegate.introspect(token); // 如果ADFS没返回active字段,根据结果是否为空判断token有效性 if (!result.containsKey("active")) { // 结果非空说明token有效,设置active为true;空的话就是无效 result.put("active", !result.isEmpty()); } return result; } }
然后在你的资源服务器配置里注册这个自定义的Bean:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.token.TokenIntrospector; @Configuration public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { // 替换默认的TokenIntrospector为我们自定义的 resources.tokenIntrospector(adfsTokenIntrospector()); } @Bean public TokenIntrospector adfsTokenIntrospector() { return new ADFSCompatibleTokenIntrospector(); } }
你自己写的/oauth/check_token是完全符合OAuth2规范的(主动返回了active字段),但ADFS的实现没跟上规范,所以必须做这个适配。另外,ADFS返回的用户信息字段可能和你自己的Auth Server不一样,比如用户ID可能在sub字段或者其他ADFS自定义字段里,你可能需要根据实际返回的JSON结构调整Spring的用户信息转换器。
内容的提问来源于stack exchange,提问作者Zach Pham

