OAuth 全称是 Open Authorization
,它是一种授权机制。
数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。
系统从而产生一个短期的进入令牌(token
),用来代替密码,供第三方应用使用。
OAuth2.0
的令牌授权方式分为四种:
- 授权码(
authorization-code
) - 隐藏式(
implicit
) - 密码式(
password
) - 客户端凭证(
client-credentials
)
1.授权码
该模式适用于那些有后端的 Web
应用。
这种方式是最常用的流程,安全性也最高。
授权码(authorization-code
)方式,指的是第三方应用先申请一个授权码,然后再用该码获取令牌。
授权码通过前端传送,令牌则是储存在后端,而且所有与资源服务器的通信都在后端完成。这样的前后端分离,可以避免令牌泄漏。
1-1.获取授权码code
譬如有客户端 a.com
和授权服务端 b.com
,那么首先 A
网站可通过如下链接获取授权码:
`https://b.com/oauth/authorize
?response_type=code
&client_id=${CLIENT_ID}
&redirect_uri=${REDIRECT_URI}
&scope=read`
1-2.链接重定向
在上述获取授权码成功之后,系统会重定向到新链接:
`${REDIRECT_URI}?code=AUTHORIZATION_CODE`
1-3.获取令牌access_token
在拿到授权码 code
之后,就可以在后端,向 B
网站请求令牌。
`https://b.com/oauth/token
?client_id=${CLIENT_ID}
&client_secret=${CLIENT_SECRET}
&grant_type=authorization_code
&code=${AUTHORIZATION_CODE}`
其中,client_id
参数和 client_secret
参数用来让 B
确认 A
的身份(client_secret
参数是保密的,因此只能在后端发请求)。
上述链接调用之后,大致会返回如下形式的 JSON
数据:
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{}
}
2.隐藏式
该模式适用于没有后端服务的纯前端应用。
隐藏式(implicit
)允许直接向前端颁发令牌。
相对上节,该模式省略了授权码这个中间步骤。而是直接获取 access_token
。
为了防止令牌泄漏,access_token
通常定义到锚点而非 queryString
。
第一步,跳转到授权链接:
`https://b.com/oauth/authorize
?response_type=token
&client_id=${CLIENT_ID}
&redirect_uri=${REDIRECT_URI}
&scope=read`
授权成功后,会直接重定向到:
`${REDIRECT_URI}#token=ACCESS_TOKEN`
TIP
令牌的位置是
URL
锚点(fragment
),而不是查询字符串(queryString
),这是因为OAuth2.0
允许跳转网址是HTTP
协议,因此存在"中间人攻击"的风险,而浏览器跳转时,锚点不会发到服务器,就减少了泄漏令牌的风险。这种方式把令牌直接传给前端,是很不安全的。因此,只能用于一些安全要求不高的场景,并且令牌的有效期必须非常短,通常就是会话期间(
session
)有效,浏览器关掉,令牌就失效了。
3.密码式
该模式适用于其他授权模式不便使用,且用户高度信任的应用。
密码式允许用户把用户名和密码,直接告诉该应用。该应用就使用你的密码,申请令牌。
A
网站直接请求如下链接,获取令牌:
`https://oauth.b.com/token
?grant_type=password
&username=${USERNAME}
&password=${PASSWORD}
&client_id=${CLIENT_ID}`
该模式不存在 REDIRECT_URI
,因此无需发生跳转。
而是会把令牌放到 JSON
数据里,作为 HTTP
响应。
TIP
该模式需要用户给出自己的用户名/密码,风险很大,因此在实际业务中不推荐使用。
4.客户端凭证
该模式适用于没有前端的命令行应用,即在命令行下请求令牌。
第一步,在命令行访问链接:
`https://oauth.b.com/token
?grant_type=client_credentials
&client_id=${CLIENT_ID}
&client_secret=${CLIENT_SECRET}`
验证通过之后,直接返回令牌。
TIP
这种方式给出的令牌,是针对第三方应用的,而不是针对用户的,即有可能多个用户共享同一个令牌。