OAuth2 重定向失败并出现 CORS 错误
OAuth2 redirection fails with CORS error
我有一个 RESTful 服务,我使用 Spring Security
和 pac4j-oauth
保护了它。一个重要的细节是 Google 作为 OAuth2
服务器——我们需要用户的 Gmail 地址来知道他们是否是我们系统的合法用户,最终该服务还需要访问他们的日历。
当用户第一次访问受保护的资源(输入 URL)时,他们会被重定向到 Google。一旦他们通过身份验证,他们就会被重定向回我们的服务。这很好用。
问题是我想使用 Ajax
调用服务。当我发出第一个 Ajax
调用时,它返回到 Google 的重定向。这可能会弄乱 Ajax
调用,但实际上它甚至没有那么远。浏览器看到重定向并抛出 CORS
错误:"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:8443' is therefore not allowed access."
我不知道该如何处理。欢迎提出建议。
一些想法:
如果我用 JSONP
调用替换常规 Ajax
调用,重定向仍然会导致错误(因为它 returns 一个 URL而不是 JSONP
脚本)但也许客户端可以检测到它并代表服务导航到 Google?一旦用户通过身份验证,客户端就可以再次将他们带回受保护的资源?
虽然这感觉不对。一方面,这意味着 RESTful 服务的未来 Ajax
客户将不得不经历同样的困境。我希望客户端不依赖于服务器的安全实现。
虽然 CORS
错误很常见,但我只发现其他几个人专门抱怨 OAuth2
身份验证。所以我也想知道我们的架构是否在某个地方走错了路。我们究竟在做什么,如此不寻常?
如有任何见解,我们将不胜感激。
经过更多调查,这是我的结论。
我先从#2 开始。是的,我们可能走错了路。具体来说,OAuth2
是为 授权 而设计的,而不是身份验证。 (虽然如果我们是 运行 我们自己的 OAuth2
服务器,我们可能已经摆脱了它。)
Google 当然支持身份验证:请参阅 Google Sign-In 的文档。但请注意他们列出的两个选项。
- 将其编码到客户端中。这不适用于
RESTful
服务。
- One-time authorization code flow。此选项对于 RESTful 服务非常有意义。但同样,它并不是要对用户进行身份验证;这是关于让用户授权我们的服务访问他们的日历。而且他们只需要这样做一次。
所以计划是我们将有一个网页提供选项来授权我们的服务访问他们的 Google 日历。用户将明确单击 link 以获得来自 Google 的授权——RESTful
服务不需要重定向他们的浏览器。这避免了 CORS
问题。然后客户端将 post Google 的访问令牌访问我们的 RESTful
服务。
请注意,我们服务的其他消费者不需要实现这一点,他们只需要让用户以不需要重定向到第三方的方式进行身份验证。最初我们将使用我们自己的 user/pwd 数据库,着眼于将来连接到公司目录或 SSO
。 Spring Security
当然支持很多选项。
所以:我们不得不妥协我们最初的计划,但现在我们正在处理有据可查且有示例代码的流程。所以我希望从现在开始事情会更顺利。
我希望这可以帮助其他人避免我们所犯的相同 OAuth2
设计错误,即与第三方一起使用它来验证我们 RESTful
服务的用户。有更合适的方法来验证用户。
我有一个 RESTful 服务,我使用 Spring Security
和 pac4j-oauth
保护了它。一个重要的细节是 Google 作为 OAuth2
服务器——我们需要用户的 Gmail 地址来知道他们是否是我们系统的合法用户,最终该服务还需要访问他们的日历。
当用户第一次访问受保护的资源(输入 URL)时,他们会被重定向到 Google。一旦他们通过身份验证,他们就会被重定向回我们的服务。这很好用。
问题是我想使用 Ajax
调用服务。当我发出第一个 Ajax
调用时,它返回到 Google 的重定向。这可能会弄乱 Ajax
调用,但实际上它甚至没有那么远。浏览器看到重定向并抛出 CORS
错误:"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://localhost:8443' is therefore not allowed access."
我不知道该如何处理。欢迎提出建议。
一些想法:
如果我用
JSONP
调用替换常规Ajax
调用,重定向仍然会导致错误(因为它 returns 一个 URL而不是JSONP
脚本)但也许客户端可以检测到它并代表服务导航到 Google?一旦用户通过身份验证,客户端就可以再次将他们带回受保护的资源?虽然这感觉不对。一方面,这意味着 RESTful 服务的未来
Ajax
客户将不得不经历同样的困境。我希望客户端不依赖于服务器的安全实现。虽然
CORS
错误很常见,但我只发现其他几个人专门抱怨OAuth2
身份验证。所以我也想知道我们的架构是否在某个地方走错了路。我们究竟在做什么,如此不寻常?
如有任何见解,我们将不胜感激。
经过更多调查,这是我的结论。
我先从#2 开始。是的,我们可能走错了路。具体来说,OAuth2
是为 授权 而设计的,而不是身份验证。 (虽然如果我们是 运行 我们自己的 OAuth2
服务器,我们可能已经摆脱了它。)
Google 当然支持身份验证:请参阅 Google Sign-In 的文档。但请注意他们列出的两个选项。
- 将其编码到客户端中。这不适用于
RESTful
服务。 - One-time authorization code flow。此选项对于 RESTful 服务非常有意义。但同样,它并不是要对用户进行身份验证;这是关于让用户授权我们的服务访问他们的日历。而且他们只需要这样做一次。
所以计划是我们将有一个网页提供选项来授权我们的服务访问他们的 Google 日历。用户将明确单击 link 以获得来自 Google 的授权——RESTful
服务不需要重定向他们的浏览器。这避免了 CORS
问题。然后客户端将 post Google 的访问令牌访问我们的 RESTful
服务。
请注意,我们服务的其他消费者不需要实现这一点,他们只需要让用户以不需要重定向到第三方的方式进行身份验证。最初我们将使用我们自己的 user/pwd 数据库,着眼于将来连接到公司目录或 SSO
。 Spring Security
当然支持很多选项。
所以:我们不得不妥协我们最初的计划,但现在我们正在处理有据可查且有示例代码的流程。所以我希望从现在开始事情会更顺利。
我希望这可以帮助其他人避免我们所犯的相同 OAuth2
设计错误,即与第三方一起使用它来验证我们 RESTful
服务的用户。有更合适的方法来验证用户。