Auth CLI:让 Agent 配置登录
Auth CLI 帮助开发者在本机登录 KAI 管理账号,让 Agent 管理组织、项目和应用,并为业务应用生成 OAuth/OIDC 接入配置。
安装与运行
命令名为 kai-auth,包名为 @kai/auth-cli,需要 Node.js 24.3.0 或更高版本。当前可从仓库构建本地安装包;以下流程不依赖 npm 上已发布的包。
在仓库的 Yarn 开发环境中构建:
yarn workspace @kai/auth-cli build
yarn workspace @kai/auth-cli pack --out /tmp/kai-auth-cli.tgz
将生成的安装包放到开发者本机,然后运行:
npm install -g /tmp/kai-auth-cli.tgz
kai-auth browser install
kai-auth --help
browser install 为开发者管理登录下载与 CLI 匹配的 Playwright Chromium。已有 Chrome 或 Edge 时,也可以在登录时指定 --browser chrome 或 --browser msedge。应用侧 oauth step-up 使用系统浏览器,不要求下载这个 Chromium;不支持自动打开浏览器的环境可用 --no-open。
源码开发可用 yarn auth:cli --help,它先构建再运行 CLI;已有构建产物时可用 node packages/cli/dist/index.js --help。运行使用对应平台安装的依赖;不要把 Linux 容器中的 node_modules 用于宿主 Node。交互登录需要图形浏览器,应在开发者可操作的环境中执行。
开发者先登录,Agent 继续配置
kai-auth login --profile default --origin https://auth.kai.com
kai-auth status --profile default --json
login 打开独立的 Playwright 浏览器并进入 /console。开发者在该窗口完成正常登录及所需验证,CLI 保存本机管理会话。它不导入已有浏览器 profile,也不要求把密码或验证码放进命令、项目文件或 Agent 对话。
后续命令默认使用 default profile;可以用 --profile NAME 区分账号或环境。--origin 仅用于 login,其他管理命令使用 profile 中保存的服务地址。未登录、会话失效或权限不足时,命令会报错。login 会自动清除已过期的本机会话;已有未过期 profile 需要重新登录时,先运行 logout 再 login,或者选择一个新的 profile 名称。
Agent 必须在能访问该本机 profile 的环境中运行。本版没有独立的远程无界面登录流程;远程 Agent 无法直接复用开发者另一台机器上的登录状态。
这是开发者管理会话。业务应用的 OAuth access token 不会因此获得管理 API 权限。组织、项目和应用操作继续由服务端校验身份、角色、资源归属与组织状态,敏感操作保留原有的再次验证要求。
完整示例:创建应用并生成接入文件
以下示例使用 jq 提取命令输出中的 ID。它创建 public Web 应用,通过 Authorization Code + PKCE 登录,不需要 client secret。将回调地址替换成业务应用实际使用的 HTTPS 地址。
先创建组织和项目;已有资源可用 list 查询并直接使用返回的 ID。
ORGANIZATION_ID=$(
printf '%s' '{"name":"Example Team","slug":"example-team"}' |
kai-auth organizations create --stdin --json |
jq -er '.data.id'
)
PROJECT_ID=$(
printf '%s' '{"name":"Example App","slug":"example-app"}' |
kai-auth projects create --organization "$ORGANIZATION_ID" --stdin --json |
jq -er '.data.id'
)
创建应用的 JSON 使用与管理 API 相同的字段:
cat > application.json <<'JSON'
{
"name": "Example Web",
"clientType": "public",
"applicationKind": "web",
"accessMode": "authenticated_users",
"scopes": ["openid", "profile", "email"],
"requiredScopes": ["openid"],
"optionalScopes": ["profile", "email"],
"signInMethods": ["authorization_code"],
"redirectUris": ["https://app.example.com/oauth/callback"],
"postLogoutRedirectUris": ["https://app.example.com/signed-out"]
}
JSON
APPLICATION_ID=$(
kai-auth applications create \
--organization "$ORGANIZATION_ID" \
--project "$PROJECT_ID" \
--file application.json --json |
jq -er '.data.application.id'
)
kai-auth init \
--organization "$ORGANIZATION_ID" \
--project "$PROJECT_ID" \
--application "$APPLICATION_ID" \
--redirect-uri https://app.example.com/oauth/callback \
--directory ./my-app --json
kai-auth config show --directory ./my-app --json
kai-auth config env --directory ./my-app --json
kai-auth doctor --directory ./my-app --json
每一步失败后先处理错误,再继续下一步。authenticated_users 允许非组织成员登录;仅对组织成员开放时改为 members_only。profile 和 email 在此示例中是可选权限,应用必须处理用户未授权这些信息的情况。
init 读取已登记应用,在目标目录创建:
| 文件 | 用途 |
|---|---|
kai-auth.json |
公开的应用接入配置,供 CLI 和 Agent 读取 |
.env.example |
环境变量示例,不会自动加载进业务应用 |
KAI_AUTH.md |
供开发者与 Agent 使用的接入说明 |
生成操作不覆盖已有文件;发生冲突时先审查现有内容,或选择新目录。--redirect-uri 必须是该应用已经登记的回调;有多个回调时必须显式选择,命令不会自动修改回调白名单。配置中的 issuer 来自 Discovery,可以与登录使用的服务 origin 不同。
.env.example 包含 KAI_AUTH_ORIGIN、KAI_AUTH_ISSUER、KAI_AUTH_CLIENT_ID、KAI_AUTH_CLIENT_TYPE、KAI_AUTH_SCOPES 和 KAI_AUTH_SIGN_IN_METHODS;浏览器授权应用还包含 KAI_AUTH_REDIRECT_URI。confidential 应用的 KAI_AUTH_CLIENT_SECRET 仅为空白占位。生成文件不包含管理会话或实际 client secret。
配置生成后,Agent 还需要结合业务应用的框架实现 OIDC 登录入口、回调、PKCE、state、nonce、令牌验证和应用自己的会话。使用 Discovery 中的端点,按照Authorization Code + PKCE和令牌校验与 claims完成接入;生成文件不等于业务应用已经支持登录。
给 Agent 的任务示例
开发者完成本机 kai-auth login 后,可以提供以下任务:
使用 kai-auth --json 为当前项目接入 KAI 登录。先检查 status 和组织、项目、
应用列表,确认目标资源;需要创建或更新时先读取对应 schema,再提交 JSON。
为选定应用运行 init,阅读 KAI_AUTH.md,并按本项目的框架实现标准 OIDC
Authorization Code + PKCE、回调校验与应用会话。使用 config show/env 获取
公开配置,运行 doctor 后,再验证业务应用真实登录、回调和退出流程。
client secret 只从安全文件交给服务端环境,不放入前端代码或命令输出。
本页的机器可读地址为 /docs/auth-cli/index.md;也可以通过 /llms.txt 查找其余接入资料。
应用侧的额外身份验证
kai-auth oauth step-up 为应用发起 OAuth 额外身份验证。它与下文用于删除项目等管理动作的 kai-auth step-up 是不同流程,不读取或转发管理 profile 的 Cookie,也不直接调用 KAI 的私有验证接口。
当前命令适用于已登记的 native / public 应用,必须启用 Authorization Code、允许 openid,并配置精确的本机回调,例如 http://127.0.0.1:8765/oauth/callback。该回调需要事先加入应用白名单,并由 init --redirect-uri 写入配置。命令不会放宽回调校验、自动增加白名单或把端口替换为随机值;端口被占用时先处理冲突。Web 和 confidential 应用按其运行环境接入标准授权码流程;Device-only 应用必须先登记并启用 Authorization Code,不能通过向 Device 请求添加 acr_values 获取额外验证结果。
kai-auth doctor --directory ./native-app --step-up --json
kai-auth oauth step-up \
--directory ./native-app \
--expected-sub CURRENT_USER_SUBJECT \
--max-proof-age 300 \
--timeout 600 \
--json
--expected-sub 必填,取当前业务已验证身份的 sub,不能填写邮箱、昵称,也不能根据本次回调临时更换预期用户。issuer 从接入配置固定读取。
CLI 先启动只监听本机的回调,再打开系统浏览器。用户在 KAI 页面亲自完成登录和额外验证;CLI 使用新的随机 state、nonce 与 S256 PKCE 兑换授权码,并验证 ID token 签名、issuer、audience、nonce、用户、额外验证策略及时间。它请求 openid 及应用登记的全部必选权限,不额外请求可选权限,也不把这次证明保存为管理登录会话。若必选权限包含 offline_access,命令会在发起授权前报配置错误;该命令不申请长效访问授权,需要调整应用的必选权限配置后重试。
--max-proof-age默认 300 秒,限制实际证明的新鲜度;刷新令牌不能重新计算此时间。--timeout默认 600 秒,限制本次命令等待时间;取消、超时或中断不会被当作验证成功。--no-open只把授权入口写到 stderr,供用户在能够访问本机回调的浏览器中打开;它不自动批准、不提交密码,也不是远程无界面认证。--proof-file NEW_PRIVATE_FILE显式要求把通过校验的签名 ID token 保存到新的私有文件,权限为0600,不覆盖已有文件。普通命令输出不包含 ID token、access token、refresh token、授权码或 Cookie。
成功结果只区分 verified 与 password_only,不返回 TOTP、Passkey 等实际方式;当前版本不包含手机批准。password_only 表示密码证明校验成功,不表示已经满足高等级要求;业务只接受高等级验证时仍须要求 verified。普通 JSON 输出是 CLI 的本机验真报告,不是可以转交给任意服务器的签名凭证;其他服务需要验证专门面向自己的 OAuth 证明,不能盲目信任这份 JSON 或面向 CLI client ID 的 ID token。
使用 --json 时,stdout 只输出一份机器可读结果;进度写入 stderr。成功示例:
{
"ok": true,
"data": {
"status": "verified",
"issuer": "https://auth.kai.com",
"subject": "CURRENT_USER_SUBJECT",
"acr": "urn:kai:acr:step-up",
"authTime": 1790000000,
"expiresAt": 1790000300
}
}
authTime 与 expiresAt 均为秒级 Unix 时间;后者是 ID token 的到期时间,不会延长 --max-proof-age 规定的证明有效窗口。显式保存证明时,结果另含 proofFile 路径。未完成、超时或验证失败时返回 ok: false 和脱敏的 error.code / error.message,并以非零状态退出;不会返回成功状态或未校验的令牌。
doctor --step-up 只检查本地配置、Discovery 和这条流程需要的公开能力,不会替代真实用户验证,也不保证远端应用登记没有变化。完整登录、取消、错误回调、时间过期和同一账号核对仍应实际验收。
命令与输入契约
| 命令 | 主要参数与用途 |
|---|---|
browser install |
安装默认 Chromium |
login |
--profile NAME --origin URL;可选 --browser chrome 或 --browser msedge |
status、logout |
查看或清除所选 profile 的本机登录状态 |
organizations list |
查看当前账号可用的组织 |
organizations get/create/update/delete |
get、update、delete 使用 --organization UUID |
projects list/get/create/update/delete |
必须指定 --organization UUID;get、update、delete 另需 --project UUID |
applications list/get/create/update/delete |
必须指定 --organization UUID --project UUID;get、update、delete 另需 --application UUID |
step-up start/prove/send-otp/verify-otp/cancel |
通过 --file 或 --stdin 提供 JSON;除 start 外还需 --transaction UUID |
oauth step-up |
应用侧额外验证;--directory DIR --expected-sub SUBJECT,可选时间限制、--no-open、--proof-file NEW_FILE |
schema NAME |
输出指定输入的 JSON Schema |
init |
指定组织、项目、应用 UUID;可选 --directory DIR --redirect-uri URL |
config show/env |
读取 --directory DIR 下的接入配置或生成环境变量说明 |
doctor |
检查 --directory DIR 下的配置及服务端 Discovery;--step-up 追加本机 OAuth 额外验证检查 |
create、update 使用 --file PATH 或 --stdin 二选一读取 JSON。输入在发请求前通过 API 的 Effect Schema 验证;服务器仍会检查当前数据和权限。可读取以下 schema:
kai-auth schema organization-create --json
kai-auth schema organization-update --json
kai-auth schema project-create --json
kai-auth schema project-update --json
kai-auth schema application-create --json
kai-auth schema application-update --json
kai-auth schema project-delete --json
kai-auth schema step-up-start --json
kai-auth schema step-up-prove --json
kai-auth schema step-up-send-otp --json
kai-auth schema step-up-verify-otp --json
kai-auth schema step-up-cancel --json
JSON Schema 用于了解字段结构;跨字段限制也会在实际命令执行时验证。例如 requiredScopes 与 optionalScopes 必须同时给出、不重叠,并合起来等于 scopes;native 应用必须为 public。回调和客户端规则见应用登记与回调。
delete 必须显式提供 --confirm,值等于待删除对象的 UUID。删除项目还需要通过 --file 或 --stdin 提供有效的 project-delete 再次验证凭证。凭证绑定具体动作、对象、会话与版本并由服务端验证,--confirm 不能代替它。
删除项目的再次验证
使用相同的 profile 发起、验证并消费 step-up 事务,不能从另一个浏览器登录会话复制凭证。先为目标项目启动事务:
kai-auth step-up start --stdin --json <<JSON
{"action":"project_remove","resourceId":"$PROJECT_ID"}
JSON
读取响应中的 data.transaction。transactionId 用作后续的 --transaction;每次提交使用最新返回的 transactionRevision 作为 expectedTransactionRevision。allowedMethods 列出可用方式,otpTargets 给出可用联系人的 ID 和脱敏地址。
| 命令 | 输入 JSON 字段 |
|---|---|
step-up prove |
expectedTransactionRevision、method(password 或 totp)、proof(密码或六位 TOTP) |
step-up send-otp |
expectedTransactionRevision、method(email_otp 或 sms_otp)、contactId |
step-up verify-otp |
expectedTransactionRevision、challengeId、code(六位验证码) |
step-up cancel |
expectedTransactionRevision |
开发者通过受保护的输入文件或 stdin 提供密码、TOTP 或验证码,避免放入命令行参数、shell 历史、普通项目文件或日志。不要把证明输入交给无关工具。只选服务器允许的验证方式;这里的管理 step-up 命令不直接执行 Passkey,需要 Passkey 时在控制台完成管理操作。应用侧 oauth step-up 则将验证交给 KAI 浏览器页面。
例如,把验证输入安全保存在项目以外的私有文件后:
kai-auth step-up prove --transaction "$TRANSACTION_ID" \
--file "$PRIVATE_PROOF_INPUT_FILE" --json
密码或 TOTP 验证使用 prove。邮件或短信验证先调用 send-otp,再使用其返回的 challengeId 和最新事务版本调用 verify-otp。仅当返回 data.transaction.state 为 ready 时,data.proof 才是可用于删除的请求体;否则继续按事务状态处理,不能自行填造凭证。
将 ready 响应中的 data.proof 保存为权限受限的临时 JSON 文件后,可以完成删除:
kai-auth projects delete --organization "$ORGANIZATION_ID" \
--project "$PROJECT_ID" --confirm "$PROJECT_ID" \
--file "$PRIVATE_DELETE_PROOF_FILE" --json
凭证只能使用一次并有有效期。事务不再需要时使用 step-up cancel;失败或版本变化时读取错误并重新确认当前状态,不重复提交旧凭证。
机密应用与本机凭据
confidential 应用只适用于能保守秘密的服务端。创建这类应用时,CLI 将一次性 client secret 写入本机的新文件,权限为 0600,结果只返回文件路径。默认文件放在 CLI 配置目录,也可用 applications create --secret-file PATH 指定一个不存在的文件。将秘密通过服务端的秘密管理机制提供给应用,不能放进前端 bundle、版本库或普通日志。
CLI 配置目录依次采用 KAI_AUTH_CONFIG_DIR、$XDG_CONFIG_HOME/kai-auth、~/.config/kai-auth。profile 凭据与业务项目文件分开保存,应只允许所需的本机开发者或 Agent 访问。kai-auth logout --profile NAME 对尚未过期的会话先执行服务端注销,再清除该 profile 的本机登录状态;服务端连接失败时保留 profile 供重试注销。业务应用的 OIDC 退出流程见退出与撤销。
JSON 输出与诊断范围
所有命令支持 --json,stdout 只输出一个 JSON 对象,进度发往 stderr。成功形态为 {"ok":true,"data":...};失败形态为 {"ok":false,"error":{"code":"...","message":"..."}},有请求编号时附带 requestId。doctor 的检查失败额外在 data 中保留逐项报告,错误码为 DIAGNOSTICS_FAILED。失败退出码非零。Agent 应同时检查退出码和 ok,解析时不要合并 stderr 与 stdout。
命令不会打印 session cookie 或 client secret。doctor 校验本地接入配置和实时 Discovery,包括 issuer、协议端点、scope、grant 和 PKCE 等配置。每项报告 pass、fail 或 skipped;它不重新核对远端应用当前的登记状态,也不执行真实 OAuth 登录。
通过检查只说明已检查的条件符合要求,不代表完整授权、回调、换取令牌或应用会话已经验证。真实登录仍需在业务应用中完成,并检查用户拒绝授权、可选权限未获准、回调错误和退出等结果。