OAuth 核心概念 #

概述 #

OAuth 2.0 定义了一系列核心概念,理解这些概念是掌握 OAuth 的基础。本文将深入讲解每个核心概念的细节。

text
┌─────────────────────────────────────────────────────────────┐
│                    OAuth 核心概念                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │   令牌       │  │   端点       │  │   客户端     │         │
│  │  Tokens     │  │  Endpoints  │  │  Clients    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │   授权范围   │  │   授权类型   │  │   授权请求   │         │
│  │   Scopes    │  │ Grant Types │  │  Requests   │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

令牌(Tokens) #

访问令牌(Access Token) #

访问令牌是 OAuth 中最重要的概念,它是访问受保护资源的凭证。

text
┌─────────────────────────────────────────────────────────────┐
│                      访问令牌                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  定义:用于访问受保护资源的凭证                              │
│                                                             │
│  特点:                                                     │
│  - 由授权服务器颁发                                         │
│  - 有一定的有效期                                           │
│  - 代表用户授予的权限范围                                   │
│  - 可以是任意格式                                           │
│                                                             │
│  使用方式:                                                 │
│  在 HTTP 请求头中携带                                       │
│  Authorization: Bearer <access_token>                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

令牌响应示例 #

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1//0g...",
  "scope": "profile email"
}

令牌类型 #

类型 描述 使用场景
Bearer 持有者令牌,最常用 大多数 OAuth 实现
MAC 消息认证码令牌 需要额外安全验证
PoP 所有权证明令牌 高安全要求场景

Bearer 令牌使用 #

http
GET /api/userinfo HTTP/1.1
Host: resource.example.com
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...

javascript
const response = await fetch('https://api.example.com/userinfo', {
  headers: {
    'Authorization': `Bearer ${accessToken}`
  }
});

刷新令牌(Refresh Token) #

刷新令牌用于获取新的访问令牌,无需用户重新授权。

text
┌─────────────────────────────────────────────────────────────┐
│                      刷新令牌                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  定义:用于获取新访问令牌的凭证                              │
│                                                             │
│  特点:                                                     │
│  - 有效期通常比访问令牌长                                   │
│  - 可以多次使用(可配置)                                   │
│  - 可以被撤销                                               │
│  - 不直接用于访问资源                                       │
│  - 需要安全存储                                             │
│                                                             │
│  使用场景:                                                 │
│  - 访问令牌过期后获取新令牌                                 │
│  - 长期访问用户资源                                         │
│  - 减少用户重复授权                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

刷新令牌流程 #

text
┌─────────┐     ┌─────────┐     ┌─────────┐
│  客户端  │     │ 授权服务│     │ 资源服务│
└────┬────┘     └────┬────┘     └────┬────┘
     │               │               │
     │ 访问资源      │               │
     │──────────────────────────────>│
     │               │               │
     │ 令牌过期      │               │
     │<──────────────────────────────│
     │               │               │
     │ 刷新令牌请求  │               │
     │──────────────>│               │
     │               │               │
     │ 新访问令牌    │               │
     │<──────────────│               │
     │               │               │
     │ 再次访问资源  │               │
     │──────────────────────────────>│
     │               │               │
     │ 返回数据      │               │
     │<──────────────────────────────│
     │               │               │

刷新令牌请求 #

http
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=1//0g...
&client_id=your_client_id
&client_secret=your_client_secret

刷新令牌响应 #

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "1//0h...",
  "scope": "profile email"
}

令牌生命周期 #

