授权响应 The Authorization Response
一旦用户完成登录并批准请求,授权服务器就准备好将用户重定向回应用程序。
授权码响应
如果请求有效且用户同意授权请求,授权服务器将生成授权代码并将用户重定向回应用程序,将授权代码和应用程序的“状态”值添加到重定向 URL。
生成授权码
授权码必须在发出后不久过期。OAuth 2.0 规范建议最长生命周期为 10 分钟,但实际上,大多数服务将到期时间设置得更短,大约 30-60 秒。授权代码本身可以是任意长度,但应该记录代码的长度。
因为授权代码是短期的和一次性使用的,所以您可以将它们实现为自编码令牌。使用这种技术,您可以避免将授权代码存储在数据库中,而是将所有必要的信息编码到授权代码本身中。您可以使用服务器端环境的内置加密库,也可以使用 JSON Web 签名 (JWS) 等标准。但是,由于此授权代码仅供授权服务器使用,因此通常可以更简单地将它们实现为存储在授权端点和令牌端点可访问的服务器端缓存中的短字符串。
在任何情况下,需要与授权代码相关联的信息如下。
client_id
– 请求此代码的客户端 ID(或其他客户端标识符)redirect_uri
– 使用的重定向 URL。这需要存储,因为访问令牌请求必须包含相同的重定向 URL,以便在发布访问令牌时进行验证。- 用户信息——识别此授权代码所针对的用户的某种方式,例如用户 ID。
- 过期日期——代码需要包含一个过期日期,这样它只会持续很短的时间。
- 唯一 ID – 代码需要自己的某种唯一 ID,以便能够检查该代码之前是否被使用过。数据库 ID 或随机字符串就足够了。
- PKCE:
code_challenge
andcode_challenge_method
– 当支持 PKCE 时,需要存储应用程序提供的这两个值,以便稍后在颁发访问令牌时验证它们。
通过创建 JWS 编码字符串或通过生成随机字符串并将相关信息存储在数据库中来生成授权代码后,您需要将用户重定向到应用程序指定的重定向 URL。要添加到重定向 URL 的查询字符串中的参数如下:
code
此参数包含客户端稍后将交换访问令牌的授权代码。
state
如果初始请求包含状态参数,则响应还必须包含来自请求的确切值。客户端将使用它来将此响应与初始请求相关联。
例如,授权服务器通过发送以下 HTTP 响应来重定向用户。
代码语言:javascript复制HTTP/1.1 302 Found
Location: https://example-app.com/redirect?code=g0ZGZmNjVmOWI&state=dkZmYxMzE2
隐式授权类型响应
使用隐式授权 ( response_type=token
),授权服务器立即生成一个访问令牌,并重定向到片段中带有令牌和其他访问令牌属性的回调 URL。
例如,授权服务器通过发送以下 HTTP 响应来重定向用户(额外的换行符用于显示目的)。
代码语言:javascript复制HTTP/1.1 302 Found
Location: https://example-app.com/redirect#access_token=MyMzFjNTk2NTk4ZTYyZGI3
&state=dkZmYxMzE2
&token_type=Bearer
&expires_in=86400
您可以看到这比发布一个临时的一次性授权代码要危险得多。由于与拦截 HTTPS 请求相比,Attack者可以通过更多方式从 HTTP 重定向中窃取数据,因此与授权代码流相比,使用此选项的风险更大。
从授权服务器的角度来看,在它创建访问令牌并发送 HTTP 重定向时,它无法知道重定向是否成功以及正确的应用程序是否收到了访问令牌。这有点像将访问令牌抛向空中,祈祷应用程序能够捕捉到它。这与授权代码方法形成对比,在授权代码方法中,即使授权服务器不能保证授权代码没有被盗,它至少可以通过要求客户端密码或 PKCE 代码验证程序来防止被盗的授权代码有用. 这提供了更高级别的安全性,因为授权服务器现在可以更加确信它不会将访问令牌泄露给Attack者。
由于这些原因以及OAuth 2.0 for Browser-Based Apps中的更多记录,建议不再使用隐式流。
错误响应
有两种不同类型的错误需要处理。第一种错误是开发人员在创建授权请求时做错了。另一种错误是用户拒绝请求(单击“拒绝”按钮)。
如果请求的语法有问题,例如redirect_uri
orclient_id
无效,那么重要的是不要重定向用户,而应该直接显示错误消息。这是为了避免让您的授权服务器被用作开放式重定向器。
如果redirect_uri
和client_id
都有效,但仍然存在其他问题,则可以将用户重定向回查询字符串中有错误的重定向 URI。
当重定向回应用程序以指示错误时,服务器将以下参数添加到重定向 URL:
error
以下列表中的单个 ASCII 错误代码:
invalid_request
– 请求缺少参数、包含无效参数、多次包含参数或无效。access_denied
– 用户或授权服务器拒绝了请求unauthorized_client
– 不允许客户端使用此方法请求授权代码,例如,如果机密客户端尝试使用隐式授权类型。unsupported_response_type
– 服务器不支持使用此方法获取授权代码,例如,如果授权服务器从未实现隐式授权类型。invalid_scope
– 请求的范围无效或未知。server_error
– 服务器可以使用此错误代码重定向,而不是向用户显示 500 Internal Server Error 页面。temporarily_unavailable
– 如果服务器正在进行维护或不可用,则可以返回此错误代码,而不是使用 503 服务不可用状态代码进行响应。
error_description
授权服务器可以选择包含人类可读的错误描述。此参数旨在供开发人员了解错误,而不是要显示给最终用户。该参数的有效字符为除双引号和反斜杠外的 ASCII 字符集,具体为十六进制代码 20-21、23-5B 和 5D-7E。
error_uri
服务器还可以返回一个 URL 到一个人类可读的网页,其中包含有关错误的信息。这是为了让开发人员获得有关错误的更多信息,而不是为了向最终用户显示。
state
如果请求包含状态参数,则错误响应还必须包含来自请求的确切值。客户端可以使用它来将此响应与初始请求相关联。
例如,如果用户拒绝授权请求,服务器将构造以下 URL 并发送如下所示的 HTTP 重定向响应(URL 中的换行符用于说明目的)。
代码语言:javascript复制HTTP/1.1 302 Found
Location: https://example-app.com/redirect?error=access_denied
&error_description=The user denied the request
&error_uri=https://oauth2server.com/error/access_denied
&state=wxyz1234