Passport 身份认证平台接入文档
概述
Passport 是 Alaikis.com 的企业级 SaaS 身份认证平台,提供 OAuth 2.0 和 OpenID Connect (OIDC) 协议,支持第三方应用快速接入。系统采用统一用户模型,管理员和终端用户共用 user 表。
核心概念
| 概念 | 说明 |
|---|---|
| App | 一个产品/服务,如 "CRM系统",共享 logo 和用户池 |
| Client | App 下的 OAuth 实例,代表一个使用场景(内部/B2B/公开) |
| client_id | Client 的唯一标识,OAuth 流程入口(公开标识,泄露无害) |
| client_secret | Client 密钥,仅服务端使用,不嵌入客户端 |
| open_id | 用户在某个 App 下的唯一标识(app_user.id) |
平台入口
| 系统 | 域名 | 说明 |
|---|---|---|
| 管理后台 | https://authhub.alaikis.com/adm/ | 管理员登录、用户/应用/客户端管理 |
| 商户中心 | https://id.alaikis.com/mc/ | 商户登录、应用/用户/社交登录配置 |
| 用户中心 | https://account.alaikis.com/u/ | 用户登录、注册、找回密码 |
| API 服务 | https://passport.alaikis.com | OAuth/API 接口 |
| 授权页面 | https://auth.alaikis.com | OAuth 授权页面 |
接入方式选择
| 方式 | 适用场景 | 需要的凭证 | 安全等级 |
|---|---|---|---|
| 桌面简化登录 | 桌面客户端、CLI、AI Agent | client_id + 用户密码 | ★★★ |
| OAuth 授权码 | Web 应用(有服务端) | client_id + client_secret | ★★★★★ |
| OAuth Implicit | 纯前端 SPA | client_id | ★★★★ |
| SSO 跨应用 | 多应用统一登录 | sso_session_id | ★★★★ |
| 社交登录 | 微信/Facebook/LinkedIn 等 | identity_source 配置 | ★★★★ |
桌面客户端简化登录(推荐)
AI 时代的简化授权方案。桌面客户端、CLI 工具、AI Agent 只需 client_id + 用户账号密码,直接获取 token。
安全设计
- client_id 是公开标识(类似 Google OAuth),泄露无害
- client_secret 不嵌入客户端,逆向工程无法获取
- 用户密码由用户输入,不存储在客户端
- 自动绑定用户到应用(首次登录自动激活)
- 不需要回调地址(callback_url)
登录
curl -X POST "https://passport.alaikis.com/api/v1/open/user/desktop/login" \
-H "Content-Type: application/json" \
-d '{
"client_id": "8755645",
"account": "user@example.com",
"password": "your_password"
}'
参数:
| 参数 | 必填 | 说明 |
|---|---|---|
client_id | 是 | 客户端 ID(数字或名称均可) |
account | 是 | 邮箱 / 用户名 / 手机号 |
password | 是 | 用户密码 |
响应:
{
"code": 200,
"data": {
"access_token": "6bc4b62df9cf6ed19b4884810fca3d04",
"token_type": "bearer",
"refresh_token": "250b340cdf8794cea7da1d9a5be11b7c",
"sso_session_id": "a1d50f92f322b0f66a4d1d6dcb9dd489...",
"open_id": 101,
"user_id": 3,
"user_name": "alex",
"email": "alex@example.com",
"merchant_id": 1,
"expires_in": 3600,
"refresh_token_expires_in": 2592000
}
}
Token 刷新
access_token 有效期 1 小时,过期前用 refresh_token 刷新获取新的 access_token。refresh_token 有效期 30 天,每次刷新滚动续期。
curl -X POST "https://passport.alaikis.com/api/v1/open/user/desktop/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "250b340cdf8794cea7da1d9a5be11b7c"
}'
响应:
{
"code": 200,
"data": {
"access_token": "a82e3e314f936e6955adaa5151aba13f",
"token_type": "bearer",
"refresh_token": "250b340cdf8794cea7da1d9a5be11b7c",
"expires_in": 3600,
"refresh_token_expires_in": 2592000
}
}
Token 生命周期:
| Token | 有效期 | 说明 |
|---|---|---|
access_token | 1 小时 | API 调用凭证,过期后需刷新 |
refresh_token | 30 天 | 刷新 access_token,每次刷新滚动续期 |
刷新流程:
登录 → access_token (1h) + refresh_token (30d)
↓ access_token 过期前
刷新 → 新 access_token (1h) + refresh_token 续期 (30d)
↓ 30天无活动
refresh_token 过期 → 需重新登录
获取用户信息
curl -H "auth-token: YOUR_DEV_TOKEN" \
-d "uid=101" \
"https://passport.alaikis.com/api/v1/user/profile/detail"
社交登录
Passport 支持商户级别配置社交登录,用户可通过微信、Facebook、LinkedIn 等第三方平台登录。
支持的平台
| 平台 | 配置字段 | 授权流程 |
|---|---|---|
| 微信 | AppID, AppSecret | 扫码登录 (qrconnect) |
| App ID, App Secret | OAuth 2.0 | |
| Client ID, Client Secret | OAuth 2.0 / OIDC | |
| Client ID, Client Secret | OIDC | |
| GitHub | Client ID, Client Secret | OAuth 2.0 |
| Microsoft | Client ID, Client Secret | OIDC |
| 自定义 OIDC | Client ID, Secret + 端点 | 标准 OIDC |
商户配置流程
- 商户登录商户中心
https://id.alaikis.com/mc/ - 进入「社交登录」页面
- 点击「新建身份源」→ 选择平台
- 填入对应平台的 AppID/AppSecret
- 系统自动生成回调地址:
https://passport.alaikis.com/oidc/callback/{id} - 在社交平台后台配置该回调地址
发起社交登录
GET https://passport.alaikis.com/oidc/federate/{identity_source_id}
用户访问此 URL 后,重定向到社交平台授权页面。授权完成后回调到 Passport,自动创建/匹配用户。
多商户个性化
每个商户独立配置自己的社交登录 IdP:
- 商户 A 可以配置自己的微信 AppID
- 商户 B 可以配置不同的 Facebook 应用
- 用户通过社交登录后自动归属到对应商户
OAuth 2.0 标准授权流程
适用于有服务端的 Web 应用。
1. 授权 URL 构造
GET https://passport.alaikis.com/oauth/v2/authorize
| 参数 | 必填 | 说明 |
|---|---|---|
client_id | 是 | 客户端 ID |
response_type | 是 | code(推荐)或 token |
redirect_url | 是 | 授权回调地址 |
scope | 否 | 权限范围,默认 get_user_info |
state | 否 | 状态参数,防止 CSRF |
2. 换取 Token
curl -X POST "https://passport.alaikis.com/api/v1/token" \
-H "auth-token: YOUR_DEV_TOKEN" \
-d "code=xxx"
注册
Passport 区分两种注册:商户注册和用户注册。
| 类型 | 前端页面 | API | 说明 |
|---|---|---|---|
| 商户注册 | https://authhub.alaikis.com/customer/auth/register | POST /customer/auth/register | 创建商户 + Internal App + 管理员账号 |
| 用户注册 | https://account.alaikis.com/u/register?client_id=XXX | POST /api/v1/open/user/register | 用户注册到指定应用 |
商户注册
商户注册会自动创建:
- 商户 (merchant)
- 内部管理应用 (app, type=internal)
- OAuth 客户端 (client)
- 管理员用 户 (user) + admin 角色
访问 https://authhub.alaikis.com/customer/auth/register 或通过 API:
curl -X POST "https://passport.alaikis.com/customer/auth/register" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "email=business@example.com&password=your_password&name=公司名称"
用户注册
第三方应用引导用户到用户中心注册,需传入 client_id:
前端页面: https://account.alaikis.com/u/register?client_id=8755645
1. 获取验证码
curl -X POST "https://passport.alaikis.com/api/v1/open/user/verify/send" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "account=user@example.com&type=email&client_id=8755645"
2. 注册
curl -X POST "https://passport.alaikis.com/api/v1/open/user/register" \
-H "Content-Type: application/json" \
-d '{
"client_id": "8755645",
"account": "user@example.com",
"password": "your_password",
"code": "123456"
}'
公开应用注册自动激活(state=1),私有应用待激活(state=0)
找回密码
前端页 面: https://account.alaikis.com/u/forgot-password
1. 发送重置验证码
curl -X POST "https://passport.alaikis.com/api/v1/open/user/reset/send" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "account=user@example.com&client_id=8755645"
2. 重置密码
curl -X POST "https://passport.alaikis.com/api/v1/open/user/reset" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "account=user@example.com&code=123456&password=new_password&client_id=8755645"
登录
前端页面:
| 系统 | 登录页面 |
|---|---|
| 管理后台 | https://authhub.alaikis.com/adm/login |
| 商户中心 | https://id.alaikis.com/mc/login |
| 用户中心 | https://account.alaikis.com/u/login |
API 调用
curl -X POST "https://passport.alaikis.com/api/v1/open/user/login" \
-H "Content-Type: application/json" \
-d '{
"client_id": "8755645",
"account": "user@example.com",
"password": "your_password"
}'
验证码登录
邮箱验证码登录
curl -X POST "https://passport.alaikis.com/api/v1/open/user/email/login" \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "code": "123456", "client_id": "8755645"}'
手机验证码登录
curl -X POST "https://passport.alaikis.com/api/v1/open/user/phone/login" \
-H "Content-Type: application/json" \
-d '{"tel": "13800138000", "code": "123456", "client_id": "8755645"}'
SSO 单点登录
用户登录任一应用后,获得 sso_session_id,可用于跨域访问其他应用。
验证 SSO Session
curl -X POST "https://passport.alaikis.com/api/v1/open/user/sso/session/validate" \
-H "X-SSO-Token: sso_session_xxx"
智能体统一 Token
用户登录 (1次) → SSO Session → Agent Token (1个) → 按需交换各应用 access_token
获取 Agent Token
curl -X POST "https://passport.alaikis.com/api/v1/open/agent/token" \
-H "Content-Type: application/json" \
-d '{"sso_session_id": "sso_session_xxx", "agent_id": "my_agent_001"}'
交换应用 Token
curl -X POST "https://passport.alaikis.com/api/v1/open/agent/token/exchange" \
-H "Content-Type: application/json" \
-d '{"agent_token": "agent_token_xxx", "app_id": 1}'
SLO 单点登出
curl -X POST "https://passport.alaikis.com/api/v1/open/user/sso/logout" \
-H "X-SSO-Token: sso_session_xxx"
密码管理
修 改密码
curl -X POST "https://passport.alaikis.com/api/v1/open/user/password/change" \
-H "Content-Type: application/json" \
-d '{"old_password": "current_password", "new_password": "new_password"}'
API 端点总览
用户认证(公开,无需 auth-token)
| 端点 | 方法 | 说明 |
|---|---|---|
/api/v1/open/user/desktop/login | POST | 桌面客户端简化登录(推荐) |
/api/v1/open/user/desktop/refresh | POST | 刷新 access_token |
/api/v1/open/user/login | POST | 标准密码登录 |
/api/v1/open/user/register | POST | 用户注册 |
/api/v1/open/user/verify/send | POST | 发送验证码 |
/api/v1/open/user/email/login | POST | 邮箱验证码登录 |
/api/v1/open/user/phone/login | POST | 手机验证码登录 |
/api/v1/open/user/reset/send | POST | 发送密码重置验证码 |
/api/v1/open/user/reset | POST | 重置密码 |
/api/v1/open/user/password/change | POST | 修改密码 |
/api/v1/open/user/sso/session/validate | POST | 验证 SSO Session |
/api/v1/open/user/sso/logout | POST | SSO 登出 |
/api/v1/open/agent/token | POST | 获取 Agent Token |
/api/v1/open/agent/token/exchange | POST | 交换应用 Token |
/api/v1/open/agent/apps | GET | 查询可访问应用 |
/api/v1/open/agent/token/revoke | POST | 撤销 Agent Token |
/oidc/federate/{id} | GET | 发起社交登录 |
/oidc/callback/{id} | GET | 社交登录回调 |
/oauth/v2/authorize | GET | OAuth 授权页面 |
/api/v1/token | POST | 换取/刷新 Token |
/api/v1/revoke | POST | 撤销 Token |
错误码
| 错误码 | 说明 |
|---|---|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未授权 / Token 无效 |
| 403 | 无权限 |
| 406 | 业务错误(如密码错误、用户不存在) |
| 429 | 请求过于频繁 |
| 500 | 服务器错误 |
桌面客户端集成示例
Python
import requests
import time
PASSPORT = "https://passport.alaikis.com"
CLIENT_ID = "8755645" # 公开标识,可硬编码
class PassportAuth:
def __init__(self):
self.access_token = None
self.refresh_token = None
self.expires_at = 0
def login(self, account, password):
resp = requests.post(f"{PASSPORT}/api/v1/open/user/desktop/login", json={
"client_id": CLIENT_ID,
"account": account,
"password": password
})
data = resp.json()["data"]
self.access_token = data["access_token"]
self.refresh_token = data["refresh_token"]
self.expires_at = time.time() + data["expires_in"]
return data
def refresh(self):
resp = requests.post(f"{PASSPORT}/api/v1/open/user/desktop/refresh", json={
"refresh_token": self.refresh_token
})
data = resp.json()["data"]
self.access_token = data["access_token"]
self.expires_at = time.time() + data["expires_in"]
return data
def get_token(self):
if time.time() > self.expires_at - 60:
self.refresh()
return self.access_token
auth = PassportAuth()
auth.login("user@example.com", "password")
token = auth.get_token()
Node.js
const PASSPORT = 'https://passport.alaikis.com'
const CLIENT_ID = '8755645'
async function login(account, password) {
const resp = await fetch(`${PASSPORT}/api/v1/open/user/desktop/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ client_id: CLIENT_ID, account, password })
}).then(r => r.json())
return resp.data
}
async function refresh(refreshToken) {
const resp = await fetch(`${PASSPORT}/api/v1/open/user/desktop/refresh`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ refresh_token: refreshToken })
}).then(r => r.json())
return resp.data
}
安全说明
- client_id 是公开标识,可以嵌入客户端(泄露无害)
- client_secret 是服务端密钥,不要嵌入客户端
- refresh_token 存储在本地,不要泄露给第三方
- access_token 有效期短(1小时),泄露风险可控
- 社交登录通过 OIDC 联邦流程,Passport 不接触用户社交平台密码
- 密码 bcrypt 加密存储
- JWT RS256 签名
- 登录失败自动锁定
协议支持
- OAuth 2.0 (RFC 6749)
- OpenID Connect 1.0
- JWT (RFC 7519)
- TOTP (RFC 6238)
- Token Exchange (RFC 8693)
- Token Refresh (RFC 6749 Section 6)