text
┌─────────────────────────────────────────────────────────────┐
│                    令牌生命周期                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   用户授权                                                  │
│      │                                                      │
│      ▼                                                      │
│   ┌─────────────┐                                           │
│   │ 颁发令牌    │                                           │
│   │ Access +    │                                           │
│   │ Refresh     │                                           │
│   └──────┬──────┘                                           │
│          │                                                  │
│          ▼                                                  │
│   ┌─────────────┐    过期    ┌─────────────┐               │
│   │ 使用访问令牌 │ ─────────> │ 刷新令牌    │               │
│   │ 访问资源    │           │ 获取新令牌  │               │
│   └─────────────┘           └──────┬──────┘               │
│          ▲                         │                        │
│          │                         ▼                        │
│          │                  ┌─────────────┐                │
│          └──────────────────│ 新访问令牌  │                │
│                             └─────────────┘                │
│                                                             │
│   撤销场景:                                                │
│   - 用户主动撤销                                            │
│   - 令牌泄露                                                │
│   - 密码修改                                               │
│   - 安全事件                                                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

令牌安全存储 #

text
访问令牌存储位置:

┌─────────────────────────────────────────────────────────────┐
│                    存储位置对比                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  浏览器环境:                                               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │ localStorage│  │ sessionStorage│ │  Cookie     │         │
│  │  ❌ 不推荐   │  │  ⚠️ 一般     │  │ ✅ 推荐     │         │
│  │  易受XSS攻击 │  │  关闭丢失    │  │ HttpOnly    │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                             │
│  移动端:                                                   │
│  ┌─────────────┐  ┌─────────────┐                          │
│  │ Keychain    │  │ Keystore    │                          │
│  │ (iOS)       │  │ (Android)   │                          │
│  │ ✅ 推荐     │  │ ✅ 推荐     │                          │
│  └─────────────┘  └─────────────┘                          │
│                                                             │
│  服务器端:                                                 │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐         │
│  │ 数据库加密   │  │ Redis       │  │ 内存        │         │
│  │ ✅ 推荐     │  │ ✅ 推荐     │  │ ⚠️ 一般     │         │
│  └─────────────┘  └─────────────┘  └─────────────┘         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

端点(Endpoints) #

OAuth 2.0 定义了几个标准端点,用于完成授权流程。

授权端点(Authorization Endpoint) #

text
┌─────────────────────────────────────────────────────────────┐
│                     授权端点                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用途:用于用户授权,获取授权码                              │
│                                                             │
│  请求方式:GET                                               │
│                                                             │
│  示例:                                                     │
│  https://accounts.google.com/o/oauth2/v2/auth               │
│  https://github.com/login/oauth/authorize                   │
│                                                             │
│  必需参数:                                                 │
│  - response_type:响应类型(code/token)                    │
│  - client_id:客户端标识                                    │
│  - redirect_uri:回调地址                                   │
│  - scope:授权范围                                          │
│  - state:防CSRF状态值                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

授权请求示例 #

http
GET /authorize?response_type=code
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb
&scope=profile%20email
&state=xyzABC123 HTTP/1.1
Host: auth.example.com

令牌端点(Token Endpoint) #

text
┌─────────────────────────────────────────────────────────────┐
│                     令牌端点                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用途:用于获取和刷新令牌                                    │
│                                                             │
│  请求方式:POST                                              │
│                                                             │
│  示例:                                                     │
│  https://oauth2.googleapis.com/token                        │
│  https://github.com/login/oauth/access_token                │
│                                                             │
│  功能:                                                     │
│  - 用授权码换取令牌                                         │
│  - 刷新访问令牌                                             │
│  - 客户端凭证授权                                           │
│  - 密码模式授权                                             │
│                                                             │
└─────────────────────────────────────────────────────────────┘

令牌请求示例 #

http
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb
&client_id=s6BhdRkqt3
&client_secret=gX1fPt3W

刷新令牌端点 #

通常与令牌端点相同,通过 grant_type 区分:

http
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=8xLOxBtZp8
&client_id=s6BhdRkqt3
&client_secret=gX1fPt3W

撤销端点(Revocation Endpoint) #

