YOS-Pass 统一身份认证

为第三方应用提供安全、便捷的扫码登录解决方案

版本 2.0  |  广东思丞技术支持服务中心 荣誉出品
平台官网:https://auth.ycceo.com/YOS-Pass/ 主站官网:https://ycceo.com

关于 YOS-Pass

YOS-Pass 是由 广东思丞技术支持服务中心 研发的新一代统一身份认证平台。 它基于 OAuth 2.0 思想,采用二维码扫码 + JWT Token 签名验证机制,为 Web、App、小程序等多端应用提供安全、快捷的登录服务。

通过 YOS-Pass,你的用户无需记住账号密码,只需使用 YOS 万象 IOA App 扫描二维码,即可一键完成登录, 同时你的应用无需存储用户密码,大幅降低安全风险。

已接入 支持管理员 支持第三方应用 签名防篡改

计费说明

计费项单价计费时机说明
扫码登录成功2 元/次Token 签发时用户扫码确认授权后,YOS-Pass 生成 access_token 时自动扣费
发起登录请求免费调用 start_login 创建二维码不收费
轮询状态免费调用 session_status 轮询不收费

接入流程

第三方应用接入 YOS-Pass 只需以下 5 个步骤:

  1. 注册应用:在管理员后台创建接入方,获得 app_keyapp_secret
  2. 发起登录:你的服务端使用 app_keyapp_secret 生成签名,调用 api/start_login.php,获取二维码数据。
  3. 展示 & 扫码:将二维码展示给用户,用户使用 YOS 万象 IOA App 扫描。
  4. 获取令牌:前端轮询 api/session_status.php,授权成功后获得 access_token(JWT 格式)。
  5. 验证令牌:你的服务端对 access_token 进行 JWT 签名验证,通过后完成登录。

推荐 如果你的 App 或网站不想自行实现轮询,可以使用我们提供的 通用登录页login.php),只需跳转链接即可完成全流程。

API 接口文档

发起登录

POST https://auth.ycceo.com/YOS-Pass/api/start_login.php

请求头

Content-Type: application/json
X-Request-Signature: {HMAC-SHA256}

请求体

{
  "app_key": "your_app_key",
  "app_secret": "your_app_secret",
  "timestamp": 1234567890,
  "nonce": "random_string"
}

返回(成功)

{
  "success": true,
  "error_code": 0,
  "session_id": "64位hex",
  "qr_data": "base64编码的JSON",
  "expires_in": 150
}

返回(失败)

{
  "success": false,
  "error_code": 4004,
  "message": "域名不在白名单内"
}

轮询状态

GET https://auth.ycceo.com/YOS-Pass/api/session_status.php?session_id={sid}

返回(待授权)

{
  "status": "pending",
  "success": true,
  "message": "等待扫码授权"
}

返回(已授权)

{
  "status": "authorized",
  "success": true,
  "access_token": "jwt_token"
}

返回(已过期)

{
  "status": "expired",
  "error_code": 1002,
  "message": "二维码已过期"
}

提示 建议轮询间隔 2 秒,超时 150 秒。

App 扫码授权(统一接口)

POST https://auth.ycceo.com/YOS-Pass/authorize.php

请求体

{
  "session_id": "xxx",
  "signature": "HMAC签名",
  "timestamp": 1234567890
}

返回

{
  "success": true,
  "error_code": 0,
  "message": "授权成功",
  "access_token": "token",
  "type": "admin" 或 "app"
}

此接口同时支持管理员二维码和第三方二维码,自动识别类型。签名算法:HMAC-SHA256(session_id|timestamp, app_secret)

密钥体系说明

整个接入流程涉及 两类密钥,各自用途不同,请勿混淆:

密钥名称存储位置用途
app_secret
每 App 独立
YOS-Pass DB
also in your config.php
① start_login 请求签名(youquan → YOS-Pass)
② authorize 扫码签名(YOS IOA App → YOS-Pass)
③ JWT Token 签发(YOS-Pass complete_login)
YOS_APP_SECRET
每 App 独立
your config.php ④ JWT Token 验签(your app 服务端本地)
值等于你的 app_secret

关键 ③ JWT 签发和④ JWT 验签使用同一把密钥(你自己的 app_secret),而非系统全局密钥。 每个 App 的密钥独立,互不干扰——你的 app_secret 只签你自己的 Token。

请求时序:谁发什么、用什么密钥

