Spring OAuth2 - JWT 令牌在服务器上工作但不在本地主机上工作?

2024-05-21

我看到了myapp能够在服务器上正确处理 OAuth2 JWT 令牌,但在本地主机上给出令牌转换错误。

我的流程如下 -

在服务器上, the myapp就在我们的后面custom api-gateway

  1. 获取访问令牌- 通过邮递员,我点击了 api-gateway 令牌端点,该端点又调用了 authserver 令牌端点。我得到 OAuth JWT 令牌作为响应。

所以,总而言之,邮递员
request:--(creds)--> api-gateway --(samecreds) --> auth-server
回复:jwt 令牌

  1. 接下来,我打myapp终点- 再次通过邮递员,我点击了 api-gateway 端点,该端点又点击了相应的myapp端点。我得到了所需的回应。对于此请求,在访问 api-gateway 之前,我设置了标头Authorization: Bearer JWT from step1

As the myapp开发人员,我知道 api 网关正在将 JWT 令牌重新发送到myapp使用相同的标头机制,即Authorization: Bearer JWT from step1。从日志中,我看到这与我在邮递员中点击时提供的值相同api-gateway

因此,邮递员请求: --(jwt)--> api-gateway --(相同的 jwt)-->myapp
响应是一些数据,这对于本次讨论来说是微不足道的。

解码后的 JWT Payload 如下:

