OAuth 2.0 几种授权类型总结
OAuth 协议解决了以下问题:
- 密码泄露风险
- 无法控制授权范围、有效期
OAuth 协议中,术语“授权类型(Grant Types)”是指应用获取“访问令牌(Access Token)”的方式。OAuth 2.0 定义了以下几种授权类型:
- 用户类资源:需要用户先授权
- 授权码模式(Authorization Code),需要用户授权
- 简化模式(Implicit),不建议使用
- 密码模式(Password)
- 设备码模式(Device Code)
- 商户类资源,无需用户授权
- 客户端模式(Client Credentials),也叫商户模式接入
- 其它
- 令牌刷新模式(Refresh Token)
几种授权类型都有其对应的使用场景,各有利弊,但目的都是为了获取访问令牌。访问令牌是一个用于访问已授权资源的临时凭据。
商户在接入认证服务器之前,需要先申请一套专用的 client_id
、client_secret
,据此再申请 access_token
。下表总结了其中三种主流授权类型下,申请 access_token
令牌的前置条件:
授权方式 | grant_type | 授权的前置条件 | 描述 |
---|---|---|---|
授权码模式 | authorization_code |
授权码 | 这种模式是最常见、功能最完整、流程最严密的授权模式,第三方应用需要先获取授权码,才能申请到令牌。它的特点就是通过第三方应用的后台服务器,与“服务提供商”的认证服务器进行互动,通过授权码(authorization_code )交换访问令牌(access_token ),第三方应用不接触用户密码,安全性高。 |
密码模式 | password |
用户的账号、密码 | 这种模式通常用在用户对该应用高度信任的情况下,或者所有服务都由同一家公司提供。在这种模式下,用户必须把自己的用户名和密码发给应用。应用使用这些信息,再向“服务提供商”索要授权,其风险在于应用获知了密码。但应用无需存储密码,而是存储和使用令牌即可。 密码模式还有一种主流的变种,即使用用户手机号和短信验证码申请令牌,相比密码模式会更安全些。为了区分,可以自定义一个 grant_type 为 sms_verify_code 。 |
客户端模式 | client_credentials |
无 | 第三方应用以自己的名义,而不是以用户的名义,向“服务提供商”进行认证,并获取商户类资源,而不是用户类资源。 |
授权码模式
OAuth 旨在让用户能够对第三方应用授予有限的访问权限。第三方应用首先需要确定所需的权限,然后将用户导向浏览器以获得其授权。简单回顾下:
要开始授权流程,第三方应用需要先构建 URL。这里附一张流程图,详细总结下授权码模式的整个流程:
报文如下:
交互方式上特别注意浏览器会进行几次 302 重定向。流程总结如下:
- 第三方应用首先向服务提供商申请
client_id
应用唯一标识、client_secret
密钥,用于后续获取令牌时提供身份校验; - 获取授权码:此时要提供预分配好的
client_id
标识来源,提供scope
标识要申请的权限,提供redirect_uri
标识授权完毕后要回跳的第三方应用的链接。 - 第一次 302 重定向:认证服务器展示登录授权页。
- 第二次 302 重定向:在用户提交授权,认证服务器认证成功后,会分配授权码
code
,并重定向回第三方应用的redirect_uri
。 - 建议第三方应用要根据当前用户会话生成随机且唯一的
state
参数,并在接收到授权码时先进行校验,避免 CSRF 攻击。 - 最后,第三方应用会向认证服务器申请令牌
access_token
,此时要提供预分配好的client_id
、client_secret
、code
以便认证。这一步是在后端之间完成的,对用户不可见。 access_token
是有有效期的,过期后需要刷新。- 拿到令牌
access_token
后,第三方应用就可以访问资源方,获取所需资源。access_token
相当于用户的 session id。
以微信公众平台为例,微信网页授权 就是使用了“授权码模式(grant_type=authorization_code
)”。商户在完成接入并获取用户的 access_token
之后,可用于如下场景:
- 获取用户 openid
- 获取用户信息(如昵称、头像、性别、所在地)
- ……
简化模式
简化了授权码模式,不再需要授权码(Authorization Code)换令牌(Access Token),而是 Authorization Server 直接返回令牌(Access Token)。
1 | +--------+ +---------------+ |
密码模式
报文如下:
客户端模式
客户端授权模式用于请求商户资源,而不是用户资源,报文如下:
以微信公众平台为例,获取公众号的 access_token 就是使用了“客户端模式(grant_type=client_credential
)”。商户在完成接入并获取应用的 access_token
之后,可用于如下场景:
- 自定义菜单的配置
- 消息推送
- 素材管理
- 用户管理
- 帐户管理
- 数据统计
- …… 大量服务
参考
RFC 6749 - The OAuth 2.0 Authorization Framework - IETF
RFC 6750 - The OAuth 2.0 Authorization Framework: Bearer Token Usage
https://developer.linkedin.com/zh-cn/docs/oauth2