4. Mock Token 端点实现:模拟 /oauth/token 接口,返回固定格式的 Access Token 与 Refresh Token

在依赖隔离调试中,真实授权服务器(AS)往往不可用或响应不稳定。通过 Mock 一个 /oauth/token 端点,我们可以让被测系统(SUT)在完全可控的 Token 响应下运行,从而聚焦于业务逻辑与 Token 生命周期管理。

4.1 Mock 端点核心职责

Mock Token 端点需要模拟授权服务器在 Client Credentials 与 Authorization Code 两种最常用流程下的 Token 颁发行为。其核心职责包括:

  • 请求验证:检查 grant_type、client_id、client_secret 等必填参数。
  • 固定响应:返回预定义的 Access Token、Refresh Token、Token 类型及过期时间。
  • 状态模拟:支持模拟成功响应、参数错误、客户端认证失败等场景。
关键原则:Mock 端点不执行真实签名或加密,仅返回符合 OAuth2.0 规范结构的静态 Token 字符串,便于调试时人工识别与断言。

4.2 接口规范与参数清单

下表列出了 Mock /oauth/token 端点支持的请求参数与固定响应字段:

方向 参数 / 字段 类型 说明
请求 grant_type string 固定为 client_credentials 或 authorization_code
client_id string 预置客户端标识,如 mock-client
client_secret string 预置客户端密钥,如 mock-secret
code string 仅 authorization_code 时需要,固定为 mock-auth-code
响应 access_token string 固定值 mock-access-token-v1
token_type string 固定为 Bearer
expires_in int 固定为 3600(1 小时)
refresh_token string 固定值 mock-refresh-token-v1
scope string 固定为 read write

4.3 Mock 端点处理流程

下图展示了 Mock Token 端点的内部处理逻辑与状态分支:

Mock /oauth/token 端点处理流程 接收 POST 请求 参数完整性校验 grant_type 判断 client_credentials 处理 authorization_code 处理 组装固定 Token 响应 返回 200 + JSON

4.4 代码实现示例(Node.js + Express)

以下是一个轻量级 Mock Token 端点的实现,使用 Express 框架,支持两种 grant_type 并返回固定 Token:

const express = require('express');
const app = express();
app.use(express.json());

const MOCK_CLIENTS = {
  'mock-client': { secret: 'mock-secret', grants: ['client_credentials', 'authorization_code'] }
};

const MOCK_TOKENS = {
  access_token: 'mock-access-token-v1',
  token_type: 'Bearer',
  expires_in: 3600,
  refresh_token: 'mock-refresh-token-v1',
  scope: 'read write'
};

app.post('/oauth/token', (req, res) => {
  const { grant_type, client_id, client_secret, code } = req.body;

  // 1. 参数完整性校验
  if (!grant_type || !client_id || !client_secret) {
    return res.status(400).json({ error: 'invalid_request', error_description: 'Missing required parameters' });
  }

  // 2. 客户端认证
  const client = MOCK_CLIENTS[client_id];
  if (!client || client.secret !== client_secret) {
    return res.status(401).json({ error: 'invalid_client', error_description: 'Client authentication failed' });
  }

  // 3. grant_type 分支处理
  if (grant_type === 'client_credentials') {
    return res.status(200).json(MOCK_TOKENS);
  }

  if (grant_type === 'authorization_code') {
    if (code !== 'mock-auth-code') {
      return res.status(400).json({ error: 'invalid_grant', error_description: 'Invalid authorization code' });
    }
    return res.status(200).json(MOCK_TOKENS);
  }

  // 4. 不支持的 grant_type
  return res.status(400).json({ error: 'unsupported_grant_type', error_description: 'Grant type not supported' });
});

app.listen(4000, () => console.log('Mock OAuth2 Token endpoint running on port 4000'));

4.5 测试验证与调试技巧

启动 Mock 服务后,可以使用 curl 快速验证端点行为:

# 测试 Client Credentials 流程
curl -X POST http://localhost:4000/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"client_credentials","client_id":"mock-client","client_secret":"mock-secret"}'

# 测试 Authorization Code 流程
curl -X POST http://localhost:4000/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"authorization_code","client_id":"mock-client","client_secret":"mock-secret","code":"mock-auth-code"}'

# 测试错误场景:无效客户端
curl -X POST http://localhost:4000/oauth/token \
  -H "Content-Type: application/json" \
  -d '{"grant_type":"client_credentials","client_id":"invalid","client_secret":"wrong"}'
调试建议:在集成测试中,将 SUT 的 Token 端点 URL 替换为 http://localhost:4000/oauth/token,即可在不依赖真实授权服务器的情况下,验证 Token 获取、缓存、刷新及过期处理逻辑。

4.6 常见 Mock 场景对照

测试场景 触发条件 预期响应 调试目标
正常 Token 获取 合法 client_id + secret 200 + 固定 Token JSON 验证 SUT 正确解析 Token 字段
客户端认证失败 错误 client_secret 401 + invalid_client 验证 SUT 错误处理与重试逻辑
无效授权码 authorization_code + 错误 code 400 + invalid_grant 验证 SUT 授权码校验分支
不支持的 grant_type grant_type = password 400 + unsupported_grant_type 验证 SUT 是否过滤非法流程
注意:Mock 端点返回的 Token 不具备真实签名,切勿在生产环境或安全测试中使用。本 Mock 仅用于依赖隔离调试,确保 SUT 在可控输入下正确运行。