我正在开发包含第三方集成的RESTful API。我们使用OAuth和授权代码流来对第三方进行身份验证。用户必须登录我们的服务,然后再登录第三方,以便我们的应用程序可以访问第三方。
我们的一些资源需要与第三方进行互动才能完成(比如GET /third-party-userpic
)。如果用户已经登录到该服务,我们将从数据存储中检索访问令牌并使用它来检索用户的图片,这很容易!
但是,如果我们没有为该服务保留该用户的有效凭据,则无法获取用户的图片。这将在首次使用时发生,如果凭据过期或被撤销,也可能发生。在这种情况下,我们希望与客户端进行通信,告知他们需要访问授权URI并开始OAuth流程。
我和我的同事们设计了这个可能性,包括:
200 OK
成功,并在某种程度上指示响应正文中需要或允许身份验证。这是不优雅的,并且不能很好地扩展到不同内容类型的资源,并且要求客户端知道它何时访问可能需要此认证方案的资源。403 Forbidden
以及在标题或正文中进行身份验证的链接。问题是,这需要区别于由于权限问题而生成的403 Forbidden
,并且与我们想要403
的含义不符。401 Unauthorized
。这有一个问题,即当用户未登录时,要求客户端将其与我们平台生成的401
区分开来。还有一个问题401 Unauthorized
是HTTP挑战的一部分 - 响应认证方案,但我们没有在此处实施质询 - 响应流程。客户从不接触凭证。4XX
状态代码,以允许客户端轻松地将此条件与其他可能的故障分开。从技术角度来看,这似乎是最干净的,但制作新的状态代码并不是我们可能需要做的事情!答案 0 :(得分:1)
要开始这样做:我发现很难相信显示用户图片是一个关键组件,所以我认为有一个更严重的后果,而不是用户被谴责为默认头像代表。
在这种情况下,由于动作尚未成功,因此2xx级响应代码几乎无法解决。虽然服务器端有一种机制失败,但客户端有机会纠正此问题(通过OAuth进行身份验证)。这排除了5xx级状态代码,建议使用4xx级。
正确断言,401不太正确,因为此代码特定于所请求的资源。来自RFC 7235, section 3.1:
401(未授权)状态代码表示该请求尚未应用,因为它缺少目标资源的有效身份验证凭据 。
但是,您的案例中的目标资源很好;这是一个很麻烦的外部服务。除此之外,401将您带入HTTP身份验证框架的核心,该框架引入了许多实际问题。
此范围内最合适的状态代码确实是403.来自RFC 7231, section 6.5.1:
403(禁止)状态代码表示服务器理解请求但拒绝授权。希望公开请求被禁止的服务器可以在响应有效负载中描述该原因(如果有的话)。
虽然这听起来可能没有关系,但请考虑
[...]可能会因与凭证无关的原因而禁止请求。
RFC也读取:
客户端可以使用新的或不同的凭据重复请求。
因此,这个代码是放宽的,因为它不是特定于所请求的资源,而是考虑其他情况,这会妨碍成功运行。这也是您按照Choosing an HTTP Status Code — Stop Making It Hard上的流程图获得的响应代码。
答案 1 :(得分:0)
https://tools.ietf.org/html/rfc6750建议遵循的内容:
<强> insufficient_scope 强> 该请求需要比提供的更高的权限 访问令牌。资源服务器应该应该使用HTTP进行响应 403(禁止)状态代码和MAY包括“范围” 具有访问受保护的必要范围的属性 资源。
WWW-Authenticate: Bearer realm="myprotectedresource",
error="insufficient_scope",
error_description="Insufficient scope for this resource scopes", scope="SOME_SCOPE"
以下是来自同一来源的授权流程图
+--------+ +---------------+
| |--(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)-- Authorization Grant ---| |
| | +---------------+
| |
| | +---------------+
| |--(C)-- Authorization Grant -->| Authorization |
| Client | | Server |
| |<-(D)----- Access Token -------| |
| | +---------------+
| |
| | +---------------+
| |--(E)----- Access Token ------>| Resource |
| | | Server |
| |<-(F)--- Protected Resource ---| |
+--------+ +---------------+
答案 2 :(得分:0)
指示响应正文中需要或允许的身份验证
我认为这很大程度上取决于“必需”与“允许”:您是否可以成功完成请求,只有部分结果丢失?
如果你能(并且想要),可能是这样的:
HTTP/1.1 200 OK
Date: Tue, 10 May 2016 01:08:07 GMT
Content-Type: application/vnd.whatever+json
Link: <https://third-party.example/authorize>;
rel="https://example.com/doc/#authorize-3rd-party"
Warning: 299 - "part of the content is missing; authorize with third party"
...content with only the pic missing...
如果您不能(或不想),那么424 (Failed Dependency),403 (Forbidden)(但请参阅评论)和400 (Bad Request)听起来都可能是合适的状态代码。但是,状态代码不是解决所有问题的方法。在响应有效载荷中细化它们的含义是完全正常的。甚至还有一个新标准 - RFC 7807:
HTTP/1.1 400 Bad Request
Date: Tue, 10 May 2016 01:08:07 GMT
Content-Type: application/problem+json
{
"type": "https://example.com/doc/#authorize-3rd-party",
"title": "You need to authorize with a third party for this.",
"authorizeAt": "https://third-party.example/authorize"
}
你对401(未经授权)和发明自己的状态代码的疑虑非常正确。