rest - HTTP API : Communicating the need to authenticate to a third party

标签 rest http oauth restful-authentication api-design

我正在开发一个包含第三方集成的 RESTful API。我们将 OAuth 与授权代码流结合使用以针对第三方进行身份验证。用户必须登录我们的服务,然后再登录第三方,以便我们的应用程序可以访问第三方。

我们的一些资源需要与第三方交互才能完成(比如 GET/third-party-userpic)。如果用户已经登录到该服务,我们将从我们的数据存储中检索访问 token 并使用它来检索用户的图片,很简单!

但是,如果我们不持有该用户使用该服务的有效凭据,我们就无法获取该用户的照片。这将在首次使用时发生,如果凭据过期或被撤销也可能发生。在这种情况下,我们希望与客户端沟通他们需要访问授权 URI 并开始 OAuth 流程。

我和我设计这个的同事讨论了几种可能性,包括:

  • 返回 200 OK 成功,并指示响应正文中需要或允许以某种方式进行身份验证。这是不优雅的,不能很好地扩展到不同内容类型的资源,并且要求客户端知道它何时访问可能需要此身份验证方案的资源。
  • 返回 403 Forbidden 以及用于在 header 或正文中进行身份验证的链接。问题在于,这需要与由于权限问题而生成的 403 Forbidden 区分开来,感觉与我们想要的 403 的含义不符。
  • 返回 401 Unauthorized。这有同样的问题要求客户端将其与用户未登录时我们平台生成的 401 分开。还有一个额外的问题是 401 Unauthorized是 HTTP 质询-响应身份验证方案的一部分,但我们并未在此处实现质询-响应流程。客户端永远不会触及凭据。
  • 创建一个新的 4XX 状态代码,以允许客户端轻松地将这种情况与其他可能的故障区分开来。从技术角度来看,这似乎是最干净的,但制作新的状态代码并不是我们可能需要做的事情!

最佳答案

开始:我发现很难相信显示用户图片是一个关键组成部分,所以我认为这比用户被谴责为由默认头像代表的后果更大。

在这种情况下,2xx 级响应代码几乎是不可能的,因为操作没有成功。虽然服务器端的机制失败了,但客户端有机会纠正这个问题(通过 OAuth 进行身份验证)。这排除了 5xx 类状态代码,建议使用 4xx 类。

正如您正确断言的那样,401 不太正确,因为此代码特定于所请求的资源。来自 RFC 7235, section 3.1 :

The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource.

但是,您的目标资源没问题;这是一个麻烦的外部服务。除此之外,401 将带您进入 HTTP 身份验证框架的核心,它引入了许多实际问题。

这个范围内最合适的状态码确实是403。来自RFC 7231, section 6.5.1 :

The 403 (Forbidden) status code indicates that the server understood the request but refuses to authorize it. A server that wishes to make public why the request has been forbidden can describe that reason in the response payload (if any).

虽然一开始这听起来可能无关紧要,但考虑一下

[...] a request might be forbidden for reasons unrelated to the credentials.

RFC 还写道:

The client MAY repeat the request with new or different credentials.

所以这段代码很宽松,因为它不是特定于所请求的资源,而是很好地考虑了阻止成功操作的其他情况。当您按照 Choosing an HTTP Status Code — Stop Making It Hard 上的流程图​​操作时,这也是您将获得的响应代码。 .

关于rest - HTTP API : Communicating the need to authenticate to a third party,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37080391/

相关文章:

android - 使用 Android AccountManager 进行第三方 OAuth2 授权

c# - 为什么 WebInvoke 不允许此方法,但 WebGet 可以?

java - 使用简单的 spring-data-rest 项目获取 404 错误

ruby - HttpGenericRequest 中 body 与 body_stream 的区别

http - 为什么传输编码 :Chunked sent instead of Content-Encoding:gzip for some of clients?

.net - 如何在没有 ShowDialog() 的情况下等待表单关闭?

c# - 是否可以或有必要设置ServiceStack客户端删除请求的内容类型?

java - 使用 Java REST API 接收两次相同的参数名称

javascript - Angular 的 $http 中返回的 Promise 与普通 Javascript (ES6) 中返回的 Promise 相同吗?

php - 将 Google OAuth API 与现有用户系统集成?