{
  "app-userId": "c54a-4140-9fa0-0f39",
  "user_name": "[email protected] /cdn-cgi/l/email-protection",
  "scope": [
    "all"
  ],
  "exp": 1656929583,
  "authorities": [
    "app1_viewer",
    "app1_modifier",
    "app2_viewer",
    "app2_blog_creator],
  "client_id": "api-gw-client"
  ...
}

请注意 -"client_id": "api-gw-client"上述有效负载中的字段。因此,身份验证服务器正在将令牌颁发给api-gateway client.


现在在 mylocal dev env 上,即myapp在本地主机上运行 - 我正在尝试实现与服务器上类似的流程。

在本地主机上,myapp 不在 api-gateway 后面运行,但它直接命中

  1. 获取访问令牌 - 通过邮递员,我点击 api-gateway (与上面的服务器流中的服务器实例相同。即 api-gateway/auth-server 不在本地主机上运行,​​而是在服务器上运行)令牌端点,该端点又调用 authserver 令牌端点。我得到 OAuth JWT 令牌作为响应。

因此,邮递员请求: --(creds)--> api-gateway --(samecreds) --> auth-server
响应:jwt token

是的,此令牌可以在服务器流步骤 2 中使用并且有效。解码后的 JWT 令牌有效负载与我之前发布的相同,即

{
  "app-userId": "c54a-4140-9fa0-0f39",
  "user_name": "[email protected] /cdn-cgi/l/email-protection",
  "scope": [
    "all"
  ],
  "exp": 1656929583,
  "authorities": [
    "app1_viewer",
    "app1_modifier",
    "app2_viewer",
    "app2_blog_creator],
  "client_id": "api-gw-client"
  ...
}

请再次注意 -"client_id": "api-gw-client"上述有效负载中的字段。因此,身份验证服务器正在将令牌颁发给api-gateway客户。我还不确定这个领域是微不足道的还是重要的。

  1. 接下来,我打myapp本地主机端点- 再次通过邮递员,但我打了myapp直接端点(不通过本地主机上运行的 api-gateway)。对于这个请求,在点击之前,我设置了标头Authorization: Bearer JWT from step1.

但这次我收到错误:

p.a.OAuth2AuthenticationProcessingFilter :身份验证请求 失败:error=“invalid_token”,error_description=“无法转换” JSON 的访问令牌”

我想知道是什么导致了这个错误。我不认为client_id: api-gw-client正在造成这种情况。无论如何,我创建了一个签名的 jwt 令牌client_id: myapp并在请求中使用它。但我仍然遇到同样的错误。
The key我在本地主机上使用的与身份验证服务器用于签名的匹配(对应)。我仔细检查了。所以它肯定不是key issue.

我需要基于 localhost 的设置工作,这样我就可以在本地测试我的 api,而无需部署到服务器(在我的情况下,部署到服务器非常耗时)。因此,这个设置对于我按时完成任务非常重要。任何答案/建议都将不胜感激。


我的项目中使用的 Spring OAuth2 库如下 -

  1. org.springframework.security:spring-security-oauth2-jose:5.4.2
  2. org.springframework.cloud:spring-cloud-starter-oauth2:2.1.3.RELEASE

给出错误的类是:OAuth2AuthenticationProcessingFilter.java https://github.com/spring-attic/spring-security-oauth/blob/main/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.java (API Doc https://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/authentication/OAuth2AuthenticationProcessingFilter.html)


抱歉,我不会回答您的问题(@Toerktumlare 是对的,您的安全配置丢失),但会尝试解释为什么我不会将 API 网关设置为 OAuth2 客户端。

简而言之,API 网关的作用是成为系统资源的黑匣子,这可以使其被视为资源服务器,但在我看来,它应该对 OAuth2(和其他身份验证机制)保持透明。保持简单:

  • clients(UI) 处理用户登录(需要时)
  • 资源服务器控制对资源的访问
  • gateway(如果有的话)应尽可能保持透明,只为所有资源提供单一入口点。

在你的场景中:

  • 如果您被要求实施多因素身份验证,您预计会发生什么情况:除了登录名/密码之外,还需要生物识别、外部应用程序验证、Goolgle 身份验证器令牌或其他内容之一?除了授权服务器之外,您真的打算在网关中实现所有这些吗?
  • 如果它总是得到api-gw-client作为客户端 ID,您的授权服务器如何实现基于客户端的处理(例如检查请求的范围对于客户端是否合法,或将客户端权限添加到访问令牌)?
  • 多租户场景怎么样(R1 and R2网关后面的资源服务器期望来自不同发行者的身份,或者C1 and C2客户端不会针对同一授权服务器对用户进行身份验证)?
  • 如果某些客户端和资源服务器使用 OAuth2 之外的其他内容怎么办?

此外,您的客户端必须知道每个 API 端点接受和生成的媒体类型(XML、JSON、PDF、多部分等)并设置Content-type and Accept相应的标题。为什么会有所不同Authorization header?

在我看来,如果你想节省时间和精力,请使用你的API网关来代理仅您的资源服务器。保留授权服务器装置。对于您不维护但您的客户需要的外部 API(如果有的话)(Tweeter feed、Google API 等)也是如此。

这就是我总是配置资源服务器的方式 https://github.com/ch4mpy/spring-addons/tree/master/samples/tutorials/resource-server_with_jwtauthenticationtoken:

  • Authorization header is missing or invalid (malformed, expired, wrong issuer, bad audience, etc.) => 401 (unauthorized) and not 302 (redirect to login)
    • 在多租户场景中,为什么资源服务器要费心去确定要重定向到哪个授权服务器?
    • 对于不在浏览器中运行的客户端(例如移动应用程序),重定向的含义是什么?
  • Authorization标头有效,但关联的声明无法通过访问控制(例如,错误的权限或不是预期的主题)=> 403(禁止)

客户端应该知道如何获取所需的访问令牌)以及如何设置Authorization发送请求时的标头(这就是您当前使用 Postman 所做的事情)。它甚至可以拦截401来触发用户身份验证,然后重试失败的资源访问。重要的 OAuth2 客户端库(例如角度身份验证 oidc 客户端 https://github.com/damienbod/angular-auth-oidc-client对于 Angular)提供了这样的功能。

有了这样的客户端,网关可以充当资源服务器(以及授权服务器或外部 API,如果您愿意的话,但为什么呢?)的外观,转发Authorization标头并完全忽略用户登录。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring OAuth2 - JWT 令牌在服务器上工作但不在本地主机上工作? 的相关文章

随机推荐