text
┌─────────────────────────────────────────────────────────────┐
│                     撤销端点                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用途:撤销访问令牌或刷新令牌                                │
│                                                             │
│  请求方式:POST                                              │
│                                                             │
│  RFC:RFC 7009                                               │
│                                                             │
│  示例:                                                     │
│  https://oauth2.googleapis.com/revoke                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

撤销请求示例 #

http
POST /revoke HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

token=45ghiukldjahdnhzdauz&token_type_hint=refresh_token

端点发现 #

OAuth 2.0 授权服务器元数据(RFC 8414):

http
GET /.well-known/oauth-authorization-server HTTP/1.1
Host: auth.example.com

响应示例:

json
{
  "issuer": "https://auth.example.com",
  "authorization_endpoint": "https://auth.example.com/authorize",
  "token_endpoint": "https://auth.example.com/token",
  "revocation_endpoint": "https://auth.example.com/revoke",
  "scopes_supported": ["profile", "email", "openid"],
  "response_types_supported": ["code", "token"],
  "grant_types_supported": [
    "authorization_code",
    "implicit",
    "refresh_token"
  ]
}

客户端(Clients) #

客户端类型 #

OAuth 2.0 定义了两种客户端类型:

text
┌─────────────────────────────────────────────────────────────┐
│                     客户端类型                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 机密客户端(Confidential Client)                     │   │
│  │                                                      │   │
│  │ 特点:                                               │   │
│  │ - 能够安全存储 client_secret                         │   │
│  │ - 运行在服务器端                                     │   │
│  │ - 可以使用所有授权类型                               │   │
│  │                                                      │   │
│  │ 示例:                                               │   │
│  │ - Web 服务器应用                                     │   │
│  │ - 后端服务                                           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │ 公共客户端(Public Client)                           │   │
│  │                                                      │   │
│  │ 特点:                                               │   │
│  │ - 无法安全存储 client_secret                         │   │
│  │ - 运行在用户设备上                                   │   │
│  │ - 需要使用 PKCE 增强安全                             │   │
│  │                                                      │   │
│  │ 示例:                                               │   │
│  │ - 单页应用(SPA)                                    │   │
│  │ - 原生移动应用                                       │   │
│  │ - 桌面应用                                           │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

客户端注册 #

在使用 OAuth 之前,客户端需要在授权服务器注册:

text
注册时需要提供:
├── 应用名称
├── 应用类型(Web/原生/SPA)
├── 重定向 URI(redirect_uri)
├── 允许的授权类型
├── 允许的授权范围
└── 其他元数据

注册后获得:
├── client_id(客户端标识)
└── client_secret(客户端密钥,仅机密客户端)

注册示例 #

json
{
  "client_name": "My Awesome App",
  "redirect_uris": [
    "https://myapp.example.com/callback",
    "https://myapp.example.com/auth/callback"
  ],
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "scope": "profile email",
  "token_endpoint_auth_method": "client_secret_basic"
}

客户端认证 #

机密客户端需要在令牌端点进行认证:

Basic 认证 #

http
POST /token HTTP/1.1
Host: auth.example.com
Authorization: Basic czZCaGRSa3F0Mzo3RmpmcDBaQnIxS3REUmJuZlZkbUl3
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA

POST 参数认证 #

http
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&client_id=s6BhdRkqt3
&client_secret=7Fjfp0ZBr1KtDRbnfVdmIw

客户端配置文件 #

OAuth 2.0 定义了几种客户端配置文件:

配置文件 描述 推荐授权类型
Web Application 服务器端 Web 应用 授权码模式
User Agent 单页应用(SPA) 授权码 + PKCE
Native Application 原生移动/桌面应用 授权码 + PKCE

授权范围(Scopes) #

Scope 的作用 #

