认证流程¶
本页逐个讲清每种对接流程。请根据平台对接指南中你的调用方类型选择对应 流程;时序图展示谁与谁通信,配方是可直接运行的请求。
| 流程 | 调用方 | 凭据 | 是否有交互用户 |
|---|---|---|---|
| A | 后端服务 → NL REST | OAuth2 client_credentials Bearer JWT |
否 |
| B | 后端 / 第三方 → NH 边缘数据 | Partner API key | 否 |
| C | 套件中的浏览器用户 → 任意产品 | NS 会话 + 网关 / 票据 | 是 |
| D | 设备或网关固件 | MQTT/HTTP 设备凭据 | 否 |
| E | 不随套件部署的产品 | OIDC 授权码 + PKCE | 是 |
身份概念(为什么只有一个身份平面、客户 IdP 接在哪里)见 SSO 与 OIDC。
流程 A —— 后端服务调用 NL(client_credentials)¶
用于没有交互用户、读取设备/遥测或下发命令的服务器。运维在 NL 中创建一个限定租户、带指定
scopes 的服务账号;你会拿到 client_id 与 client_secret。
sequenceDiagram
participant App as 你的后端
participant NL as NereidLink
App->>NL: POST /v1/auth/token(client_id + client_secret)
NL-->>App: access_token(JWT,expires_in 约 1800s)
App->>NL: GET /v1/tenants/{tenant}/devices<br/>Authorization: Bearer <token>
NL-->>App: 200 JSON
Note over App,NL: 收到 401:重新换 token(无 refresh token)
token 端点接受 JSON、表单或 HTTP Basic 三种凭据形式;仅支持
grant_type=client_credentials。
# 1)用服务账号凭据换取机器 token
TOKEN=$(curl -sS https://link.example/v1/auth/token \
-u "$NL_CLIENT_ID:$NL_CLIENT_SECRET" \
-H 'Content-Type: application/json' \
-d '{"grant_type":"client_credentials"}' | jq -r .access_token)
# 2)调用租户作用域 REST 端点
curl -sS "https://link.example/v1/tenants/$TENANT_ID/devices?page=1&page_size=50" \
-H "Authorization: Bearer $TOKEN"
Token 响应:{"access_token":"…","token_type":"Bearer","expires_in":1800}。
- 把 token 缓存到接近
expires_in;这里特意没有 refresh token——需要时再次出示 secret 换取。 - 同一 client id 反复失败会被临时锁,返回
429,与来源地址无关;secret 当作配置,切勿 记录日志。 - 同一 JWT 即 OpenAPI 文档中的
BearerAuth方案。 - 命令/控制类端点要求对应服务账号 scope;只读集成应只授予只读 scope。
流程 B —— 第三方读取 NH 边缘数据(partner key)¶
用于只需只读 Open Horizon 交换资源(服务、pattern、策略、节点、协议、用户、HA 组)的 外部系统。运维在控制台签发绑定某一组织的 partner key。
sequenceDiagram
participant P as 第三方系统
participant NH as NereidHorizon BFF
participant EX as Edge Exchange
P->>NH: GET /api/v1/{org}/nodes<br/>X-Api-Key: nk_live_…
NH->>NH: key 是否有效?org 是否匹配?是否 GET?
NH->>EX: 用共享 exchange 凭据代理
EX-->>NH: exchange 响应
NH-->>P: 200 JSON(调用记入审计日志)
curl -sS "https://horizon.example/api/v1/$ORG/nodes" \
-H "X-Api-Key: nk_live_<base64url>"
- Key 格式:
nk_live_<base64url>(生产)、nk_test_<base64url>(非生产)。Key 可设过期、 可吊销。 - 每次请求被强制限定在该 key 的 org:
?org=覆盖或路径 org 不一致一律403。只允许GET;任何修改返回403。 - 合作方不直接访问 Edge Exchange——BFF 持有一套共享 exchange 凭据,且每次调用写入只追加的 审计日志。
- 控制台 API(
openapi-console.yaml)是面向浏览器用户的另一套面(流程 C);合作方只用openapi-partner.yaml。
流程 C —— 套件内浏览器用户(SSO + 网关)¶
以 NS 为入口时,用户登录一次即可进入每个产品,无需再次登录。你的前端不处理密码,也接触不到 上游 token。
C.1 登录与网关¶
sequenceDiagram
participant U as 浏览器
participant NS as NereidSphere
participant NI as NereidIdentity
participant P as 产品(NL/NF/NH)
U->>NS: 打开门户(无会话)
NS->>NI: 授权码 + PKCE
NI-->>U: 品牌化登录(可经代理 IdP / MFA)
U->>NI: 完成认证
NI-->>NS: code → 服务端换 token,校验 id token
NS-->>U: 密封的 ns_session cookie(HttpOnly、SameSite)
U->>NS: GET /p/link/v1/tenants/t/devices(带 cookie)
NS->>P: 转发并注入 X-User-Id / X-User-Email / X-User-Roles
P-->>U: 响应
网关调用方规则:
- 在
/p/{product}/...下调用产品;前缀在转发前被剥除 (/p/link/v1/…→ NL origin 的/v1/…)。 - 凭据是
ns_sessioncookie——发同源/带凭据请求即可,无需出示 bearer token。 - 修改类请求要带双提交 CSRF 头
X-Csrf-Token,其值等于 JavaScript 可读的ns_csrfcookie。OPTIONS预检与服务间票据交换豁免。 - 不要自行发送
X-User-*或X-NS-Integration-Secret:入站副本总会被剥除,再由网关加盖 已验证的值。产品仅在请求来自网关时信任这些头。
C.2 进入独立托管的产品(票据)¶
浏览器只持有 NS cookie,因此进入独立托管的产品使用一次性交接票据(30 秒有效、单次使用、 绑定 audience):
sequenceDiagram
participant U as 浏览器
participant NS as NereidSphere
participant P as 产品后端
U->>NS: GET /auth/enter/{product}?to=/dashboard
NS->>NS: 解析会话;要求有 /nereid{product}/{tenant}/{role} 组
NS-->>U: 302 {product.url}/auth/ns-callback?ticket=…&to=/dashboard
U->>P: GET /auth/ns-callback?ticket=…
P->>NS: POST /api/v1/auth/ticket/verify<br/>X-NS-Client-Id / X-NS-Client-Secret
NS-->>P: 身份快照 + "to"
P-->>U: 产品本地会话
由产品后端(而非浏览器)核验票据:
POST https://sphere.example/api/v1/auth/ticket/verify
X-NS-Client-Id: link
X-NS-Client-Secret: <products[].sso_secret>
Content-Type: application/json
{"ticket":"..."}
响应携带已验证身份——sub、preferred_username、email、name、roles,以及 groups
(形如 /nereid{product}/{tenant}/{role} 的套件分配组)——还有相对路径 to。产品采用
默认拒绝:没有该产品分配组的用户会被退回门户;仅有身份不构成授权。随后产品签发自己的
常规会话(例如 NF 会签发本地 JWT,并为 X-Tenant-Id 解析租户)。
C.3 网关的另一种用法:external-auth¶
不想实现票据交换的产品/Ingress 可把认证委托给
GET https://<ns>/api/v1/auth/verify(Ingress external-auth)。有效会话返回 204 与需要
转发的 X-User-* 响应头;仅在已认证路径上信任这些头。
流程 D —— 设备与网关固件¶
物理设备与边缘网关不使用用户账号或 OAuth。它们用 NL 中预置的设备凭据认证,走南向线协议:
- 凭据:访问 token(MQTT 用户名)、
id + secret(Basic)、或双向 TLS(X.509)。 - 传输:MQTT 主题(直连设备
v1/me/*,网关 hello 之后v1/gateway/*)或 HTTP (/v1/me/telemetry、/v1/me/blob、长轮询命令)。 - 网关还需协商 hello/心跳/manifest,并中继子设备流量。
这本身是一条完整流程——请从设备 SDK(Go)、 直连设备接入与 网关接入开始。二进制遥测(图片/文档落 S3)见 二进制媒体与 S3 存储。为平台新增一种南向协议使用 适配器 SDK。
流程 E —— 独立产品对接你的 IdP(直接 OIDC)¶
不随套件门户销售/部署的产品,可作为标准 OIDC 依赖方直接对接 NI(NI 可代理你的企业 IdP):
- 为该产品注册带固定重定向 URI 的客户端;ROPC 已禁用,因此使用授权码 + PKCE。
- 从
https://<issuer>/auth/realms/nereidai/.well-known/openid-configuration获取端点。 - 在服务端完成换码,对照 JWKS 校验 id token(issuer、audience、过期、nonce),建立产品 自己的会话。
- 从套件角色/组 claim 解析产品本地授权;产品仍是自身 RBAC 的权威。
套件部署中这对应 oidc 集成模式,而其他产品通常保持默认的 ns 票据模式。NS 与产品
必须在模式上一致——不一致是登录循环最常见的原因。细节与 claim 映射见
SSO 与 OIDC。
决策清单¶
- 有交互用户吗?没有 → A(NL)或 B(NH);有 → C(套件)或 E(独立)。
- 调用方是固件?一律走 D。
- 集成需要写 edge exchange 吗?NH partner API 只读;运营类写入应以认证用户身份走控制台/API, 而非 partner key。
- 确认部署形态:套件(有网关+票据)还是独立(直连 origin + 直接 OIDC)。
- 与运维带外约定并预置凭据:服务账号、partner key、OIDC 客户端或设备凭据。这些都不能自助 注册。
相关链接¶
- 平台对接指南——API 目录与调用约定。
- SSO 与 OIDC · RBAC
- 内嵌 OpenAPI:NS 与 NL 在
/api/docs提供离线 Swagger UI;NH 提供 console 与 partner 两份规范;NF 为docs/api/openapi.yaml。