┌──────────────┐                ┌──────────────┐                ┌──────────────┐
│   youquan    │                │   YOS-Pass   │                │  YOS IOA App │
│  (第三方App)  │                │   (认证服务)  │                │   (扫码端)    │
└──────┬───────┘                └──────┬───────┘                └──────┬───────┘
       │                               │                               │
       │ ① POST start_login             │                               │
       │   签名: YOS_APP_SECRET         │                               │
       │   Body: {app_key, ts, nonce}   │                               │
       ├──────────────────────────────►│                               │
       │                               │                               │
       │ ◄── {session_id, qr_data}     │                               │
       │                               │                               │
       │ ② 展示二维码                    │                               │
       │                               │         ③ POST authorize      │
       │                               │ 签名: app_secret               │
       │                               │ Body: {session_id, sig, ts}   │
       │                               │◄──────────────────────────────┤
       │                               │                               │
       │                               │ DB: status=1 ────────────────►│
       │                               │                               │
       │ ④ GET session_status           │                               │
       │   ?session_id=xxx             │                               │
       ├──────────────────────────────►│                               │
       │                               │ complete_login()              │
       │                               │ JWT 签名: app_secret          │
       │                               │                               │
       │ ◄── {access_token: JWT}       │                               │
       │                               │                               │
       │ ⑤ 本地 verifyJwt()             │                               │
       │   密钥: YOS_APP_SECRET         │                               │
       │   → 验签通过,登录成功           │                               │
步骤请求方目标签名/验签密钥
youquan 服务端YOS-Pass start_loginYOS_APP_SECRET(每App独立)
youquan 前端用户浏览器无需密钥(纯展示)
YOS IOA AppYOS-Pass authorizeapp_secret(从DB读取)
youquan 前端YOS-Pass session_status无需签名(GET请求)
youquan 服务端本地 JWT 验签YOS_APP_SECRET(即你的 app_secret)

Token 格式与验证

扫码授权成功后返回的 access_token 是一个 JWT(JSON Web Token), 你的服务端必须对该 Token 进行签名验证后才能信任其中的用户身份, 否则相当于未做任何鉴权。以下是完整规范:

4.1 Token 结构

Token 由三段组成,以 "." 分隔:header.payload.signature

// Header(固定)
{
  "alg": "HS256",
  "typ": "JWT"
}

// Payload 示例
{
  "user_id": 1,
  "exp": 1783810118,
  "iat": 1783802918
}
字段说明
alg签名算法,固定为 HS256(HMAC-SHA256)
typToken 类型,固定为 JWT
user_id用户唯一标识
iatToken 签发时间(Unix 时间戳)
expToken 过期时间(Unix 时间戳),默认有效期为签发后 2 小时(7200 秒)

4.2 签名密钥

重要 JWT 签名密钥是你自己的 app_secret。 YOS-Pass 在 complete_login() 中会从数据库查出你注册的 app_secret 来签发 Token。 你需要在服务端配置 YOS_APP_SECRET 为与 app_secret 相同的值来验证 Token。 不同 App 的密钥独立,天然隔离,一个 App 的 Token 无法被另一个 App 用来验签。

4.3 编码方式

注意 YOS-Pass 的 JWT 使用 标准 Base64 编码 (PHP 的 base64_encode / base64_decode), 不是 JWT 规范中的 Base64URL 编码。 这意味着编码结果中可能包含 +/= 字符。

4.4 验证流程

  1. 以 "." 分割 Token,得到三部分:Header、Payload、Signature
  2. 对 Header 和 Payload 分别做标准 Base64 解码,得到 JSON 原始数据
  3. 校验 exp 是否已过期(建议额外加上 ±90 秒的时钟偏差容忍)
  4. 使用 YOS-Pass 统一密钥对 "Header.Payload"(拼接时使用原始 Base64 编码值,不含 "." 且不做二次解码)做 HMAC-SHA256 签名
  5. 将计算结果与 Token 中的 Signature 做 Base64 解码后按原始字节比对
  6. 验签通过后,从 Payload 中取出 user_id 完成登录

4.5 PHP 验证代码

/**
 * 验证 YOS-Pass JWT Token
 * @param string $token   完整的 JWT Token 字符串
 * @param string $secret  YOS-Pass 统一签名密钥(从管理员处获取)
 * @return array|false    验签成功返回 payload 数组,失败返回 false
 */
