身份验证
所有 IDCloud API(Web & SDK 和 API 合约)均使用 OAuth2 with JWT Bearer Grant Type(RFC 7523)。您在后端生成一个短期 JWT assertion,将其换取 Bearer 令牌,并在后续每次调用中使用该令牌。
请勿在客户端执行此操作
JWT assertion 必须仅在您的后端生成。切勿在前端代码、移动应用、代码仓库或日志中暴露您的私钥。
获取凭据
在生成令牌之前,您需要由 Unico 提供的服务账号。请联系 Unico 支持团队并提供以下信息:
- 服务账号名称(最多 12 个字符)
- 负责人的姓名、电子邮件和电话号码(仅限巴西、美国或墨西哥号码)
您将收到:
- 唯一账号名称
- 租户 ID
- 基础 JWT payload
- 私钥文件(
.pem格式)
每个环境一个账号
请为 UAT 和生产环境分别保留独立的服务账号。
构建 JWT assertion
assertion 是紧凑 JWS 格式的 JWT:{Base64url(Header)}.{Base64url(Payload)}.{Base64url(Signature)}。
Header
{
"alg": "RS256",
"typ": "JWT"
}
Payload
| 声明 | 值 | 说明 |
|---|---|---|
iss | <account_name>@<tenant_id>.iam.acesso.io | 随凭据一同提供 |
aud | https://identityhomolog.acesso.io(UAT)或 https://identity.acesso.io(生产) | 必须与令牌端点主机匹配 |
scope | * | 授予所有权限 |
iat | Unix 时间戳(秒) | JWT 签发时间 |
exp | iat + 最多 3600 | 不得超过 iat 起 1 小时 |
{
"aud": "https://identity.acesso.io",
"scope": "*",
"iat": 1738086000,
"exp": 1738089600
}
Signature
使用 Unico 提 供的 .pem 私钥,通过 RS256(RSA + SHA-256)对 header + payload 进行签名。
请勿添加额外声明
上述列表之外的任何字段(例如 sub、jti、nbf)都会导致 1.2.22 错误。请仅使用所示的声明。
请求令牌
令牌端点对两种合约均相同:
| 环境 | 端点 |
|---|---|
| 生产 | POST https://identity.acesso.io/oauth2/token |
| UAT | POST https://identityhomolog.acesso.io/oauth2/token |
Request
| 参数 | 值 |
|---|---|
Content-Type | application/x-www-form-urlencoded |
grant_type | urn:ietf:params:oauth:grant-type:jwt-bearer |
assertion | 您已签名的 JWT |
- cURL
- Node.js
- Python
curl -X POST https://identity.acesso.io/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \
-d "assertion=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
import jwt from 'jsonwebtoken';
import fs from 'fs';
import qs from 'querystring';
const privateKey = fs.readFileSync('./private-key.pem');
const now = Math.floor(Date.now() / 1000);
const assertion = jwt.sign(
{
aud: 'https://identity.acesso.io',
scope: '*',
iat: now,
exp: now + 3600,
},
privateKey,
{ algorithm: 'RS256' }
);
const res = await fetch('https://identity.acesso.io/oauth2/token', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: qs.stringify({
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion,
}),
});
const { access_token, expires_in } = await res.json();
import time
import jwt # PyJWT
import requests
with open("private-key.pem", "rb") as f:
private_key = f.read()
now = int(time.time())
assertion = jwt.encode(
{
"aud": "https://identity.acesso.io",
"scope": "*",
"iat": now,
"exp": now + 3600,
},
private_key,
algorithm="RS256",
)
response = requests.post(
"https://identity.acesso.io/oauth2/token",
data={
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion,
},
)
token_data = response.json()
access_token = token_data["access_token"]
Response
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
}
| 字段 | 类型 | 说明 |
|---|---|---|
access_token | string | JWT 访问令牌。在所有 API 调用中通过 Authorization: Bearer <token> 使用。 |
expires_in | integer | 过期时间(秒)。示例:3600。 |
token_type | string | 始终为 Bearer。 |
使用令牌
在每个 API 请求的 Authorization 头中添加令牌。两种合约的头格式相同——不同之处在于所调用 API 的主机和路径:
| 合约 | 生产主机 | UAT 主机 |
|---|---|---|
| Web & SDK | https://api.idcloud.unico.app | https://api.idcloud.uat.unico.app |
| API | https://api.id.unico.app | https://api.id.uat.unico.app |
Web & SDK — 仅需要 Authorization 头:
curl -X POST https://api.idcloud.unico.app/client/v1/process \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{ ... }'
API — Authorization 与 APIKEY 头一起使用:
curl -X POST https://api.id.unico.app/processes/v1 \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "APIKEY: $API_KEY" \
-H "Content-Type: application/json" \
-d '{ ... }'