目录
Oauth
Oauth2.0
客户端应用注册
授权码模式(authorization code)流程
简化模式(Implicit Flow)流程
密码模式(Resource owner password credentials)流程
客户端模式(Client Credentials Flow)流程
前言
开发者A注册某IT论坛后,发现可以在信息栏中填写自己的 Github 个人信息和仓库项目,但是他又觉得手工填写十分麻烦,但是直接提供 Github 账户和密码给论坛又是非常危险的事情。开发者A发现在该论坛处,可以点击“导入”按钮,授权该论坛访问自己的 Github 账户并限制其只具备读权限。这样一来, Github 中的所有仓库和相关信息就可以很方便地被导入到信息栏中,账户隐私信息也不会泄露。
英文 | 中文 |
---|---|
Authorization Grant | 授权许可 |
Authorization Code | 授权码 |
Access Token | 访问令牌 |
Authorization | 授权 |
Authentication | 认证 |
OAuth
OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 OAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 OAuth 是安全的。OAuth 是 Open Authorization 的简写。OAuth 已经有2.0版本了,2007年发布了 OAuth1.0 协议,2011年发布会了 OAuth2.0,2.0与1.0之间不兼容。OAuth2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。
关于 OAuth2.0 认证的一个文章,讲的很简单明了——> OAuth 2.0 的一个简单解释
OAuth2.0 认证流程:获取授权码 (Authorization Code) —> 换取访问令牌(Access_token)—> 访问资源
OAuth 2 标准中定义了以下几种角色:
OAuth2.0的授权模式
客户端应用注册
客户端应用注册
在应用 OAuth 2 之前,你必须在授权方服务中注册你的应用。如 Google Identity Platform 或者 Github OAuth Setting,诸如此类 OAuth 实现平台中一般都要求开发者提供如下所示的授权设置项。
重定向URI是授权方服务在用户授权(或拒绝)应用程序之后重定向供用户访问的地址,因此也是用于处理授权码或访问令牌的应用程序的一部分。
Client ID 和 Client Secret(客户端秘钥)
一旦你的应用注册成功,授权方服务将以 client id 和 client secret 的形式为应用发布 client credentials(客户端凭证)。client id 是公开透明的字符串,授权方服务使用该字符串来标识应用程序,并且还用于构建呈现给用户的授权 url 。当应用请求访问用户的帐户时,client secret 用于验证应用身份,并且必须在客户端和服务之间保持私有性。
Authorization Code 是最常使用的一种授权许可类型,它适用于第三方应用类型为 server-side 型应用的场景。Authorization Code授权流程基于重定向跳转,客户端必须能够与 User-agent(即用户的 Web 浏览器)交互并接收通过 User-agent 路由发送的实际 Authorization Code值。
1. User Authorization Request
首先,客户端构造了一个用于请求 Authorization Code 的 URL 并引导User-agent 跳转访问。
https://authorization-server.com/auth
?response_type=code
&client_id=29352915982374239857
&redirect_uri=https://example-client.com/callback
&scope=create+delete
&state=xcoiv98y2kd22vusuye3kch
如下,是微博登录使用QQ授权
https://graph.qq.com//oauth2.0/authorize?client_id=101019034
&response_type=code
&scope=get_info,get_user_info
&redirect_uri=https://passport.weibo.com/othersitebind/bind?site=qq
&state=CODE-gz-1I24J0-2hHSCM-UB6CQF9gP1BzBvYa58483
&bentry=miniblog
&wl=&display=
2. User Authorizes Application
当用户点击上文中的示例链接时,用户必须已经在授权服务中进行登录(否则将会跳转到登录界面,不过 OAuth 2 并不关心认证过程),然后授权服务会提示用户授权或拒绝应用程序访问其帐户。以下是授权应用程序的示例:
3. Authorization Code Grant
如果用户确认授权,授权服务器将重定向 User-agent 至之前客户端提供的指向客户端的 redirect_uri 地址,并附带 code 和 state 参数(由之前客户端提供),于是客户端便能直接读取到 Authorization Code 值。
https://example-client.com/redirect?
code=g0ZGZmNjVmOWIjNTk2NTk4ZTYyZGI3
&state=xcoiv98y2kd22vusuye3kch
如下,是QQ授权成功
https://passport.weibo.com/othersitebind/bind?site=qq
&state=CODE-gz-1I24J0-2hHSCM-UB6CQF9gP1BzBvYa58483
&bentry=miniblog
&wl=
&code=4F3BE37354B5148C06CA82032C513AAC
4. Access Token Request
现在客户端已经拥有了服务器派发的 Authorization Code,接下来便可以使用 Authorization Code 和其他参数向服务器请求 Access Token(POST方式)。其他相关参数如下:
5. Access Token Grant
服务器将会验证第4步中的请求参数,当验证通过后(校验Authorization Code 是否过期,client id 和 client secret 是否匹配等),服务器将向客户端返回 Access token。
{
"access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"IwOGYzYTlmM2YxOTQ5MGE3YmNmMDFkNTVk",
"scope":"create delete"
}
至此,授权流程全部结束。直到 access token 过期或失效之前,客户端可以通过资源服务器API访问用户的帐户,并具备 scope 中给定的操作权限。
简化模式(Implicit Flow)流程
1. User Authorization Request
客户端构造的 URL 如下所示:
https://{yourOktaDomain}.com/oauth2/default/v1/authorize?
client_id=0oabv6kx4qq6h1U5l0h7
&response_type=token
&redirect_uri=http://localhost:8080
&state=state-296bc9a0-a2a2-4a57-be1a-d0e2fd9bb601
&nonce=foo
response_type 的 response_type 参数值为 token 或 id_token 。其他请求参数与 Authorization Code 授权流程相比没有并什么变化。
2. User Authorizes Application(略)
3. Redirect URI With Access Token In Fragment
假设用户授予访问权限,授权服务器将 User-agent(浏览器) 重定向回客户端使用之前提供的 redirect_uri。并在 uri 的 # 部分添加 access_token 键值对。如下所示:
http://localhost:8080/#
access_token=eyJhb[...]erw
&token_type=Bearer
&expires_in=3600&scope=openid
&state=state-296bc9a0-a2a2-4a57-be1a-d0e2fd9bb601
token_type:当且仅当 response_type 设置为 token 时返回,值恒为 Bearer。
注意在 Implicit 流程中,access_token值放在了 URI 的 # 部分,而不是作为 ?query 参数。
4. User-agent Follows the Redirect URI
User-agent(浏览器)遵循重定向指令,请求 redirect_uri 标识的客户端地址,并在本地保留 uri 的 # 部分的 access_token 信息。
5. Application Sends Access Token Extraction Script
客户端生成一个包含 token 解构脚本的 Html 页面,这个页面被发送给User-agent(浏览器),执行脚本解构完整的 redirect_uri 并提取其中的access_token(access token 信息在第4步中已经被 User-agent 保存)。
6. Access Token Passed to Application
User-agent(浏览器)向客户端发送解构提取的 access token。
至此,授权流程全部结束。直到 access token 过期或失效之前,客户端可以通过资源服务器API访问用户的帐户,并具备scope中给定的操作权限。
密码模式(Resource owner password credentials)流程
1. Resource Owner Password Credentials From User Input
用户向客户端提供用户名与密码作为授权凭据。
2. Resource Owner Password Credentials From Client To Server
客户端向授权服务器发送用户输入的授权凭据以请求 access token。客户端必须已经在服务器端进行注册。
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=password&username=johndoe&password=A3ddj3w
grant_type:必选项,值恒为 password
3. Access Token Passed to Application
授权服务器对客户端进行认证并检验用户凭据的合法性,如果检验通过,将向客户端派发 access token
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
客户端模式(Client Credentials Flow)流程
Client Credential 是最简单的一种授权流程。客户端可以直接使用它的client credentials 或其他有效认证信息向授权服务器发起获取 access token的请求。
两步中的请求体和返回体分别如下:
POST /token HTTP/1.1
Host: server.example.com
Authorization:Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
grant_type:必选项,值恒为 client_credentials
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"example_parameter":"example_value"
}
参考文章:OAuth 2 深入介绍
相关文章:OAuth 2.0攻击方法及案例总结