跳转到内容

认证器参考

认证器属于一个项目,记录调用者通过什么方式进入。它不是业务角色、资源凭据,也不是平台 SSO 提供方。包括列表/详情读取在内,都要求项目编辑者成员(owner、admin、developer)。还需单独配置端点准入并发布,见端点认证。

GET/POST /projects/{slug}/authorizers;GET/PUT/DELETE .../authorizers/{name}。创建必填 name(处理器检查 1–64 字节)、kind;可选 config 默认 JSON null;可选/null default_role 指向已有角色;可选/null secret 保存类型专用秘密。有配置要求的类型应传对象,省略 config 不会绕过校验。

响应字段为 id、project_id、name、kind、config、default_role_id、created_at、updated_at,不返回秘密/密文。更新不能改名或改 kind:省略/null config 保持,提供对象整体替换;省略/null default_role 保持,"" 清除,非空名称解析已有角色。省略/null secret 保持已有秘密,委托社交转换例外见下。应原地轮换,不要删除重建:删除认证器会级联其 API-key 关系,并非无害改名。

以下是源码推导、未执行的创建示例:

终端窗口
curl -sS "$BASE/projects/demo/authorizers" \
-H "Authorization: Bearer $PLATFORM_ACCESS_TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"machine","kind":"api_key","config":{"token_ttl_hours":1},"default_role":"public"}'
kind凭据/入口配置与边界
password原生身份/密码登录failure_backoff、交互会话配置;无资源秘密
anonymous未建立身份的请求必须通过具名匿名认证器显式公开,不创建终端用户
api_keyBearer vsk_... 或 _token 客户端凭据token_ttl_hours 默认 1,签发范围 1–24;key 属于项目用户
oauth_oidc浏览器跳转外部 OIDCissuer/client/scopes/redirect、加密 client secret、交互会话配置
jwt外部非对称 JWT bearer必填 issuer/audience,PEM/JWKS 二选一
social服务器兑换提供方授权码提供方专用配置/秘密、可选平台应用委托、交互会话配置
chat平台为已绑定聊天发送者创建首次绑定创建;不能手工创建,保留名称 chat 也被拒绝

默认角色由适用的用户创建流程使用,不是每次请求覆盖所有已有用户角色的指令。聊天绑定的调用归属应是平台 chat 行,而不是当初用于证明绑定的密码认证器。

省略/null failure_backoff 默认为 {after_failures:5,max_delay_secs:900}。内部可选 after_failures 为 0–86400 整数(0 关闭),max_delay_secs 为 1–86400 整数。未知内部键/错误类型被拒绝。按身份和客户端地址记录连续失败,等待 1、2、4… 秒至上限,成功清零。多个密码认证器取已启用配置中最严格的组合,不允许调用者挑最宽松入口。全局身份/IP 限流仍生效。

密码/OIDC/社交共享交互配置:login_token_ttl_hours 省略/null 为 12,整数 1–720;session 省略/null 为无刷新会话;对象必须含 idle_timeout_hours(1–8760,不小于 token TTL),可选 max_lifetime_hours(默认 720,显式值不小于 idle 且不超过 8760)。要删除/重置键,应发送完整替换 config,而不是局部嵌套 patch。刷新和退出见端点认证。

必填 config.issuer、client_id、post_login_redirect_uri;可选/null scopes 默认 ["openid","profile","email"],显式列表必须含精确值 openid;discovery_cache_ttl_secs 可选,60–86400。issuer 必须 HTTPS,localhost/127.0.0.1 允许 HTTP。client ID 非空且最多 512 字节;redirect 必须能解析为 URL。秘密格式 {"client_secret":"..."}:创建时必填非空、最多 1024 字节;更新省略/null 或空白保持旧值,不清除。

{"name":"external-login","kind":"oauth_oidc","config":{"issuer":"https://identity.example.invalid","client_id":"fixture-client","scopes":["openid","profile","email"],"post_login_redirect_uri":"https://app.example.invalid/signed-in","discovery_cache_ttl_secs":3600},"secret":{"client_secret":"REPLACE_WITH_PROVIDER_SECRET"},"default_role":"public"}

向外部提供方登记精确回调 BASE/projects/demo/auth/oidc/external-login/callback。浏览器入口 GET /projects/demo/auth/oidc/external-login/start;回调校验 state/code/提供方令牌,创建/解析项目身份,然后带 Viat 登录结果重定向至应用地址。不能把提供方 secret 发给浏览器。它不是用于平台账号的 /auth/oidc/{name}/start。本页未测试提供方注册、发现文档连接和真实 SSO。

issuer、audience 为必填非空字符串。subject_claim 默认 sub,提供时必须非空字符串。密钥模式二选一:

