OAuth 2.0 的场景中有四个角色:
- Resource Owner,受保护资源的所有者,一般是终端用户;
- Resource Server,资源托管者,提供访问这些受保护资源的 API;
- Client,客户端:需要请求受保护资源;
- Authorization Server,鉴权服务:提供用户认证与令牌签发服务,不过今天的讨论中可以由 Resource Server 代劳;
今天的场景中 Resource Server 是一家服务提供商 auth.com,Client 则是第三方应用 cool.app。cool.app 需要临时向 auth.com 请求一些受保护的资源,此时需要证明 auth.com 的某个用户 A 即 Resource Owner 确实授权了这一操作。
至于为什么 OAuth 2.0 能顺便实现第三方登录的效果,就会涉及到 OpenID Connect (OIDC) 的内容,当然简单点也可以是 cool.app 在获取用户授权后顺便请求了 auth.com 的 /user 接口。
在现实场景中 auth.com 一般对应各种第三方登录服务商(Apple、Microsoft、Google、WeChat 什么的),cool.app 则通常是我们自己开发的应用。无论使用哪一个 OAuth 2.0 应用模式,cool.app 都需要在 auth.com 处注册并取得身份标识,通常称为 CLIENT_ID 和 CLIENT_SECRET。
Authorization Code Flow,授权码模式
这是 Web 应用和移动 APP 上最常见的模式,用户 A 在 cool.app 的页面上点击一个授权链接,前往:
https:/authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URL&
scope=read
response_type=code 表明使用的是授权码模式,scope=read 表明了请求权限的范围。
用户跳转到 auth.com 后可以声明允许或拒绝授权。无论如何,用户都将被重定向到 redirect_uri 地址。允许授权时的目的地可能长下面这样,AUTHORIZATION_CODE 就是 auth.com 发放的授权码。
https:/authorize/callback?code=AUTHORIZATION_CODE
接下来所有的工作需要保密,所以就来到了后端服务中。cool.app 需要根据授权码请求真正的令牌,比如向 auth.com 的令牌服务(通常是 /oauth/tokon 端点)发起请求:
{
"client_id": CLIENT_ID,
"client_secret": CLIENT_SECRET,
"grant_type": "authorization_code",
"code": AUTHORIZATION_CODE,
"callback_uri": CALLBACK_URL
}
而 auth.com 在确认无误后将向 CALLBACK_URL 指定的接口颁发令牌,比如下面这个就是 GitHub 发的:
Accept: application/json
{
"access_token": "gho_16C7e42F292c6912E7710c838347Ae178B4a",
"scope": "repo,gist",
"token_type": "bearer"
}
接下来就该干嘛干嘛了。
curl -H "Authorization: Bearer ACCESS_TOKEN" https://api.github.com/user
Implicit Flow with Form Post,隐藏模式
如果 cool.app 是一个纯前端应用,就不能使用 OAuth 了吗?非也。
https:/oauth/token?
response_type=token&
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URL&
scope=read
注意到这里跳转 URL 中 response_type 变成了 token。auth.com 在返回时会直接在 URL 中携带令牌。因为这时候令牌是明文的,一般会放在 URL 的 Fragment 部分,免得通过 HTTP 请求一起发出去了,稍稍保证一点安全性。
https:/authorize/callback#token=ACCESS_TOKEN
Resource Owner Password Flow,密码模式
RFC 6749 让你把在 auth.com 的帐号密码告诉 cool.app 好让它去申请令牌?
Client Credentials Flow,客户端凭证模式
客户发现他们在 UI 上花掉的预算是核心功能的 4 倍,所以 cool.app is dead, long live the cool.cli。
cool.cli 向 auth.com 发起了 Web 请求:
curl https://auth.com/oauth/token?
grant_type=client_credentials&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
这里直接提供了 cool.cli 的注册信息,没有用户什么事,所以这里的凭证是针对客户端而不是用户的。