简介
oauth2.0是一种目前被广泛使用的开放式授权协议。各个服务平台可以使用oauth2.0协议来允许平台用户授权第三方来获取用户的信息数据等。
术语
Client : 第三方应用
Resource Owner : 资源拥有者,即平台用户
Authorization Server : 认证服务器,即平台提供的专门处理认证的服务
Resource Server : 资源服务器,平台给第三方提供资源访问的服务器,它与认证服务器可以是同一台也可以不是同一台
User Agent : 用户代理,即浏览器
协议流程
(A)用户打开客户端以后,客户端要求用户给予授权
(B)用户同意给予客户端授权。
(C)客户端使用上一步获得的授权,向认证服务器申请令牌。
(D)认证服务器对客户端进行认证以后,确认无误,同意发放令牌。
(E)客户端使用令牌,向资源服务器申请获取资源。
(F)资源服务器确认令牌无误,同意向客户端开放资源。
客户端授权类型
- 授权码模式(authorization code)
- 简化模式(implict)
- 密码模式(resource owner password credentials)
- 客户端模式(client credentials)
目前最常用的是授权码模式,因此也只对授权码模式进行学习。
授权码模式流程
(A)用户访问客户端,后者将前者重定向到认证服务器。
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向URI"(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)。
获取授权码(authorization code)
请求参数:
参数名称 | 是否可选 | 参数值 | 说明 |
response_type |
必填 | code | 响应类型,此处固定值 |
client_id |
必填 | 客户端标识 | |
redirect_uri |
必填 | 重定向url | |
scope |
可选 | 权限申请范围,多个空格分隔 | |
state |
可选 | ?客户端状态,服务端原样返回 |
例如:
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb HTTP/1.1
Host: server.example.com
返回参数:
参数名称 | 是否可选 | 参数值 | 说明 |
code |
必填 | 授权码,有效时间很短,一次性 | |
state |
可选 | 如果请求中包含,则原样返回 |
例如:
HTTP/1.1302 Found
Location: https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
错误响应(JSON):
参数名称 | 是否可选 | 参数值 | 说明 |
error |
必填 | 参见“错误代码表” | 错误代码 |
error_description |
可选 | 错误描述 | |
error_uri |
可选 | 错误信息查看手册url |
错误代码表:
错误码 | 说明 |
invalid_request |
请求格式不正确(参数缺失,重复等) |
unauthorized_client |
客户端未授权 |
access_denied |
授权被拒绝 |
unsupported_response_type |
response_type参数指定值不支持 |
invalid_scope |
scope参数有误 |
server_error |
授权服务器内部错误 |
temporarily_unavailable |
授权服务暂时无法访问 |
例如:
HTTP/1.1 302 Found
Location: https://client.example.com/cb?error=access_denied&state=xyz
注:当请求没有处理成功(参数正确,获取到授权码)时,返回错误信息时应将http响应的响应码也更改为对应的含义(500除外,可以使用其他代替)。仅当处理成功时http响应码才应该被设置为200.
获取访问令牌(access token)
请求参数:
参数名称 | 是否可选 | 参数值 | 说明 |
grant_type |
必填 |
authorization_code |
固定值 |
code |
必填 | 授权码 | |
redirect_uri |
可选 | 如有,必须和上一步一致 | |
client_id |
必填 | 客户端标识 | |
client_secret | 必填 | 客户端秘钥(该字段平台定义) |
例如:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
返回参数(JSON):
参数名称 | 是否可选 | 参数值 | 说明 |
access_token | 必填 | bearer | 访问令牌 |
token_type | 必填 | 令牌类型,bearer或mac | |
expires_in | 可选 | 过期时间 | |
refresh_token | 可选 | 刷新令牌 | |
scope | 可选 | 权限范围 |
例如:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
错误响应(JSON):
参数名称 | 是否可选 | 参数值 | 说明 |
error | 必填 | 参见“错误代码表” | 错误代码 |
error_description | 可选 | 错误描述 | |
error_uri | 可选 | 错误信息查看手册url |
错误代码表:
错误码 | 说明 |
invalid_request | 请求格式不正确(参数缺失,重复等) |
invalid_client |
客户端权限校验失败 |
invalid_grant |
授权码或refresh token无效 |
unauthorized_client |
客户端未被授权使用该授权类型 |
unsupported_grant_type |
授权服务器不支持该授权类型 |
invalid_scope |
scope参数有误 |
例如:
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"error":"invalid_request"
}
注:当请求没有处理成功(参数正确,获取到授权码)时,返回错误信息时应将http响应的响应码也更改为对应的含义(500除外,可以使用其他代替)。仅当处理成功时http响应码才应该被设置为200.
HTTP响应码参考:
302 Found
400 Bad Request
401 Unauthorized
403 Forbidden
503 Service Unavailable
刷新访问令牌
请求参数:
参数名称 | 是否可选 | 参数值 | 说明 |
grant_type | 必填 |
refresh_token |
固定值 |
refresh_token | 必填 | 刷新令牌 | |
client_id | 必填 | 客户端标识 | |
client_secret | 必填 | 客户端秘钥 | |
scop | 可选 | 权限范围 |
注:授权信息可以通过http请求头的形式发送。
例如:
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
返回参数和错误响应与“获取访问令牌”一致。
访问保护资源
客户端访问用户受保护资源时,一般只需要访问平台给出的url地址,然后将access_token和其他参数一起发送过去即可。令牌信息可以通过请求头或者包含在请求数据中。