简介
OAuth 2.1 是一个授权协议,它使第三方应用程序(例如 Twitter、GitHub)能够获得在第二方服务上特定用户资源的访问权限。
OAuth 角色
OAuth 定义了四种角色:
- 资源所有者 (Resource Owner):一个能够授予受保护资源访问权的实体。
- 应用 (Client): 获得 Resource Owner 授权而得以请求到 Resource Server 的程序,"Client"一词并不意味着任何特定的实现特征,它可以是在服务器、桌面或其他设备上执行的程序。
- 资源服务器 (Resource Server):托管受保护资源的服务器。
- 授权服务器 (Authorization Server):授权服务器验证资源所有者的身份,获得资源所有者授权后向应用颁发访问令牌。
这四个角色可以分成三方,第一方是资源所有者,第二方是资源服务器和授权服务器,第三方就是应用。 如果我们在某个网站点了“使用 GitHub 登录”,第一方是我们自己,第二方是 GitHub,第三方就是这个网站。 第二方分成两个服务是考虑到资源服务是多种多样的,需要有较好的扩展性,而授权服务是很少迭代更新的,将授权服务抽离出来可以复用和解耦。 另外,协议文档中提到的 User Agent 是指资源所有者使用的用户界面,例如浏览器。
授权方式
OAuth 2 主要定义了三种主要的授权类型,每种类型各适用于不同的场景:
1. Authorization Code 授权
Authorization Code 授权方式适合 Client 在服务端的场景,资源请求全在 Client 服务端进行。
授权请求报文示例(由授权服务器的前端发送给后端):
GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
&code_challenge=6fdkQaPm51l13DSukcAH3Mdx7_ntecHYd1vi3n0hMZY
&code_challenge_method=S256 HTTP/1.1
Host: server.example.com
交换 access token 的请求示例(由 Client 服务端发送给授权服务):
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient%2Eexample%2Ecom%2Fcb
&code_verifier=3641a2d12d66101249cdf7a79c000c1f8c05d2aafcf14bf146497bed
流程中有一步是使用 code 与授权服务交换访问令牌,它的作用官方解释是:
The authorization code provides a few important security benefits, such as the ability to authenticate the client, as well as the transmission of the access token directly to the client without passing it through the resource owner’s user agent and potentially exposing it to others, including the resource owner. [1]
code_challenge
的作用:
To prevent injection of authorization codes into the client, using code_challenge and code_verifier is REQUIRED for clients, and authorization servers MUST enforce their use, unless both of the following criteria are met:
- The client is a confidential client.
- In the specific deployment and the specific request, there is reasonable assurance by the authorization server that the client implements the OpenID Connect nonce mechanism properly.[2]
In this case, using and enforcing code_challenge and code_verifier is still RECOMMENDED.
资源服务校验访问令牌 (access token)
1. JWT
向通过 resourceserver.jwt.issuer-uri
配置的授权服务地址请求公钥,然后使用公钥校验 JWT 的签名。 公钥会缓存在资源服务,所以不是每次处理 Client 的请求都向授权服务请求公钥,网络 IO 较少,CPU 消耗较多。 另外,JWT 长度较长,会在 Client 到资源服务的请求上增加网络带宽。
2. Opaque Token
每次收到来自 Client 的请求,资源服务都会向授权服务发送请求以校验访问令牌,网络 IO 较多,CPU 消耗较少。 使用 Opaque Token 要求为资源服务器配置一对 client-id
和 client-secret
。