{"name":"external-jwt","kind":"jwt","config":{"issuer":"https://identity.example.invalid","audience":"fixture-api","jwks_url":"https://identity.example.invalid/.well-known/jwks.json","subject_claim":"sub"},"default_role":"public"}
  • PEM:public_key_pem 和 algorithm: "RS256" 或 "ES256",需可解析且匹配的公钥 PEM。上游轮换后此钥可能过时。
  • JWKS:jwks_url,HTTPS 或 loopback HTTP,按令牌 kid 选择公开钥;支持 RS256/384/512、PS256/384/512、ES256/384。这里不提供共享对称密钥 JWT 认证器,也没有 EdDSA 模式。

必须通过签名、过期、issuer、audience、subject 校验。项目身份按认证器隔离(jwt:<authorizer>:<subject>);低信任项目管理入口不能预种联邦身份。仅经过验证的 claim 能成为已声明 subject attrs/scope claims,普通请求体不能。JWKS 在上游留重叠期轮换;替换 PEM 时发送完整 config。

必填 config.provider、app_id(appid/corpid/AppKey)。可选字段:

字段默认/规则
agent_id企业微信自建应用 agent ID,普通 WeCom 应用配置要求提供
identity_key有 unionid 时优先,否则原生键;可选值见下
scopes默认见下;各项非空、最多 64 字节
qr_loginfalse;WeCom true 时使用扫码而非客户端 H5
collect_phonefalse;需要提供方权限和手机号授权/载荷
post_login_redirect_uri跳转型提供方必填有效 URL,纯 code 型不需要
api_base、auth_base默认提供方地址;测试/出口源必须 HTTPS 或 loopback HTTP,仍受 host allowlist 限制
alipay_public_key支付宝验证 RSA 公钥,适用配置必须提供;不是秘密
platform_app省略/null 为自有应用,否则引用当前项目兼容的平台应用
提供方入口/默认 scopes显式 identity_key 可选值
weixin_mp微信 H5 / snsapi_userinfounionid、openid
weixin_open网站扫码 / snsapi_loginunionid、openid
weixin_mini仅 wx.login code / 空unionid、openid
wecom客户端 H5 或扫码 / snsapi_baseuserid
dingtalk浏览器 / openidunionid、openid
dingtalk_app仅 dd.getAuthCode / 空unionid、userid
alipay浏览器 / auth_useruser_id、open_id
alipay_mini仅 my.getAuthCode / auth_baseuser_id、open_id
douyin浏览器 / user_infounionid、open_id
douyin_mini仅 tt.login / 空unionid、open_id
kuaishou浏览器 / user_infoopen_id
kuaishou_mini仅 ks.login / 空open_id

非支付宝自有应用要求 secret.app_secret 非空且最多 1024 字节。支付宝用 app_private_key(RSA PEM/base64,最多 8192 字节)及公开验证钥;支付宝小程序采集手机号需自己的 AES 解密时必须有 aes_key。更新按字段把非空社交秘密合并到已有秘密,省略/空白不抹掉相邻字段;切换配置后仍须有新提供方所需凭据。

浏览器路由为 GET /p/{slug}/_social/{name}/start、提供方回调 GET .../callback。授权码入口 POST .../exchange 必填 code,可选 phone_code、phone_data、client_id、client_secret、link。小程序手机号载荷因提供方不同,设置 collect_phone:true 不能伪造手机号许可。Viat 登录结果遵循交互会话策略。link 要求已有已认证身份,随意提交 code/自称 unionid 不能证明账号所有权。unionid 受平台族/平台作用域限制,openid 受应用限制,不能凭裸字符串合并不同人。

委托模式使用 platform_app 和被授权账号 app_id;兼容关系见平台应用。转入委托时会移除旧应用秘密,避免以后悄悄恢复;支付宝小程序手机号 AES 钥按需单独保留。转回自有应用必须提供有效自有秘密。

配置通过校验不代表提供方联调成功。须验证回调源/TLS 信任、提供方权限、项目角色、已发布认证器列表,以及拒绝案例。配置错误 400、同名冲突 409、对象不存在 404、编辑权限不足 403;登录/交换还可能因 state、上游网络、令牌、scope 失败。不要把 issuer/audience 变成可选或关闭 TLS 验证来绕过问题。

原地轮换秘密,验证新登录后再退役上游旧凭据。删除 Viat 行不会注销上游应用。移除隔离认证器前,清理端点引用并查看发布计划。凭据不能进入 repo-sync config 或复制的提供方响应。

依据: crates/viat-core/src/types/authorizer.rs、crates/viat-api/src/{dto.rs,handlers/authorizers.rs,handlers/oidc.rs,social/mod.rs,social/handlers.rs,login_backoff.rs,project_session.rs,middleware_project.rs}、crates/viat-auth/src/jwt.rs。所有配方均未执行。