text
┌─────────────────────────────────────────────────────────────┐
│                     Scope 作用                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 权限控制                                                │
│     - 限制令牌的访问权限                                    │
│     - 实现最小权限原则                                      │
│                                                             │
│  2. 用户知情                                                │
│     - 用户知道应用请求哪些权限                              │
│     - 增强透明度                                            │
│                                                             │
│  3. 权限隔离                                                │
│     - 不同令牌可以有不同权限                                │
│     - 降低安全风险                                          │
│                                                             │
│  4. 增量授权                                                │
│     - 可以逐步请求更多权限                                  │
│     - 减少用户首次授权负担                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Scope 示例 #

Google OAuth Scopes #

text
https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/calendar
https://www.googleapis.com/auth/drive
https://www.googleapis.com/auth/gmail.send

GitHub OAuth Scopes #

text
repo          - 完整仓库访问
user          - 用户信息
user:email    - 用户邮箱
read:org      - 读取组织信息
gist          - 创建 Gist

微信 OAuth Scopes #

text
snsapi_base   - 静默授权,获取用户基本信息
snsapi_userinfo - 获取用户详细信息

Scope 请求方式 #

http
GET /authorize?response_type=code
&client_id=s6BhdRkqt3
&redirect_uri=https%3A%2F%2Fclient.example.com%2Fcb
&scope=profile%20email%20openid
&state=xyzABC123 HTTP/1.1
Host: auth.example.com

Scope 响应 #

令牌响应中包含授权的范围:

json
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "profile email"
}

Scope 最佳实践 #

text
1. 请求最小必要权限
   ❌ scope=profile email calendar drive gmail
   ✅ scope=profile email

2. 使用标准 Scope 名称
   ✅ openid, profile, email

3. 增量授权
   首次登录:scope=openid profile
   需要时再请求:scope=openid profile calendar

4. 检查返回的 Scope
   授权服务器可能授予比请求更少的权限

授权类型(Grant Types) #

四种主要授权类型 #

text
┌─────────────────────────────────────────────────────────────┐
│                    授权类型概览                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. authorization_code(授权码)                            │
│     最安全、最完整的授权方式                                 │
│     适用于:服务器端应用                                     │
│                                                             │
│  2. implicit(简化模式)                                     │
│     直接返回令牌,无授权码                                   │
│     适用于:纯前端应用(已不推荐)                           │
│                                                             │
│  3. password(密码模式)                                     │
│     直接使用用户密码换取令牌                                 │
│     适用于:高度信任的第一方应用                             │
│                                                             │
│  4. client_credentials(客户端凭证)                        │
│     使用客户端凭证获取令牌                                   │
│     适用于:服务间通信,无用户参与                           │
│                                                             │
│  扩展类型:                                                 │
│  - refresh_token:刷新令牌                                  │
│  - urn:ietf:params:oauth:grant-type:jwt-bearer:JWT 断言   │
│  - urn:ietf:params:oauth:grant-type:saml2-bearer:SAML断言 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

授权类型选择 #

场景 推荐授权类型 原因
Web 服务器应用 authorization_code 安全性最高
单页应用(SPA) authorization_code + PKCE 防止授权码泄露
原生移动应用 authorization_code + PKCE 安全性保障
服务间通信 client_credentials 无需用户参与
第一方应用 password(谨慎使用) 高度信任场景
IoT 设备 device_code 无浏览器场景

授权请求参数 #

通用参数 #

text
┌─────────────────────────────────────────────────────────────┐
│                   授权请求参数                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  必需参数:                                                 │
│  ├── response_type:响应类型                                │
│  │   - code:授权码模式                                     │
│  │   - token:简化模式                                      │
│  │                                                          │
│  ├── client_id:客户端标识                                  │
│  │                                                          │
│  └── redirect_uri:回调地址                                 │
│      - 必须与注册时一致                                     │
│      - 必须是绝对 URI                                       │
│                                                             │
│  推荐参数:                                                 │
│  ├── scope:授权范围                                        │
│  │                                                          │
│  └── state:防 CSRF 状态值                                  │
│      - 必须是不可猜测的随机值                               │
│      - 必须验证返回的 state                                 │
│                                                             │
│  可选参数:                                                 │
│  ├── response_mode:响应模式                                │
│  │   - query:查询参数(默认)                              │
│  │   - fragment:URL 片段                                   │
│  │   - form_post:表单提交                                  │
│  │                                                          │
│  ├── prompt:提示模式                                       │
│  │   - none:不显示授权页面                                 │
│  │   - login:强制重新登录                                  │
│  │   - consent:强制显示授权页面                            │
│  │   - select_account:选择账户                             │
│  │                                                          │
│  ├── login_hint:登录提示                                   │
│  │                                                          │
│  └── acr_values:认证上下文参考值                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

