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://auth.com/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://cool.app/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://auth.com/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://cool.app/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
的注册信息,没有用户什么事,所以这里的凭证是针对客户端而不是用户的。