问题描述
我不知道应该通过Access_Token还是id_Token访问我的Spring Boot资源服务器。
首先,让我快速解释一下我的设置:
- 作为OAuth 2.0 Resource Server的Spring Boot应用程序。这是按照Spring文档中所述进行配置的:Minimal Configuration for JWTs这个应用程序提供了安全的@控制器,这些控制器将为一个JavaScript SPA(例如.反应)
- Google的OAuth 2.0 AP / OpenID Connect已配置(凭据、客户端ID、客户端密码)
- 一款JavaScript SPA应用程序(例如Reaction),它将用户登录到Google,并向Spring Boot资源服务器请求安全数据。这些请求包括登录用户的授权标头(带有从Google获得的持有者令牌)。
- 出于开发目的,我还使用Postman向Spring Boot资源服务器发出请求
我可以轻松地将Postman配置为从Google获取令牌。来自Google的此令牌响应包括access_token
、id_token
、scope
、expries_in
和token_type
的值。
但是,当邮递员尝试使用检索到的令牌的access_token
字段中的值作为授权标头中的承载时,我对资源服务器的请求被拒绝
我能够成功访问安全@Controllers
的唯一方法是使用id_token
作为授权标头中的持有者。
id_token
作为授权标头中的持有者?还是应该使用access_token
?其他相关信息:
id_token
的值是JWT标记。access_token
的值不是JWT标记。我知道这一点是因为我可以解码jwt.io上的id_token
,但它无法解码access_token
的值。此外,当我将access_token
作为授权标头中的持有者发送时,Spring Boot资源服务器失败,出现以下错误:
- 这篇博文Understanding identity tokens内容如下:
- 查看使用OAuth2资源服务器的spring-security-samples,我看到硬编码的
access_token
的值(出于测试目的)确实是有效的JWT。而不是从不是JWT的Google返回的access_token
。
小结:
- 我可以使用从Google获得的
id_token
的值访问我的Spring Boot资源服务器。access_token
的值不是JWT,无法通过Spring Boot进行分析。 - 是我的理解、我的配置有问题还是什么?关于
access_token
的工作方式,Google的OpenID Connect的行为是否有所不同?
如果需要,很乐意澄清或添加更多信息。感谢您的考虑和耐心!
推荐答案
您提到的博客文章在我看来是正确的,我相信OpenID Connect1.0规范并不打算将id_token
用于访问目的。
像您一样,我希望使用Google作为授权服务器可以开箱即用,因为Spring Security与Google作为一个公共的OAuth2提供者一起工作,以提供社交登录。然而,情况并非如此,我相信这并不是真正的意图,因为谷歌并不是你的授权服务器。例如,我不相信您可以将Google配置为使用您的域特定应用程序的作用域/权限/授权。这不同于Okta,后者有许多选项可以在您自己的租户中配置内容。
我实际上建议您查看Spring Authorization Server,并将Google配置为联合身份提供商。我目前正在制作一个样本,将在下周左右发布(请参阅this branch)。
话虽如此,如果您仍然对使用Google访问令牌进行资源服务器身份验证的简单用例感兴趣,则需要提供使用Google的tokeninfo endpoint的您自己的opaque token introspector。它与Spring Security所期望的不符,因此有点牵涉其中。
@EnableWebSecurity
public class SecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
http
.authorizeRequests((authorizeRequests) -> authorizeRequests
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::opaqueToken);
// @formatter:on
return http.build();
}
@Bean
public OpaqueTokenIntrospector introspector() {
return new GoogleTokenIntrospector("https://oauth2.googleapis.com/tokeninfo");
}
}
public final class GoogleTokenIntrospector implements OpaqueTokenIntrospector {
private final RestTemplate restTemplate = new RestTemplate();
private final String introspectionUri;
public GoogleTokenIntrospector(String introspectionUri) {
this.introspectionUri = introspectionUri;
}
@Override
public OAuth2AuthenticatedPrincipal introspect(String token) {
RequestEntity<?> requestEntity = buildRequest(token);
try {
ResponseEntity<Map<String, Object>> responseEntity = this.restTemplate.exchange(requestEntity, new ParameterizedTypeReference<>() {});
// TODO: Create and return OAuth2IntrospectionAuthenticatedPrincipal based on response...
} catch (Exception ex) {
throw new BadOpaqueTokenException(ex.getMessage(), ex);
}
}
private RequestEntity<?> buildRequest(String token) {
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("access_token", token);
return new RequestEntity<>(body, headers, HttpMethod.POST, URI.create(introspectionUri));
}
}
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://accounts.google.com
jwk-set-uri: https://www.googleapis.com/oauth2/v3/certs
这篇关于Spring Boot授权服务器+Google OAuth2/OpenID Connect应该与Access_Token或id_Token一起工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!