PKCE 参数 #

text
PKCE(Proof Key for Code Exchange)参数:

├── code_challenge:挑战码
│   - 由 code_verifier 生成
│   - 生成方法:code_challenge = BASE64URL(SHA256(code_verifier))
│
└── code_challenge_method:挑战方法
    - S256:SHA-256(推荐)
    - plain:明文(不推荐)

状态参数(State) #

State 的作用 #

text
┌─────────────────────────────────────────────────────────────┐
│                    State 参数作用                            │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 防止 CSRF 攻击                                          │
│     - 确保响应与请求来自同一会话                            │
│     - 防止攻击者伪造授权响应                                │
│                                                             │
│  2. 维护会话状态                                            │
│     - 可以在 state 中编码应用状态                           │
│     - 授权后恢复用户上下文                                  │
│                                                             │
│  3. 防止重放攻击                                            │
│     - 每次请求使用新的 state                                │
│     - 验证后立即失效                                        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

State 使用示例 #

javascript
function generateState() {
  return crypto.randomBytes(16).toString('hex');
}

const state = generateState();
session.oauthState = state;

const authUrl = `https://auth.example.com/authorize?` +
  `response_type=code&` +
  `client_id=${clientId}&` +
  `redirect_uri=${encodeURIComponent(redirectUri)}&` +
  `scope=profile%20email&` +
  `state=${state}`;

res.redirect(authUrl);

State 验证 #

javascript
app.get('/callback', (req, res) => {
  const { code, state } = req.query;
  
  if (state !== session.oauthState) {
    return res.status(400).send('Invalid state parameter');
  }
  
  delete session.oauthState;
  
});

重定向 URI(Redirect URI) #

Redirect URI 要求 #

text
┌─────────────────────────────────────────────────────────────┐
│                  Redirect URI 要求                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 必须是绝对 URI                                          │
│     ✅ https://example.com/callback                         │
│     ❌ /callback                                            │
│                                                             │
│  2. 必须与注册时一致                                        │
│     - 协议、主机、端口、路径都必须匹配                       │
│     - 查询参数可选匹配                                      │
│                                                             │
│  3. 必须使用 HTTPS(生产环境)                              │
│     ✅ https://example.com/callback                         │
│     ❌ http://example.com/callback                          │
│                                                             │
│  4. 不能是 localhost(生产环境)                            │
│     - 开发环境可以例外                                      │
│                                                             │
│  5. 不能使用通配符                                          │
│     ❌ https://*.example.com/callback                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Redirect URI 示例 #

text
注册的 Redirect URI:
https://example.com/auth/callback

允许的请求:
✅ https://example.com/auth/callback
✅ https://example.com/auth/callback?foo=bar

不允许的请求:
❌ http://example.com/auth/callback(协议不同)
❌ https://example.com:443/auth/callback(端口显式指定)
❌ https://example.com/callback(路径不同)
❌ https://sub.example.com/auth/callback(子域名不同)

本地开发 Redirect URI #

text
本地开发时可以使用:

http://localhost:3000/callback
http://127.0.0.1:3000/callback
http://[::1]:3000/callback

注意:
- 仅用于开发环境
- 生产环境必须使用 HTTPS

错误响应 #

