Files
new-api/docs/oauth2_setup.md
2025-09-08 12:09:26 +08:00

5.8 KiB

OAuth2 服务器设置指南

概述

该 OAuth2 服务器实现基于 RFC 6749 标准,支持以下特性:

  • 授权类型: Client Credentials, Authorization Code + PKCE, Refresh Token
  • JWT 访问令牌: 使用 RS256 签名
  • JWKS 端点: 公钥自动发布和轮换
  • 兼容性: 与现有认证系统完全兼容

配置

1. 环境变量配置

.env 文件中添加以下配置:

# OAuth2 基础配置
OAUTH2_ENABLED=true
OAUTH2_ISSUER=https://your-domain.com
OAUTH2_ACCESS_TOKEN_TTL=10
OAUTH2_REFRESH_TOKEN_TTL=720

# JWT 签名配置
JWT_SIGNING_ALGORITHM=RS256
JWT_KEY_ID=oauth2-key-1
JWT_PRIVATE_KEY_FILE=/path/to/private-key.pem

# 授权类型(逗号分隔)
OAUTH2_ALLOWED_GRANT_TYPES=client_credentials,authorization_code,refresh_token

# 强制 PKCE
OAUTH2_REQUIRE_PKCE=true

# 自动创建用户
OAUTH2_AUTO_CREATE_USER=false
OAUTH2_DEFAULT_USER_ROLE=1
OAUTH2_DEFAULT_USER_GROUP=default

2. 数据库迁移

重启应用程序将自动创建 oauth_clients 表。

3. 创建第一个 OAuth2 客户端

通过管理员界面或 API 创建客户端:

curl -X POST http://localhost:8080/api/oauth_clients \
  -H "Authorization: Bearer YOUR_ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "测试服务",
    "client_type": "confidential",
    "grant_types": ["client_credentials"],
    "scopes": ["api:read", "api:write"],
    "description": "用于服务对服务认证的测试客户端"
  }'

OAuth2 端点

标准端点

  • 令牌端点: POST /api/oauth/token
  • 授权端点: GET /api/oauth/authorize
  • JWKS 端点: GET /.well-known/jwks.json
  • 服务器信息: GET /.well-known/oauth-authorization-server

管理端点

  • 令牌内省: POST /api/oauth/introspect (需要管理员权限)
  • 令牌撤销: POST /api/oauth/revoke

客户端管理端点

  • 列出客户端: GET /api/oauth_clients
  • 创建客户端: POST /api/oauth_clients
  • 更新客户端: PUT /api/oauth_clients
  • 删除客户端: DELETE /api/oauth_clients/{id}
  • 重新生成密钥: POST /api/oauth_clients/{id}/regenerate_secret

使用示例

1. Client Credentials 流程

package main

import (
    "context"
    "golang.org/x/oauth2/clientcredentials"
)

func main() {
    cfg := clientcredentials.Config{
        ClientID:     "your_client_id",
        ClientSecret: "your_client_secret", 
        TokenURL:     "https://your-domain.com/api/oauth/token",
        Scopes:       []string{"api:read"},
    }
    
    client := cfg.Client(context.Background())
    resp, _ := client.Get("https://your-domain.com/api/protected")
    // 处理响应...
}

2. Authorization Code + PKCE 流程

package main

import (
    "context"
    "golang.org/x/oauth2"
)

func main() {
    conf := oauth2.Config{
        ClientID:     "your_web_client_id",
        ClientSecret: "your_web_client_secret",
        RedirectURL:  "https://your-app.com/callback",
        Scopes:       []string{"api:read"},
        Endpoint: oauth2.Endpoint{
            AuthURL:  "https://your-domain.com/api/oauth/authorize",
            TokenURL: "https://your-domain.com/api/oauth/token",
        },
    }
    
    // 生成 PKCE 参数
    verifier := oauth2.GenerateVerifier()
    
    // 构建授权 URL
    url := conf.AuthCodeURL("state", oauth2.S256ChallengeOption(verifier))
    
    // 用户授权后,使用授权码交换令牌
    token, _ := conf.Exchange(context.Background(), code, oauth2.VerifierOption(verifier))
    
    // 使用令牌调用 API
    client := conf.Client(context.Background(), token)
    resp, _ := client.Get("https://your-domain.com/api/protected")
}

3. cURL 示例

# 获取访问令牌
curl -X POST https://your-domain.com/api/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "client_id:client_secret" \
  -d "grant_type=client_credentials&scope=api:read"

# 使用访问令牌调用 API
curl -H "Authorization: Bearer ACCESS_TOKEN" \
  https://your-domain.com/api/status

安全建议

1. 密钥管理

  • 使用强随机密钥生成器
  • 定期轮换 RSA 密钥对
  • 将私钥存储在安全位置
  • 考虑使用 HSM 或密钥管理服务

2. 网络安全

  • 强制使用 HTTPS
  • 配置适当的 CORS 策略
  • 实现速率限制
  • 启用请求日志和监控

3. 客户端管理

  • 定期审查客户端列表
  • 撤销不再使用的客户端
  • 监控客户端使用情况
  • 为不同用途创建不同的客户端

4. Scope 和权限

  • 实施最小权限原则
  • 定期审查 scope 定义
  • 为敏感操作创建特殊 scope
  • 实现细粒度的权限控制

故障排除

常见问题

  1. "OAuth2 server is disabled"

    • 确保 OAUTH2_ENABLED=true
    • 检查配置文件是否正确加载
  2. "invalid_client"

    • 验证 client_id 和 client_secret
    • 确保客户端状态为启用
  3. "invalid_grant"

    • 检查授权类型是否被允许
    • 验证 PKCE 参数(如果启用)
  4. "invalid_scope"

    • 确保请求的 scope 在客户端配置中
    • 检查 scope 格式(空格分隔)

调试

启用详细日志:

GIN_MODE=debug
LOG_LEVEL=debug

检查 JWKS 端点:

curl https://your-domain.com/.well-known/jwks.json

验证令牌:

# 可以使用 https://jwt.io 解码和验证 JWT 令牌

生产部署

1. 负载均衡

  • OAuth2 服务器是无状态的,支持水平扩展
  • 确保所有实例使用相同的私钥
  • 使用 Redis 作为令牌存储

2. 监控

  • 监控令牌签发速率
  • 跟踪客户端使用情况
  • 设置异常告警

3. 备份

  • 备份私钥文件
  • 备份客户端配置数据
  • 制定灾难恢复计划

4. 性能优化

  • 启用 JWKS 缓存
  • 使用连接池
  • 优化数据库查询
  • 考虑使用 CDN 分发 JWKS