第一章:OAuth2 概述
什么是 OAuth2?
OAuth2 是一个开放标准的授权协议,允许用户授权第三方应用访问其在其他服务上的资源,而无需暴露用户的密码。
┌─────────────────────────────────────────────────────────────┐
│ OAuth2 角色 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐│
│ │ Resource │ │ Client ││
│ │ Owner │◄──────────授权─────────────│ (应用) ││
│ │ (用户) │ │ ││
│ └─────────────┘ └──────┬──────┘│
│ │ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐│
│ │ Authorization│◄─────│ Access │──────│ Resource ││
│ │ Server │──────►│ Token │ │ Server ││
│ │ (授权服务) │ │ │ │ (资源服务) ││
│ └─────────────┘ └─────────────┘ └─────────────┘│
│ │
└─────────────────────────────────────────────────────────────┘
核心概念
角色
| 角色 |
说明 |
示例 |
| Resource Owner |
资源所有者 |
用户 |
| Client |
客户端应用 |
第三方应用 |
| Authorization Server |
授权服务器 |
Auth0、Keycloak |
| Resource Server |
资源服务器 |
API 服务 |
令牌类型
| 令牌 |
说明 |
用途 |
| Access Token |
访问令牌 |
访问受保护资源 |
| Refresh Token |
刷新令牌 |
获取新的 Access Token |
| ID Token |
身份令牌 |
用户身份信息(OIDC) |
端点
| 端点 |
说明 |
| Authorization Endpoint |
授权端点,用户授权 |
| Token Endpoint |
令牌端点,获取令牌 |
| Revocation Endpoint |
撤销端点,撤销令牌 |
| UserInfo Endpoint |
用户信息端点(OIDC) |
| JWKS Endpoint |
公钥端点,验证 JWT |
OAuth2 流程
基本流程
┌─────────────────────────────────────────────────────────────┐
│ OAuth2 授权流程 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 用户点击"使用 XX 登录" │
│ │ │
│ ▼ │
│ 2. 重定向到授权服务器 │
│ │ │
│ ▼ │
│ 3. 用户登录并授权 │
│ │ │
│ ▼ │
│ 4. 授权服务器返回授权码 │
│ │ │
│ ▼ │
│ 5. 客户端用授权码换取令牌 │
│ │ │
│ ▼ │
│ 6. 客户端使用令牌访问资源 │
│ │
└─────────────────────────────────────────────────────────────┘
授权请求
GET /authorize?
response_type=code&
client_id=CLIENT_ID&
redirect_uri=https://client.example.com/callback&
scope=read write&
state=xyz
令牌请求
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=AUTHORIZATION_CODE&
redirect_uri=https://client.example.com/callback&
client_id=CLIENT_ID&
client_secret=CLIENT_SECRET
令牌响应
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...",
"scope": "read write"
}
Scope 权限
定义 Scope
# 常见 Scope
openid - OIDC 身份认证
profile - 用户基本信息
email - 邮箱地址
address - 地址信息
phone - 电话号码
offline_access - 离线访问(获取 refresh_token)
# 自定义 Scope
read:users - 读取用户信息
write:users - 写入用户信息
admin - 管理员权限
Scope 验证
def check_scope(required_scope, token_scopes):
"""检查令牌是否包含所需权限"""
if required_scope in token_scopes:
return True
if 'admin' in token_scopes:
return True
return False
与传统认证对比
| 特性 |
传统认证 |
OAuth2 |
| 密码存储 |
应用存储 |
授权服务器存储 |
| 密码暴露 |
应用获取密码 |
应用不获取密码 |
| 权限控制 |
应用自行控制 |
标准化 Scope |
| 单点登录 |
难以实现 |
天然支持 |
| 安全性 |
依赖应用实现 |
标准化安全 |
小结
OAuth2 基础概念:
- 角色:用户、客户端、授权服务器、资源服务器
- 令牌:Access Token、Refresh Token
- 端点:授权、令牌、撤销
- 流程:授权码换取令牌
下一章我们将学习授权模式。