授权错误 #

text
┌─────────────────────────────────────────────────────────────┐
│                    授权错误响应                              │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  错误通过 redirect_uri 返回:                               │
│                                                             │
│  https://client.example.com/cb?error=access_denied          │
│  &error_description=The%20user%20denied%20access            │
│  &state=xyz                                                 │
│                                                             │
│  标准错误码:                                               │
│  ├── invalid_request:请求参数错误                          │
│  ├── unauthorized_client:客户端未授权                      │
│  ├── access_denied:用户拒绝授权                            │
│  ├── unsupported_response_type:不支持的响应类型            │
│  ├── invalid_scope:无效的授权范围                          │
│  ├── server_error:服务器错误                               │
│  └── temporarily_unavailable:服务暂时不可用                │
│                                                             │
└─────────────────────────────────────────────────────────────┘

令牌错误 #

json
{
  "error": "invalid_grant",
  "error_description": "The provided authorization code is invalid or expired.",
  "error_uri": "https://auth.example.com/docs/errors/invalid_grant"
}

令牌错误码 #

错误码 描述
invalid_request 请求缺少必需参数
invalid_client 客户端认证失败
invalid_grant 授权码/刷新令牌无效
unauthorized_client 客户端未授权使用此授权类型
unsupported_grant_type 不支持的授权类型
invalid_scope 请求的范围无效

概念关系图 #

text
┌─────────────────────────────────────────────────────────────┐
│                    OAuth 核心概念关系                        │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                     ┌─────────────┐                         │
│                     │   Client    │                         │
│                     │  (客户端)    │                         │
│                     └──────┬──────┘                         │
│                            │                                │
│              ┌─────────────┼─────────────┐                  │
│              │             │             │                  │
│              ▼             ▼             ▼                  │
│     ┌─────────────┐ ┌─────────────┐ ┌─────────────┐        │
│     │ Client ID   │ │ Client Type │ │ Redirect URI│        │
│     │             │ │             │ │             │        │
│     └─────────────┘ └─────────────┘ └─────────────┘        │
│                            │                                │
│                            ▼                                │
│                     ┌─────────────┐                         │
│                     │ Grant Type  │                         │
│                     │ (授权类型)   │                         │
│                     └──────┬──────┘                         │
│                            │                                │
│              ┌─────────────┼─────────────┐                  │
│              │             │             │                  │
│              ▼             ▼             ▼                  │
│     ┌─────────────┐ ┌─────────────┐ ┌─────────────┐        │
│     │Authorization│ │   Token     │ │  Refresh    │        │
│     │   Endpoint  │ │  Endpoint   │ │  Endpoint   │        │
│     └──────┬──────┘ └──────┬──────┘ └─────────────┘        │
│            │               │                                │
│            │               ▼                                │
│            │        ┌─────────────┐                         │
│            │        │   Tokens    │                         │
│            │        │  (令牌)      │                         │
│            │        └──────┬──────┘                         │
│            │               │                                │
│            │     ┌─────────┼─────────┐                      │
│            │     │         │         │                      │
│            │     ▼         ▼         ▼                      │
│            │ ┌────────┐ ┌────────┐ ┌────────┐              │
│            │ │Access  │ │Refresh │ │  ID    │              │
│            │ │ Token  │ │ Token  │ │ Token  │              │
│            │ └────────┘ └────────┘ └────────┘              │
│            │               │                                │
│            └───────────────┼────────────────┐               │
│                            │                │               │
│                            ▼                ▼               │
│                     ┌─────────────┐  ┌─────────────┐        │
│                     │   Scope     │  │   State     │        │
│                     │ (授权范围)   │  │ (状态参数)   │        │
│                     └─────────────┘  └─────────────┘        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

下一步 #

现在你已经掌握了 OAuth 的核心概念,接下来学习 授权码模式,了解最安全、最完整的授权流程!

最后更新:2026-03-28