function verifyYosToken($token, $secret) {
    $parts = explode('.', $token);
    if (count($parts) !== 3) {
        return false;  // Token 格式错误
    }

    list($headerB64, $payloadB64, $signatureB64) = $parts;

    // 使用标准 base64_decode(非 base64url)
    $header    = json_decode(base64_decode($headerB64), true);
    $payload   = json_decode(base64_decode($payloadB64), true);
    $signature = base64_decode($signatureB64);

    if (!$header || !$payload || !$signature) {
        return false;  // 解码失败
    }

    // 校验算法
    if ($header['alg'] !== 'HS256') {
        return false;
    }

    // 校验过期时间(±90 秒时钟偏差容忍)
    if (isset($payload['exp']) && time() - 90 > $payload['exp']) {
        return false;  // Token 已过期
    }

    // 计算签名:签名原文为 "headerB64.payloadB64"(原始 Base64 字符串,不做二次编码)
    $expectedSig = hash_hmac('sha256', $headerB64 . '.' . $payloadB64, $secret, true);

    // 二进制安全比对
    if (!hash_equals($expectedSig, $signature)) {
        return false;  // 签名不匹配
    }

    return $payload;
}

// 使用示例:
// $payload = verifyYosToken($_POST['access_token'], $jwtSecret);
// if ($payload) {
//     $_SESSION['user_id'] = $payload['user_id'];
// } else {
//     die('Token 验证失败');
// }

4.6 常见错误

请求签名机制

所有 POST 请求(除授权接口外)必须在请求头 X-Request-Signature 中携带 HMAC-SHA256 签名, 签名原文为 整个请求体(raw body),密钥为 app_secret,签名结果经 Base64 编码。

// PHP 服务端签名示例
$secret = 'your_app_secret';
$body = file_get_contents('php://input');
$signature = base64_encode(hash_hmac('sha256', $body, $secret, true));
// JavaScript(浏览器)签名示例(仅用于测试)
const signature = CryptoJS.HmacSHA256(body, appSecret).toString(CryptoJS.enc.Base64);

错误码对照表

所有接口返回的错误码定义如下,便于您快速定位问题。

错误码 常量 说明
0ERR_SUCCESS成功
1001ERR_QR_GENERATE_FAIL二维码生成失败
1002ERR_QR_EXPIRED二维码已过期
1003ERR_QR_INVALID_SESSION无效会话
2001ERR_APP_NOT_FOUND应用不存在
2002ERR_APP_DISABLED应用已禁用
3001ERR_RATE_LIMIT速率限制
3002ERR_QUOTA_EXCEEDED可用余额不足
4001ERR_MISSING_PARAM缺少必要参数
4002ERR_INVALID_SIGNATURE签名无效
4003ERR_TIMESTAMP_INVALID时间戳无效或已过期
4004ERR_DOMAIN_NOT_ALLOWED域名不在白名单内
4005ERR_SESSION_USED会话已使用
4006ERR_SESSION_NOT_FOUND会话不存在
4007ERR_MISSING_SESSION_ID缺少 session_id
4008ERR_MISSING_SIGNATURE缺少签名或时间戳
4009ERR_REQUEST_EXPIRED请求已过期
5000ERR_SERVER_ERROR服务器内部错误
5001ERR_TOKEN_GENERATE_FAIL令牌生成失败

快速开始(PHP)

// ===== 配置 =====
$jwtSecret  = 'YOS-Pass 统一签名密钥';  // 从管理员处获取
$appKey     = 'your_app_key';
$appSecret  = 'your_app_secret';

// ===== 1. 发起登录,获取二维码 =====
$apiUrl = 'https://auth.ycceo.com/YOS-Pass/api/start_login.php';
$data = [
    'app_key'    => $appKey,
    'app_secret' => $appSecret,
    'timestamp'  => time(),
    'nonce'      => bin2hex(random_bytes(8))
];
$body = json_encode($data);
$signature = base64_encode(hash_hmac('sha256', $body, $appSecret, true));

$ch = curl_init($apiUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-Request-Signature: ' . $signature
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$result = json_decode($response, true);

if ($result['success']) {
    $sessionId = $result['session_id'];
    $qrData = base64_decode($result['qr_data']);  // 用于生成二维码图片
    // 将 $qrData 或 $sessionId 传给前端
}

// ===== 2. 前端轮询(建议每 2 秒一次,超时 150 秒)=====
// GET https://auth.ycceo.com/YOS-Pass/api/session_status.php?session_id=xxx
// 当 status === 'authorized' 时,将 access_token 用 POST 提交给你的服务端

// ===== 3. 服务端验证 Token(你的 login callback)=====
// 收到前端传来的 access_token 后:
$token   = $_POST['access_token'];
$payload = verifyYosToken($token, $jwtSecret);  // verifyYosToken 见上文第 4 节

if ($payload) {
    $_SESSION['user_id'] = $payload['user_id'];
    // 登录成功,跳转或返回
} else {
    http_response_code(401);
    die(json_encode(['error' => 'Token 无效或已过期']));
}

安全建议

技术支持

如有接入问题或定制需求,请联系我们的技术支持团队: