我对于是否应该通过 access_token 还是 id_token 访问我的 Spring Boot 资源服务器有点困惑。
首先,让我快速解释一下我的设置:
- Spring Boot 应用程序作为 OAuth 2.0 资源服务器。这是按照 Spring 文档中所述进行配置的: JWT 的最小配置 此应用提供安全的 @Controller,将为 JavaScript SPA(例如 React)
- Google 的 OAuth 2.0 AP / OpenID Connect 已配置(凭据、客户端 ID、客户端密钥)
- JavaScript SPA 应用程序(例如 React)将用户登录到 Google 并向 Spring Boot 资源服务器发出请求以获取安全数据。这些请求包括登录用户的授权标头(带有从 Google 获取的不记名令牌)。
- 出于开发目的,我还使用 Postman 向 Spring Boot 资源服务器发出请求,
我可以轻松配置 Postman 以从 Google 获取令牌。来自 Google 的此令牌响应包括 access_token
、id_token
、scope
、expries_in
和 token_type
的值代码>.
但是,当 Postman 尝试使用检索到的令牌的 access_token
字段中的值作为授权标头中的承载时,我对资源服务器的请求被拒绝
这是我能够成功访问安全的唯一方法>@Controllers
是通过使用 id_token
作为 Authorization 标头中的 Bearer 来实现的。
我是否应该使用 id_token 作为授权标头中的承载者?或者我应该使用access_token
?
一些其他相关信息:
-
id_token
的值是 JWT 令牌。 access_token
的值不是 JWT 令牌。我知道这一点是因为我可以解码 jwt.io 上的 id_token
但它无法解码access_token
的值。此外,当我将 access_token
作为 Authorization 标头中的 Bearer 发送时,Spring Boot 资源服务器会失败并出现以下错误:
尝试解码 Jwt 时发生错误:无效的不安全/JWS/JWE 标头:无效的 JSON:位置 2 处出现意外的令牌 ɭ�。
您不应使用身份令牌来授权对 API 的访问。
要访问 API,您应该使用 OAuth 的访问令牌,该令牌仅适用于受保护的资源 (API),并且内置范围界定。
- 查看 spring-security-samples 对于使用 OAuth2 资源服务器,我看到硬编码的
access_token
的值(用于测试目的)确实是一个有效的 JWT。与从 Google 返回的 access_token
相反,它不是 JWT。
总之:
- 我可以使用从 Google 获取的 id_token 值来访问我的 Spring Boot 资源服务器。
access_token
的值不是 JWT,Spring Boot 无法解析。
- 是我的理解有问题,还是我的配置有问题? Google 的 OpenId Connect 在
access_token
的工作方式方面是否有不同的行为?
如果需要,很乐意澄清或添加更多信息。感谢您的考虑和耐心!
I'm a bit confused regarding whether I should be accessing my Spring Boot Resource Server via an access_token or an id_token.
First, let me quickly explain my setup:
- Spring Boot app as an OAuth 2.0 Resource Server. This is configured as described in the Spring docs: Minimal Configuration for JWTs This app provides secured @Controllers that will provide data for a JavaScript SPA (eg. React)
- Google's OAuth 2.0 AP / OpenID Connect already configured (Credentials, Client Id, Client Secret)
- A JavaScript SPA app (eg. React) that logs the user into Google and makes requests to the Spring Boot Resource Server for secured data. These requests include the Authorization header (with Bearer token obtained from Google) for the logged in user.
- For development purposes, I'm also using Postman to make requests to the Spring Boot Resource Server
I can easily configure Postman to get a token from Google. This token response from Google includes values for access_token
, id_token
, scope
, expries_in
and token_type
.
However, my requests to the Resource Server are denied when Postman tries to use the value from retrieved token's access_token
field as the Bearer in the Authorization header
The only way I'm able to successfully access the secured @Controllers
is by using the id_token
as the Bearer in the Authorization header.
Is it expected that I should use the id_token
as the Bearer in the Authorization header? Or is it expected that I should use the access_token
?
Some additional relevant info:
- The value of the
id_token
is a JWT token. The value of the access_token
is not a JWT token. I know this because I can decode the id_token
on jwt.io but it is unable to decode the value of the access_token
. Further, the Spring Boot Resource Server fails with the following when I send the access_token
as the Bearer in the Authorization header:
An error occurred while attempting to decode the Jwt: Invalid unsecured/JWS/JWE header: Invalid JSON: Unexpected token ɭ� at position 2.
You should not use an identity token to authorize access to an API.
To access an API, you should be using OAuth’s access tokens, which are intended only for the protected resource (API) and come with scoping built-in.
- Looking at at the spring-security-samples for using OAuth2 Resource Server, I see the value of there hard-coded
access_token
(for testing purposes) is indeed a valid JWT. As opposed to the access_token
returned from Google which is not a JWT.
In summary:
- I can access my Spring Boot Resource Server using the value of the
id_token
obtained from Google. The value of the access_token
is not a JWT and fails to parse by Spring Boot.
- Is there something wrong with my understanding, my configuration or what? Does Google's OpenId Connect behave differently regarding how the
access_token
works?
Happy to clarify or add more info if needed. Thanks for your consideration and your patience!
发布评论
评论(1)
在我看来,您提到的博客文章是正确的,并且我相信 OpenID Connect 1.0 规范并不打算将 id_token 用于访问目的。
和您一样,我预计使用 Google 作为授权服务器可以开箱即用,因为 Spring Security 与 Google 一起作为公共 OAuth2 提供者来提供社交登录。然而,事实并非如此,而且我相信这并不是真正的意图,因为 Google 并不是真正的您的授权服务器。例如,我不相信您可以将 Google 配置为使用特定于域的应用程序的范围/权限/权限。这与 Okta 之类的东西不同,Okta 中有很多用于在您自己的租户中配置事物的选项。
我实际上建议查看 Spring 授权服务器,并将 Google 配置为联合服务器身份提供者。我目前正在为此编写一个示例,它将在下周左右发布(更新:现在包含在 官方示例)。
话虽如此,如果您仍然对使用 Google 访问令牌对资源服务器进行身份验证的简单用例感兴趣,则需要提供自己的 不透明令牌使用 Google 的 的内省器 tokeninfo 端点。它与 Spring Security 所期望的不符,所以有点牵扯。
The blog post you mentioned is correct in my view, and I believe the OpenID Connect 1.0 spec does not intend for an
id_token
to be used for access purposes.Like you, I expected that using Google as an Authorization Server would work out of the box, because Spring Security works with Google as a common OAuth2 provider for providing social login. However, this is not the case, and I believe it is not really intended, because Google is not really your authorization server. For example, I don't believe you can configure Google to work with scopes/permissions/authorities of your domain-specific application. This is different from something like Okta, where there are many options for configuring things in your own tenant.
I would actually recommend checking out Spring Authorization Server, and configuring Google as a federated identity provider. I'm working on a sample for this currently and it will be published within the next week or so (update: now contained in the official sample).
Having said that, if you're still interested in a simple use case where Google access tokens are used for authenticating with your resource server, you would need to provide your own opaque token introspector that uses Google's tokeninfo endpoint. It doesn't match what Spring Security expects, so it's a bit involved.