@m1a0rz/agent-identity 0.4.1 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-cn.md +32 -19
- package/README.md +32 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +80 -7
- package/dist/scripts/demo-get-session.d.ts +15 -0
- package/dist/scripts/demo-get-session.d.ts.map +1 -0
- package/dist/scripts/demo-get-session.js +58 -0
- package/dist/src/actions/identity-actions.d.ts +74 -8
- package/dist/src/actions/identity-actions.d.ts.map +1 -1
- package/dist/src/actions/identity-actions.js +217 -84
- package/dist/src/commands/identity-commands.d.ts.map +1 -1
- package/dist/src/commands/identity-commands.js +139 -11
- package/dist/src/gateway/identity-session-methods.d.ts +2 -2
- package/dist/src/gateway/identity-session-methods.d.ts.map +1 -1
- package/dist/src/gateway/identity-session-methods.js +9 -5
- package/dist/src/hooks/after-tool-call.d.ts.map +1 -1
- package/dist/src/hooks/after-tool-call.js +12 -0
- package/dist/src/hooks/before-agent-start.d.ts +2 -0
- package/dist/src/hooks/before-agent-start.d.ts.map +1 -1
- package/dist/src/hooks/before-agent-start.js +33 -6
- package/dist/src/hooks/before-tool-call.d.ts +1 -0
- package/dist/src/hooks/before-tool-call.d.ts.map +1 -1
- package/dist/src/hooks/before-tool-call.js +29 -5
- package/dist/src/hooks/llm-input.d.ts.map +1 -1
- package/dist/src/hooks/llm-input.js +32 -4
- package/dist/src/hooks/sessions-send-propagation.d.ts.map +1 -1
- package/dist/src/hooks/sessions-send-propagation.js +1 -0
- package/dist/src/hooks/sessions-spawn-propagation.d.ts.map +1 -1
- package/dist/src/hooks/sessions-spawn-propagation.js +1 -0
- package/dist/src/hooks/tool-result-persist.d.ts +20 -0
- package/dist/src/hooks/tool-result-persist.d.ts.map +1 -0
- package/dist/src/hooks/tool-result-persist.js +50 -0
- package/dist/src/preflight/plugin-preflight.d.ts +55 -0
- package/dist/src/preflight/plugin-preflight.d.ts.map +1 -0
- package/dist/src/preflight/plugin-preflight.js +226 -0
- package/dist/src/preflight/plugin-state.d.ts +18 -0
- package/dist/src/preflight/plugin-state.d.ts.map +1 -0
- package/dist/src/preflight/plugin-state.js +19 -0
- package/dist/src/routes/oidc-login.js +2 -2
- package/dist/src/services/identity-client.d.ts +129 -2
- package/dist/src/services/identity-client.d.ts.map +1 -1
- package/dist/src/services/identity-client.js +175 -20
- package/dist/src/services/identity-credentials.d.ts +1 -1
- package/dist/src/services/identity-credentials.d.ts.map +1 -1
- package/dist/src/services/identity-credentials.js +32 -16
- package/dist/src/services/oidc-client.d.ts +12 -1
- package/dist/src/services/oidc-client.d.ts.map +1 -1
- package/dist/src/services/oidc-client.js +20 -3
- package/dist/src/services/session-refresh.d.ts +10 -0
- package/dist/src/services/session-refresh.d.ts.map +1 -1
- package/dist/src/services/session-refresh.js +29 -5
- package/dist/src/services/skill-contract-metadata.d.ts +35 -0
- package/dist/src/services/skill-contract-metadata.d.ts.map +1 -0
- package/dist/src/services/skill-contract-metadata.js +145 -0
- package/dist/src/services/skill-contract-renderer.d.ts +14 -0
- package/dist/src/services/skill-contract-renderer.d.ts.map +1 -0
- package/dist/src/services/skill-contract-renderer.js +120 -0
- package/dist/src/services/tip-propagation.d.ts +2 -0
- package/dist/src/services/tip-propagation.d.ts.map +1 -1
- package/dist/src/services/tip-propagation.js +4 -3
- package/dist/src/services/tip-with-refresh.d.ts +1 -1
- package/dist/src/services/tip-with-refresh.d.ts.map +1 -1
- package/dist/src/services/tip-with-refresh.js +24 -39
- package/dist/src/store/credential-store.d.ts +6 -1
- package/dist/src/store/credential-store.d.ts.map +1 -1
- package/dist/src/store/credential-store.js +3 -0
- package/dist/src/store/oidc-state-store.d.ts +3 -3
- package/dist/src/store/oidc-state-store.d.ts.map +1 -1
- package/dist/src/store/oidc-state-store.js +2 -2
- package/dist/src/store/sender-session-store.d.ts +8 -0
- package/dist/src/store/sender-session-store.d.ts.map +1 -1
- package/dist/src/store/sender-session-store.js +34 -1
- package/dist/src/store/skill-contract-store.d.ts +19 -0
- package/dist/src/store/skill-contract-store.d.ts.map +1 -0
- package/dist/src/store/skill-contract-store.js +65 -0
- package/dist/src/store/skill-path-store.d.ts +5 -0
- package/dist/src/store/skill-path-store.d.ts.map +1 -1
- package/dist/src/store/skill-path-store.js +13 -1
- package/dist/src/tools/identity-approve-tool.d.ts +2 -11
- package/dist/src/tools/identity-approve-tool.d.ts.map +1 -1
- package/dist/src/tools/identity-config-suggest.d.ts +2 -13
- package/dist/src/tools/identity-config-suggest.d.ts.map +1 -1
- package/dist/src/tools/identity-config.d.ts +2 -7
- package/dist/src/tools/identity-config.d.ts.map +1 -1
- package/dist/src/tools/identity-fetch.d.ts +2 -13
- package/dist/src/tools/identity-fetch.d.ts.map +1 -1
- package/dist/src/tools/identity-fetch.js +3 -3
- package/dist/src/tools/identity-get-role-credentials.d.ts +10 -0
- package/dist/src/tools/identity-get-role-credentials.d.ts.map +1 -0
- package/dist/src/tools/identity-get-role-credentials.js +56 -0
- package/dist/src/tools/identity-get-session-token.d.ts +8 -0
- package/dist/src/tools/identity-get-session-token.d.ts.map +1 -0
- package/dist/src/tools/identity-get-session-token.js +46 -0
- package/dist/src/tools/identity-get-tip-token.d.ts +8 -0
- package/dist/src/tools/identity-get-tip-token.d.ts.map +1 -0
- package/dist/src/tools/identity-get-tip-token.js +46 -0
- package/dist/src/tools/identity-list-credentials.d.ts +2 -11
- package/dist/src/tools/identity-list-credentials.d.ts.map +1 -1
- package/dist/src/tools/identity-list-credentials.js +4 -3
- package/dist/src/tools/identity-list-risk-patterns.d.ts +2 -7
- package/dist/src/tools/identity-list-risk-patterns.d.ts.map +1 -1
- package/dist/src/tools/identity-list-roles.d.ts +8 -0
- package/dist/src/tools/identity-list-roles.d.ts.map +1 -0
- package/dist/src/tools/identity-list-roles.js +43 -0
- package/dist/src/tools/identity-list-tips.d.ts +2 -7
- package/dist/src/tools/identity-list-tips.d.ts.map +1 -1
- package/dist/src/tools/identity-login.d.ts +2 -7
- package/dist/src/tools/identity-login.d.ts.map +1 -1
- package/dist/src/tools/identity-logout.d.ts +2 -7
- package/dist/src/tools/identity-logout.d.ts.map +1 -1
- package/dist/src/tools/identity-risk-check.d.ts +3 -17
- package/dist/src/tools/identity-risk-check.d.ts.map +1 -1
- package/dist/src/tools/identity-set-binding.d.ts +2 -10
- package/dist/src/tools/identity-set-binding.d.ts.map +1 -1
- package/dist/src/tools/identity-status.d.ts +2 -7
- package/dist/src/tools/identity-status.d.ts.map +1 -1
- package/dist/src/tools/identity-unset-binding.d.ts +2 -9
- package/dist/src/tools/identity-unset-binding.d.ts.map +1 -1
- package/dist/src/tools/identity-whoami.d.ts +2 -7
- package/dist/src/tools/identity-whoami.d.ts.map +1 -1
- package/dist/src/types.d.ts +25 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils/derive-session-key.d.ts +1 -0
- package/dist/src/utils/derive-session-key.d.ts.map +1 -1
- package/dist/src/utils/derive-session-key.js +28 -4
- package/dist/src/utils/resolve-identity-endpoint.d.ts +26 -0
- package/dist/src/utils/resolve-identity-endpoint.d.ts.map +1 -0
- package/dist/src/utils/resolve-identity-endpoint.js +90 -0
- package/openclaw.plugin.json +18 -1
- package/package.json +11 -3
- package/skills/SKILL.md +9 -9
package/README-cn.md
CHANGED
|
@@ -39,6 +39,8 @@ UserPool OIDC 登录、TIP (Trusted Identity Provider) 令牌(通过 Identity
|
|
|
39
39
|
| `list-tips` | 列出所有有效 TIP 令牌及其委托链、过期时间和环境变量绑定。 |
|
|
40
40
|
| `config` | 显示 identity 插件配置(敏感信息脱敏)。 |
|
|
41
41
|
| `list-credentials` 或 `list [page]` | 分页列出控制台 provider 及已绑定的凭据。使用 `list 2` 加载更多。 |
|
|
42
|
+
| `list-roles` | 列出 STS 角色类凭据提供方(非 OAuth/API key)。可选按名称前缀过滤。 |
|
|
43
|
+
| `get-role <provider> [--use-tip] [--show-secrets]` | 获取某角色提供方的 STS 临时凭据(默认脱敏)。 |
|
|
42
44
|
| `fetch <provider> [--flow=...]` | 添加凭据。flow 根据 provider 类型自动推断;可用 `--flow` 覆盖。 |
|
|
43
45
|
| `set <provider> <envVar>` | 将凭据绑定到环境变量供工具注入。无凭据时从 `process.env[envVar]` 导入。 |
|
|
44
46
|
| `unset <provider>` | 移除 provider 的环境变量绑定。 |
|
|
@@ -104,7 +106,8 @@ openclaw plugins install --link .
|
|
|
104
106
|
|
|
105
107
|
**A. 平台侧访问配置(Identity)**:用于获取 TIP Token、拉取/托管凭据、做权限校验(可选)。
|
|
106
108
|
|
|
107
|
-
- `endpoint
|
|
109
|
+
- `endpoint`(可选):Identity API 根地址(例如 `https://id.cn-beijing.volcengineapi.com`)。**优先级最高**。
|
|
110
|
+
- `regionMetadataUrl`(可选):返回 **纯文本 region id**(如 `cn-beijing`)的 HTTP(S) URL。仅当 **未配置 `endpoint`** 时使用:客户端拼接 `https://id.{region}.volcengineapi.com`。单次请求约 10s 超时;失败或正文无效(如 `unknown`)时回退到 `https://id.cn-beijing.volcengineapi.com`。示例:`http://100.96.0.96/latest/region_id`(需网关能访问)。
|
|
108
111
|
- `accessKeyId` / `secretAccessKey`:用于访问 Identity API。**可选**,可使用环境变量或凭据文件(见下)。
|
|
109
112
|
- `workloadPoolName` / `workloadName`:用于签发 TIP Token。默认:`default`、`openclaw-agent`。
|
|
110
113
|
- `audience` / `durationSeconds`:可选,令牌受众与有效期。
|
|
@@ -113,6 +116,10 @@ openclaw plugins install --link .
|
|
|
113
116
|
- `roleTrn`:STS AssumeRole 的 Role TRN。设置后(且未设置 `workloadName`)不传 workload name,后端使用 roleName。优先级:`workloadName` > `roleTrn` > params。与 `credentialsMetadataUrl` 配合时用于 AssumeRole,或与显式 AK/SK 配合。
|
|
114
117
|
- `sessionToken`:STS 会话令牌(或使用 `VOLCENGINE_SESSION_TOKEN` 环境变量)。
|
|
115
118
|
|
|
119
|
+
**Identity API 地址解析**:已配置 `endpoint` → 否则用 `regionMetadataUrl` 拉取 region 拼接 URL → 否则 `https://id.cn-beijing.volcengineapi.com`。**SigV4 签名用 region** 从解析后的主机名匹配 `id.{region}.volcengineapi.com` 推断;否则为 `cn-beijing`。
|
|
120
|
+
|
|
121
|
+
**工作负载池(凭据 / STS)**:`workloadPoolName`(默认 `default`)用于限定 `ListCredentialProviders`、`ListRoleCredentialProviders` 以及 `GetResourceOauth2Token`、`GetResourceApiKey`、`GetUserCredential`、`GetRoleCredentials` 等接口的 `PoolName`。若配置了 `userpool.userPoolName`,角色提供方列表还会在客户端按用户池再过滤。
|
|
122
|
+
|
|
116
123
|
**凭据解析顺序**(AK/SK):1)显式 config → 2)环境变量(`VOLCENGINE_ACCESS_KEY`、`VOLCENGINE_SECRET_KEY`、`VOLCENGINE_SESSION_TOKEN`)→ 3)远程元数据(`credentialsMetadataUrl` + `roleTrn`,从完整 URL 拉取后做 AssumeRole;404 时回退)→ 4)凭据文件(config 的 `credentialsFile`,或 `VOLCENGINE_CREDENTIALS_FILE` 环境变量,或 `/var/run/secrets/iam/credential`)。凭据文件格式(VeFaaS):`access_key_id`、`secret_access_key`、`session_token`(可选)、`role_trn`(可选,用于 AssumeRole)。`RUNTIME_IAM_ROLE_TRN` 环境变量可在从文件加载时提供 role TRN。
|
|
117
124
|
|
|
118
125
|
**B. 用户登录配置(UserPool / OIDC)**:用于 `/identity login` 的用户登录与会话建立。
|
|
@@ -121,6 +128,8 @@ openclaw plugins install --link .
|
|
|
121
128
|
- `clientId` / `clientSecret`(动态模式下可自动解析)
|
|
122
129
|
- `callbackUrl`:OpenClaw 网关对外可访问的回调地址,例如 `http://127.0.0.1:18789/identity/oauth/callback`
|
|
123
130
|
- `scope`:一般包含 `openid profile email`
|
|
131
|
+
- `identityProvider`(可选):授权 URL 中 `identity_provider` 对应的 IdP 名称;不填则使用 `ListIdentityProviders` 返回的第一条。
|
|
132
|
+
- `useRelayCallback`(可选):经 UserPool relay / `redirect_relay_uri` 的 OIDC 回调流程。默认 false。
|
|
124
133
|
|
|
125
134
|
**C. 权限校验与风险审批(AuthZ,可选)**:用于 TIP + CheckPermission + 风险评估与用户审批。各开关独立,无统一 `enable`。
|
|
126
135
|
|
|
@@ -182,7 +191,8 @@ openclaw plugins install --link .
|
|
|
182
191
|
|
|
183
192
|
| 参数 | 类型 | 必填 | 含义 |
|
|
184
193
|
|------|------|------|------|
|
|
185
|
-
| `endpoint` | string |
|
|
194
|
+
| `endpoint` | string | 否 | Identity API 根地址。不填则通过 `regionMetadataUrl` 或默认 `https://id.cn-beijing.volcengineapi.com` |
|
|
195
|
+
| `regionMetadataUrl` | string | 否 | 返回纯文本 region 的 URL;在未配置 `endpoint` 时拼接 `https://id.{region}.volcengineapi.com` |
|
|
186
196
|
| `accessKeyId` | string | 否* | 火山引擎 Access Key。不填时从 `VOLCENGINE_ACCESS_KEY` 或 `credentialsFile` 读取 |
|
|
187
197
|
| `secretAccessKey` | string | 否* | 火山引擎 Secret Key。不填时从 `VOLCENGINE_SECRET_KEY` 或 `credentialsFile` 读取 |
|
|
188
198
|
| `workloadPoolName` | string | 否 | 工作负载池名称,默认 `default` |
|
|
@@ -195,6 +205,7 @@ openclaw plugins install --link .
|
|
|
195
205
|
| `sessionToken` | string | 否 | STS 临时会话令牌(或 `VOLCENGINE_SESSION_TOKEN`) |
|
|
196
206
|
| `subagentTipPropagation` | boolean | 否 | 将 TIP 和 session 传播到子 agent。默认 false |
|
|
197
207
|
| `webchatSessionExchange` | boolean | 否 | 启用 `identity.session.put` / `identity.session.get` gateway WS 方法供 webchat 客户端使用。默认 false |
|
|
208
|
+
| `personalSessionMode` | boolean | 否 | 个人/单用户模式:TIP、OIDC session、凭据仅存储在 `agent:main:main`(不做按发送者或 per-channel-peer 隔离)。子 agent 会话不变。默认 false;多租户或群聊共享场景勿开启。 |
|
|
198
209
|
|
|
199
210
|
\* AK/SK 至少通过 `accessKeyId`+`secretAccessKey`、环境变量、`credentialsMetadataUrl`+`roleTrn` 或 `credentialsFile` 之一提供。
|
|
200
211
|
|
|
@@ -243,8 +254,8 @@ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
|
|
|
243
254
|
|
|
244
255
|
| 方法 | 参数 | 响应 | 描述 |
|
|
245
256
|
| --- | --- | --- | --- |
|
|
246
|
-
| `identity.session.put` | `{ sessionKey, idToken, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | 将 OIDC id_token 注入到插件 session
|
|
247
|
-
| `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey }` | 获取指定 session 已存储的 user token
|
|
257
|
+
| `identity.session.put` | `{ sessionKey, idToken, refreshToken?, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | 将 OIDC id_token 注入到插件 session;可选传入 `refreshToken`(加密存储),用于静默续期。通过 `buildEffectiveSessionKey` 解析实际存储 key(与 hooks/commands 相同的隔离逻辑)。 |
|
|
258
|
+
| `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey, hasRefreshToken }` | 获取指定 session 已存储的 user token。`hasRefreshToken` 表示是否存有 refresh token;响应中不会返回 refresh token 明文。 |
|
|
248
259
|
|
|
249
260
|
- `senderId` 默认值为 `"openclaw-control-ui"`。对于 main session,实际存储 key 为 `agent:main:main:user:<senderId>`。
|
|
250
261
|
- `channel` 可选;当 session 来源于可发送消息的渠道(feishu、telegram 等)时传入,可启用 per-channel-peer key 提升。
|
|
@@ -264,7 +275,7 @@ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
|
|
|
264
275
|
**典型流程(BFF → webchat → plugin):**
|
|
265
276
|
|
|
266
277
|
1. BFF 完成 3LO 登录并获取用户的 OIDC `id_token`
|
|
267
|
-
2. Webchat 客户端调用 `identity.session.put`,传入 session key 和 `id_token`
|
|
278
|
+
2. Webchat 客户端调用 `identity.session.put`,传入 session key 和 `id_token`(若需静默续期,可一并传入 token 响应中的 `refresh_token` 作为 `refreshToken`)
|
|
268
279
|
3. 插件校验 token,存储 session,并获取 TIP
|
|
269
280
|
4. 后续该 session 中的 agent 运行拥有有效身份——无需手动登录
|
|
270
281
|
|
|
@@ -274,20 +285,22 @@ TIP token 通过 `GetWorkloadAccessTokenForJWT` 获取。工作负载行为:
|
|
|
274
285
|
|
|
275
286
|
## 工具
|
|
276
287
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
281
|
-
- **
|
|
282
|
-
- **
|
|
283
|
-
- **
|
|
284
|
-
- **
|
|
285
|
-
- **
|
|
286
|
-
- **
|
|
287
|
-
- **
|
|
288
|
-
- **
|
|
289
|
-
- **
|
|
290
|
-
- **identity_list_risk_patterns**
|
|
288
|
+
面向 Agent 的用法见 [`skills/SKILL.md`](skills/SKILL.md)。本插件注册的工具有:
|
|
289
|
+
|
|
290
|
+
- **identity_whoami** — 会话身份(sub、TIP)
|
|
291
|
+
- **identity_status** — 登录、TIP、凭据、绑定
|
|
292
|
+
- **identity_login** / **identity_logout** — OIDC 登录或刷新 TIP;清除会话
|
|
293
|
+
- **identity_list_credentials** — OAuth/API key 类 provider 与已存凭据(支持 `page`、`name`、`flow`、`type` 过滤)
|
|
294
|
+
- **identity_list_roles** — STS 角色类凭据提供方(`name` 前缀过滤)
|
|
295
|
+
- **identity_fetch** — 添加凭据(`provider`、`flow`、`redirectUrl`、`scopes`、`returnValue`)
|
|
296
|
+
- **identity_get_role_credentials** — 某角色提供方的 STS 临时凭据(`providerName`、`useTip`)
|
|
297
|
+
- **identity_get_tip_token** / **identity_get_session_token** — 原始 TIP JWT 或会话 user token(进阶场景)
|
|
298
|
+
- **identity_config** — 当前生效配置(脱敏)
|
|
299
|
+
- **identity_config_suggest** — 可合并的配置片段(`intent`、`lang`)
|
|
300
|
+
- **identity_set_binding** / **identity_unset_binding** — 工具注入用的环境变量绑定
|
|
301
|
+
- **identity_risk_check** / **identity_list_risk_patterns** — 风险评估(可选插件能力)
|
|
302
|
+
- **identity_approve_tool** — 可选;**仅供人工审批** — 推荐 `/identity approve <id>`(模型不得自批)
|
|
303
|
+
- **identity_list_tips** — 所有有效 TIP 与绑定(运维 / 多会话排查)
|
|
291
304
|
|
|
292
305
|
## 钩子
|
|
293
306
|
|
package/README.md
CHANGED
|
@@ -39,6 +39,8 @@ Single command `/identity` (alias `/id`) with subcommands. Default with no args:
|
|
|
39
39
|
| `list-tips` | List all valid TIP tokens with delegation chain, expiry, and env bindings. |
|
|
40
40
|
| `config` | Show identity plugin config (sensitive values redacted). |
|
|
41
41
|
| `list-credentials` or `list [page]` | List providers from control plane (paginated) and your credentials with bound env. Use `list 2` to load more. |
|
|
42
|
+
| `list-roles` | List STS role credential providers (not OAuth/API key). Optional name prefix filter. |
|
|
43
|
+
| `get-role <provider> [--use-tip] [--show-secrets]` | Get temporary STS credentials for a role provider (masked by default). |
|
|
42
44
|
| `fetch <provider> [--flow=...]` | Add credential. Flow auto-inferred from provider type (api_key/oauth2/m2m); override with `--flow`. |
|
|
43
45
|
| `set <provider> <envVar>` | Bind credential to env var for tool injection. If no credential, import from `process.env[envVar]`. |
|
|
44
46
|
| `unset <provider>` | Remove env binding for provider. |
|
|
@@ -104,7 +106,8 @@ The plugin typically needs three types of config:
|
|
|
104
106
|
|
|
105
107
|
**A. Platform access (Identity)**: For TIP Token, credential fetch/hosting, and optional permission checks.
|
|
106
108
|
|
|
107
|
-
- `endpoint
|
|
109
|
+
- `endpoint` (optional): Full Identity API base URL (e.g. `https://id.cn-beijing.volcengineapi.com`). **Highest priority** for the API host.
|
|
110
|
+
- `regionMetadataUrl` (optional): HTTP(S) URL that returns a **plain-text region id** (e.g. `cn-beijing`). Used only when `endpoint` is **unset**: the client builds `https://id.{region}.volcengineapi.com`. Request timeout ~10s; on failure or invalid body (e.g. `unknown`), falls back to `https://id.cn-beijing.volcengineapi.com`. Example metadata URL: `http://100.96.0.96/latest/region_id` (must be reachable from the gateway).
|
|
108
111
|
- `accessKeyId` / `secretAccessKey`: For Identity API access. **Optional** when using env vars or credential file (see below).
|
|
109
112
|
- `workloadPoolName` / `workloadName`: For issuing TIP Token. Defaults: `default`, `openclaw-agent`.
|
|
110
113
|
- `audience` / `durationSeconds`: Optional, token audience and validity.
|
|
@@ -113,6 +116,10 @@ The plugin typically needs three types of config:
|
|
|
113
116
|
- `roleTrn`: Role TRN for STS AssumeRole. When set (and `workloadName` not set), workload name is omitted; backend uses roleName. Priority: `workloadName` > `roleTrn` > params. Used with `credentialsMetadataUrl` (AssumeRole after fetch) or explicit AK/SK.
|
|
114
117
|
- `sessionToken`: STS session token (or use `VOLCENGINE_SESSION_TOKEN` env).
|
|
115
118
|
|
|
119
|
+
**Identity API host resolution**: `endpoint` if set → else region from `regionMetadataUrl` → else `https://id.cn-beijing.volcengineapi.com`. **SigV4 signing region** is inferred from the resolved host when it matches `id.{region}.volcengineapi.com`; otherwise `cn-beijing`.
|
|
120
|
+
|
|
121
|
+
**Workload pool (credentials / STS)**: `workloadPoolName` (default `default`) scopes `ListCredentialProviders`, `ListRoleCredentialProviders`, and control-plane calls such as `GetResourceOauth2Token`, `GetResourceApiKey`, `GetUserCredential`, and `GetRoleCredentials` via `PoolName`. Role provider listing also filters by `userpool.userPoolName` when configured.
|
|
122
|
+
|
|
116
123
|
**Credential resolution order** (AK/SK): 1) Explicit config → 2) Env vars (`VOLCENGINE_ACCESS_KEY`, `VOLCENGINE_SECRET_KEY`, `VOLCENGINE_SESSION_TOKEN`) → 3) Remote metadata (`credentialsMetadataUrl` + `roleTrn`, fetches from full URL then AssumeRole; 404 falls through) → 4) Credential file (`credentialsFile` config, or `VOLCENGINE_CREDENTIALS_FILE` env, or `/var/run/secrets/iam/credential`). Credential file format (VeFaaS): `access_key_id`, `secret_access_key`, `session_token` (optional), `role_trn` (optional for AssumeRole). `RUNTIME_IAM_ROLE_TRN` env can supply role TRN when loading from file.
|
|
117
124
|
|
|
118
125
|
**B. User login (UserPool / OIDC)**: For `/identity login` and session setup.
|
|
@@ -121,6 +128,8 @@ The plugin typically needs three types of config:
|
|
|
121
128
|
- `clientId` / `clientSecret` (auto-resolved in dynamic mode)
|
|
122
129
|
- `callbackUrl`: Public callback URL for OpenClaw gateway, e.g. `http://127.0.0.1:18789/identity/oauth/callback`
|
|
123
130
|
- `scope`: Typically `openid profile email`
|
|
131
|
+
- `identityProvider` (optional): IdP name for the `identity_provider` authorize param. When omitted, the first entry from `ListIdentityProviders` is used.
|
|
132
|
+
- `useRelayCallback` (optional): UserPool relay / `redirect_relay_uri` flow for OIDC callback. Default false.
|
|
124
133
|
|
|
125
134
|
**C. AuthZ and risk approval (optional)**: For TIP + CheckPermission + risk evaluation. Each flag is independent; no single "enable" switch.
|
|
126
135
|
|
|
@@ -182,7 +191,8 @@ Add to `openclaw.json` under `plugins.entries.agent-identity.config`:
|
|
|
182
191
|
|
|
183
192
|
| Param | Type | Required | Description |
|
|
184
193
|
|-------|------|----------|--------------|
|
|
185
|
-
| `endpoint` | string |
|
|
194
|
+
| `endpoint` | string | No | Identity API base URL. Omit to use `regionMetadataUrl` or default `https://id.cn-beijing.volcengineapi.com` |
|
|
195
|
+
| `regionMetadataUrl` | string | No | Plain-text region id URL; builds `https://id.{region}.volcengineapi.com` when `endpoint` unset |
|
|
186
196
|
| `accessKeyId` | string | No* | Volcengine Access Key. Omit to load from `VOLCENGINE_ACCESS_KEY` or `credentialsFile` |
|
|
187
197
|
| `secretAccessKey` | string | No* | Volcengine Secret Key. Omit to load from `VOLCENGINE_SECRET_KEY` or `credentialsFile` |
|
|
188
198
|
| `workloadPoolName` | string | No | Workload pool name, default `default` |
|
|
@@ -195,6 +205,7 @@ Add to `openclaw.json` under `plugins.entries.agent-identity.config`:
|
|
|
195
205
|
| `sessionToken` | string | No | STS session token (or `VOLCENGINE_SESSION_TOKEN`) |
|
|
196
206
|
| `subagentTipPropagation` | boolean | No | Propagate TIP and session to subagents. Default false |
|
|
197
207
|
| `webchatSessionExchange` | boolean | No | Enable `identity.session.put` / `identity.session.get` gateway WS methods for webchat clients. Default false |
|
|
208
|
+
| `personalSessionMode` | boolean | No | Single-user mode: TIP, OIDC session, and credentials are stored only under `agent:main:main` (no per-sender or per-channel-peer keys). Subagent sessions unchanged. Default false — do not enable for multi-tenant or shared groups. |
|
|
198
209
|
|
|
199
210
|
\* AK/SK must be provided via `accessKeyId`+`secretAccessKey`, environment variables, `credentialsMetadataUrl`+`roleTrn`, or `credentialsFile`.
|
|
200
211
|
|
|
@@ -243,8 +254,8 @@ When `identity.webchatSessionExchange` is `true`, the plugin registers two gatew
|
|
|
243
254
|
|
|
244
255
|
| Method | Params | Response | Description |
|
|
245
256
|
| --- | --- | --- | --- |
|
|
246
|
-
| `identity.session.put` | `{ sessionKey, idToken, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | Inject an OIDC id_token into a plugin session. Resolves effective storage key via `buildEffectiveSessionKey` (same sender isolation as hooks/commands). |
|
|
247
|
-
| `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey }` | Retrieve the stored user token for a session. |
|
|
257
|
+
| `identity.session.put` | `{ sessionKey, idToken, refreshToken?, senderId?, channel? }` | `{ sub, expiresAt, effectiveSessionKey, hasTip }` | Inject an OIDC id_token into a plugin session; optional `refreshToken` is stored encrypted for silent token renewal. Resolves effective storage key via `buildEffectiveSessionKey` (same sender isolation as hooks/commands). |
|
|
258
|
+
| `identity.session.get` | `{ sessionKey, senderId?, channel? }` | `{ userToken, sub, expiresAt, effectiveSessionKey, hasRefreshToken }` | Retrieve the stored user token for a session. `hasRefreshToken` indicates whether a refresh token is stored; the refresh token value is never returned. |
|
|
248
259
|
|
|
249
260
|
- `senderId` defaults to `"openclaw-control-ui"`. The effective storage key is `agent:main:main:user:<senderId>` for main sessions.
|
|
250
261
|
- `channel` is optional; when the session originates from a sendable channel (feishu, telegram, etc.), pass it to enable per-channel-peer key promotion.
|
|
@@ -264,7 +275,7 @@ Both methods are **restricted to webchat WS connections only** (`isWebchatConnec
|
|
|
264
275
|
**Typical flow (BFF → webchat → plugin):**
|
|
265
276
|
|
|
266
277
|
1. BFF completes 3LO login and obtains an OIDC `id_token` for the user
|
|
267
|
-
2. Webchat client calls `identity.session.put` with the session key and `id_token`
|
|
278
|
+
2. Webchat client calls `identity.session.put` with the session key and `id_token` (optionally `refreshToken` from the token response if silent renewal is desired)
|
|
268
279
|
3. Plugin verifies the token, stores the session, and acquires TIP
|
|
269
280
|
4. Subsequent agent runs in that session have a valid identity — no manual login needed
|
|
270
281
|
|
|
@@ -274,20 +285,22 @@ Follow-up messages (login success, credential fetch done) are not delivered when
|
|
|
274
285
|
|
|
275
286
|
## Tools
|
|
276
287
|
|
|
277
|
-
-
|
|
278
|
-
|
|
279
|
-
- **
|
|
280
|
-
- **
|
|
281
|
-
- **
|
|
282
|
-
- **
|
|
283
|
-
- **
|
|
284
|
-
- **
|
|
285
|
-
- **
|
|
286
|
-
- **
|
|
287
|
-
- **
|
|
288
|
-
- **
|
|
289
|
-
- **
|
|
290
|
-
- **
|
|
288
|
+
Agent-facing behavior is summarized in [`skills/SKILL.md`](skills/SKILL.md). Registered tools:
|
|
289
|
+
|
|
290
|
+
- **identity_whoami** — Session identity (sub, TIP)
|
|
291
|
+
- **identity_status** — Login, TIP, credentials, bindings
|
|
292
|
+
- **identity_login** / **identity_logout** — OIDC login or refresh TIP; clear session
|
|
293
|
+
- **identity_list_credentials** — OAuth/API key providers and stored credentials (`page`, `name`, `flow`, `type` filters)
|
|
294
|
+
- **identity_list_roles** — STS role credential providers (`name` prefix filter)
|
|
295
|
+
- **identity_fetch** — Add credential (`provider`, `flow`, `redirectUrl`, `scopes`, `returnValue`)
|
|
296
|
+
- **identity_get_role_credentials** — STS credentials for a role provider (`providerName`, `useTip`)
|
|
297
|
+
- **identity_get_tip_token** / **identity_get_session_token** — Raw TIP JWT or session user token (advanced)
|
|
298
|
+
- **identity_config** — Effective plugin config (redacted)
|
|
299
|
+
- **identity_config_suggest** — Config merge snippets (`intent`, `lang`)
|
|
300
|
+
- **identity_set_binding** / **identity_unset_binding** — Env var bindings for tool injection
|
|
301
|
+
- **identity_risk_check** / **identity_list_risk_patterns** — Risk evaluation (optional plugin)
|
|
302
|
+
- **identity_approve_tool** — Optional; **human approval only** — prefer `/identity approve <id>` (agents must not self-approve)
|
|
303
|
+
- **identity_list_tips** — All valid TIP tokens and bindings (ops / multi-session debug)
|
|
291
304
|
|
|
292
305
|
## Hooks
|
|
293
306
|
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAmF7D,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,GAAG,EAAE,iBAAiB,QA+etD"}
|
package/dist/index.js
CHANGED
|
@@ -13,15 +13,18 @@
|
|
|
13
13
|
* See the License for the specific language governing permissions and
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
|
+
import { runPluginPreflight } from "./src/preflight/plugin-preflight.js";
|
|
17
|
+
import { pluginState } from "./src/preflight/plugin-state.js";
|
|
16
18
|
import { createIdentityCommand, createIdCommand } from "./src/commands/identity-commands.js";
|
|
17
19
|
import { createBeforeAgentStartHandler } from "./src/hooks/before-agent-start.js";
|
|
18
20
|
import { createLlmInputHandler } from "./src/hooks/llm-input.js";
|
|
19
21
|
import { createSessionsSendPropagationHandler } from "./src/hooks/sessions-send-propagation.js";
|
|
20
22
|
import { createSessionsSpawnPropagationHandler } from "./src/hooks/sessions-spawn-propagation.js";
|
|
21
23
|
import { createSubagentEndedCleanupHandler } from "./src/hooks/subagent-ended-cleanup.js";
|
|
22
|
-
import { setSender, clearSender } from "./src/store/sender-session-store.js";
|
|
24
|
+
import { setSender, clearSender, setPersonalSessionMode } from "./src/store/sender-session-store.js";
|
|
23
25
|
import { deriveSessionKey, needsSenderIsolation, } from "./src/utils/derive-session-key.js";
|
|
24
26
|
import { createBeforeToolCallHandler } from "./src/hooks/before-tool-call.js";
|
|
27
|
+
import { createToolResultPersistHandler } from "./src/hooks/tool-result-persist.js";
|
|
25
28
|
import { createAfterToolCallHandler } from "./src/hooks/after-tool-call.js";
|
|
26
29
|
import * as skillPathStore from "./src/store/skill-path-store.js";
|
|
27
30
|
import { createOIDCCallbackHandler, createOIDCCallbackHandlerLazy, } from "./src/routes/oidc-login.js";
|
|
@@ -34,7 +37,11 @@ import { createIdentityConfigSuggestTool } from "./src/tools/identity-config-sug
|
|
|
34
37
|
import { createIdentityListRiskPatternsTool } from "./src/tools/identity-list-risk-patterns.js";
|
|
35
38
|
import { createIdentityRiskCheckTool } from "./src/tools/identity-risk-check.js";
|
|
36
39
|
import { createIdentityFetchTool } from "./src/tools/identity-fetch.js";
|
|
40
|
+
import { createIdentityGetRoleCredentialsTool } from "./src/tools/identity-get-role-credentials.js";
|
|
41
|
+
import { createIdentityGetTipTokenTool } from "./src/tools/identity-get-tip-token.js";
|
|
42
|
+
import { createIdentityGetSessionTokenTool } from "./src/tools/identity-get-session-token.js";
|
|
37
43
|
import { createIdentityListCredentialsTool } from "./src/tools/identity-list-credentials.js";
|
|
44
|
+
import { createIdentityListRolesTool } from "./src/tools/identity-list-roles.js";
|
|
38
45
|
import { createIdentityListTipsTool } from "./src/tools/identity-list-tips.js";
|
|
39
46
|
import { createIdentityLoginTool } from "./src/tools/identity-login.js";
|
|
40
47
|
import { createIdentityLogoutTool } from "./src/tools/identity-logout.js";
|
|
@@ -54,6 +61,7 @@ function hasAnyIdentityConfig(identity) {
|
|
|
54
61
|
if (!identity)
|
|
55
62
|
return false;
|
|
56
63
|
return Boolean(identity.endpoint ||
|
|
64
|
+
identity.regionMetadataUrl ||
|
|
57
65
|
identity.accessKeyId ||
|
|
58
66
|
identity.secretAccessKey ||
|
|
59
67
|
identity.sessionToken ||
|
|
@@ -70,11 +78,16 @@ export default function register(api) {
|
|
|
70
78
|
const storeDir = api.resolvePath(PLUGIN_STORE_DIR);
|
|
71
79
|
initEncryptionKey(storeDir);
|
|
72
80
|
const identityCfg = pluginConfig.identity;
|
|
81
|
+
setPersonalSessionMode(identityCfg?.personalSessionMode === true);
|
|
82
|
+
if (identityCfg?.personalSessionMode) {
|
|
83
|
+
logInfo(api.logger, "identity.personalSessionMode: non-subagent TIP/session/credentials use agent:main:main only");
|
|
84
|
+
}
|
|
73
85
|
const hasIdentity = hasAnyIdentityConfig(identityCfg);
|
|
74
86
|
const userpool = pluginConfig.userpool;
|
|
75
87
|
const identityClient = hasIdentity
|
|
76
88
|
? new IdentityClient({
|
|
77
|
-
endpoint: identityCfg?.endpoint
|
|
89
|
+
endpoint: identityCfg?.endpoint,
|
|
90
|
+
regionMetadataUrl: identityCfg?.regionMetadataUrl,
|
|
78
91
|
accessKeyId: identityCfg?.accessKeyId,
|
|
79
92
|
secretAccessKey: identityCfg?.secretAccessKey,
|
|
80
93
|
sessionToken: identityCfg?.sessionToken,
|
|
@@ -96,6 +109,9 @@ export default function register(api) {
|
|
|
96
109
|
getResourceApiKey: async () => {
|
|
97
110
|
throw new Error("Identity not configured.");
|
|
98
111
|
},
|
|
112
|
+
getUserCredential: async () => {
|
|
113
|
+
throw new Error("Identity not configured.");
|
|
114
|
+
},
|
|
99
115
|
checkPermission: async () => {
|
|
100
116
|
throw new Error("Identity not configured.");
|
|
101
117
|
},
|
|
@@ -106,9 +122,24 @@ export default function register(api) {
|
|
|
106
122
|
PageNumber: 1,
|
|
107
123
|
PageSize: 20,
|
|
108
124
|
}),
|
|
125
|
+
listRoleCredentialProviders: async () => ({
|
|
126
|
+
RoleCredentialProviders: [],
|
|
127
|
+
TotalCount: 0,
|
|
128
|
+
PageNumber: 1,
|
|
129
|
+
PageSize: 20,
|
|
130
|
+
}),
|
|
131
|
+
getRoleCredentials: async () => {
|
|
132
|
+
throw new Error("Identity not configured.");
|
|
133
|
+
},
|
|
109
134
|
getUserPool: async () => {
|
|
110
135
|
throw new Error("Identity not configured.");
|
|
111
136
|
},
|
|
137
|
+
listIdentityProviders: async () => ({
|
|
138
|
+
pageNumber: 1,
|
|
139
|
+
pageSize: 10,
|
|
140
|
+
totalCount: 0,
|
|
141
|
+
data: [],
|
|
142
|
+
}),
|
|
112
143
|
listUserPools: async () => ({
|
|
113
144
|
pageNumber: 1,
|
|
114
145
|
pageSize: 10,
|
|
@@ -278,23 +309,29 @@ export default function register(api) {
|
|
|
278
309
|
getOidcConfigForRefresh: getOidcConfigForRefresh ?? undefined,
|
|
279
310
|
configWorkloadName: identityCfg?.workloadName,
|
|
280
311
|
identityClient: hasIdentity ? identityClient : undefined,
|
|
312
|
+
workloadPoolName: identityCfg?.workloadPoolName ?? "default",
|
|
313
|
+
userPoolName: userpool?.userPoolName,
|
|
281
314
|
logger: api.logger,
|
|
282
315
|
pluginConfig,
|
|
283
316
|
sendCredentialMessage: sendToSession,
|
|
284
317
|
};
|
|
285
318
|
api.registerCommand(createIdentityCommand(identityCommandsDeps));
|
|
286
319
|
api.registerCommand(createIdCommand(identityCommandsDeps));
|
|
287
|
-
logInfo(api.logger, "commands /identity, /id (login, status, logout, list-
|
|
320
|
+
logInfo(api.logger, "commands /identity, /id (login, status, logout, list, list-roles, list-tips, fetch, set, unset); HTTP callback /identity/oauth/callback (credential OAuth uses Identity callback)");
|
|
288
321
|
// Tools (share deps with commands). Optional = only included when agent allowlist explicitly adds them.
|
|
289
322
|
api.registerTool(createIdentityWhoamiTool(identityCommandsDeps), { optional: false });
|
|
290
323
|
api.registerTool(createIdentityLogoutTool(identityCommandsDeps), { optional: false });
|
|
291
324
|
api.registerTool(createIdentityStatusTool(identityCommandsDeps), { optional: false });
|
|
292
325
|
api.registerTool(createIdentityLoginTool(identityCommandsDeps), { optional: false });
|
|
293
326
|
api.registerTool(createIdentityListCredentialsTool(identityCommandsDeps), { optional: false });
|
|
327
|
+
api.registerTool(createIdentityListRolesTool(identityCommandsDeps), { optional: false });
|
|
294
328
|
api.registerTool(createIdentityListTipsTool(identityCommandsDeps), { optional: false });
|
|
295
329
|
api.registerTool(createIdentityConfigTool(identityCommandsDeps), { optional: false });
|
|
296
330
|
api.registerTool(createIdentityConfigSuggestTool(), { optional: false });
|
|
297
331
|
api.registerTool(createIdentityFetchTool(identityCommandsDeps), { optional: false });
|
|
332
|
+
api.registerTool(createIdentityGetRoleCredentialsTool(identityCommandsDeps), { optional: false });
|
|
333
|
+
api.registerTool(createIdentityGetTipTokenTool(identityCommandsDeps), { optional: false });
|
|
334
|
+
api.registerTool(createIdentityGetSessionTokenTool(identityCommandsDeps), { optional: false });
|
|
298
335
|
api.registerTool(createIdentitySetBindingTool(identityCommandsDeps), { optional: true });
|
|
299
336
|
api.registerTool(createIdentityUnsetBindingTool(identityCommandsDeps), { optional: true });
|
|
300
337
|
api.registerTool(createIdentityRiskCheckTool({ pluginConfig, logger: api.logger }), { optional: true });
|
|
@@ -391,12 +428,12 @@ export default function register(api) {
|
|
|
391
428
|
logger: api.logger,
|
|
392
429
|
}));
|
|
393
430
|
if (skillReadCheck) {
|
|
394
|
-
api.on("session_end", (
|
|
395
|
-
if (
|
|
396
|
-
skillPathStore.clearSessionById(
|
|
431
|
+
api.on("session_end", (event) => {
|
|
432
|
+
if (event.sessionId)
|
|
433
|
+
skillPathStore.clearSessionById(event.sessionId);
|
|
397
434
|
});
|
|
398
435
|
}
|
|
399
|
-
// before_tool_call: authz, credential injection, group sender context
|
|
436
|
+
// before_tool_call: authz, credential injection, group sender context, contract injection
|
|
400
437
|
api.on("before_tool_call", createBeforeToolCallHandler({
|
|
401
438
|
storeDir,
|
|
402
439
|
identityClient: hasIdentity ? identityClient : undefined,
|
|
@@ -408,9 +445,11 @@ export default function register(api) {
|
|
|
408
445
|
identityService: hasIdentity ? identityService : undefined,
|
|
409
446
|
getOidcConfigForRefresh: getOidcConfigForRefresh ?? undefined,
|
|
410
447
|
configWorkloadName: identityCfg?.workloadName,
|
|
448
|
+
workspaceDir: api.resolvePath?.(".") ?? undefined,
|
|
411
449
|
}));
|
|
412
450
|
// Companion after_tool_call: restore env snapshot set by credential injection
|
|
413
451
|
api.on("after_tool_call", createAfterToolCallHandler({ logger: api.logger }));
|
|
452
|
+
api.on("tool_result_persist", createToolResultPersistHandler({ logger: api.logger }));
|
|
414
453
|
// Gateway WS methods: webchat session exchange (inject / retrieve user token)
|
|
415
454
|
if (identityCfg?.webchatSessionExchange && hasIdentity) {
|
|
416
455
|
const sessionMethodDeps = {
|
|
@@ -424,4 +463,38 @@ export default function register(api) {
|
|
|
424
463
|
api.registerGatewayMethod("identity.session.get", createSessionGetHandler(sessionMethodDeps));
|
|
425
464
|
logInfo(api.logger, "gateway methods: identity.session.put, identity.session.get (webchat session exchange)");
|
|
426
465
|
}
|
|
466
|
+
// Preflight: run async after register() returns so startup is never blocked.
|
|
467
|
+
// On any failure, set pluginState.degraded so hooks skip all interception.
|
|
468
|
+
const authzEnabled = !!(authz?.agentCheck || authz?.toolCheck || authz?.requireRiskApproval);
|
|
469
|
+
runPluginPreflight({
|
|
470
|
+
identityClient,
|
|
471
|
+
identityService,
|
|
472
|
+
hasIdentity,
|
|
473
|
+
credentialConfig: identityCfg
|
|
474
|
+
? {
|
|
475
|
+
accessKeyId: identityCfg.accessKeyId,
|
|
476
|
+
secretAccessKey: identityCfg.secretAccessKey,
|
|
477
|
+
sessionToken: identityCfg.sessionToken,
|
|
478
|
+
credentialsFile: identityCfg.credentialsFile,
|
|
479
|
+
credentialsMetadataUrl: identityCfg.credentialsMetadataUrl,
|
|
480
|
+
roleTrn: identityCfg.roleTrn,
|
|
481
|
+
}
|
|
482
|
+
: undefined,
|
|
483
|
+
userpool: dynamicOidcEnabled
|
|
484
|
+
? { mode: "dynamic", userPoolName: userpool?.userPoolName }
|
|
485
|
+
: explicitOidcEnabled
|
|
486
|
+
? { mode: "explicit", discoveryUrl: userpool?.discoveryUrl }
|
|
487
|
+
: undefined,
|
|
488
|
+
workloadPoolName: identityCfg?.workloadPoolName,
|
|
489
|
+
authzEnabled,
|
|
490
|
+
namespaceName: authz?.namespaceName ?? "default",
|
|
491
|
+
logger: api.logger,
|
|
492
|
+
}).then((result) => {
|
|
493
|
+
if (!result.ok) {
|
|
494
|
+
pluginState.degraded = true;
|
|
495
|
+
pluginState.failures = result.failures;
|
|
496
|
+
}
|
|
497
|
+
}).catch((err) => {
|
|
498
|
+
logWarn(api.logger, `[identity] preflight threw unexpectedly: ${String(err)}`);
|
|
499
|
+
});
|
|
427
500
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo: read local sessions.json (with field-level decryption), resolve one sessionKey, print userToken.
|
|
3
|
+
*
|
|
4
|
+
* Same path as the plugin: initEncryptionKey(storeDir) then getSession(storeDir, sessionKey).
|
|
5
|
+
*
|
|
6
|
+
* Usage (after `pnpm build`):
|
|
7
|
+
* node dist/scripts/demo-get-session.js <sessionKey>
|
|
8
|
+
* node dist/scripts/demo-get-session.js <storeDir> <sessionKey>
|
|
9
|
+
* pnpm demo:get-session -- <sessionKey>
|
|
10
|
+
*
|
|
11
|
+
* Flags:
|
|
12
|
+
* --print-token Print full userToken (default: only prefix + length)
|
|
13
|
+
*/
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=demo-get-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo-get-session.d.ts","sourceRoot":"","sources":["../../scripts/demo-get-session.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Demo: read local sessions.json (with field-level decryption), resolve one sessionKey, print userToken.
|
|
3
|
+
*
|
|
4
|
+
* Same path as the plugin: initEncryptionKey(storeDir) then getSession(storeDir, sessionKey).
|
|
5
|
+
*
|
|
6
|
+
* Usage (after `pnpm build`):
|
|
7
|
+
* node dist/scripts/demo-get-session.js <sessionKey>
|
|
8
|
+
* node dist/scripts/demo-get-session.js <storeDir> <sessionKey>
|
|
9
|
+
* pnpm demo:get-session -- <sessionKey>
|
|
10
|
+
*
|
|
11
|
+
* Flags:
|
|
12
|
+
* --print-token Print full userToken (default: only prefix + length)
|
|
13
|
+
*/
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import os from "node:os";
|
|
16
|
+
import { initEncryptionKey } from "../src/store/encryption.js";
|
|
17
|
+
import { getSession } from "../src/store/session-store.js";
|
|
18
|
+
function usage() {
|
|
19
|
+
console.error(`Usage: demo-get-session [--print-token] <sessionKey>
|
|
20
|
+
demo-get-session [--print-token] <storeDir> <sessionKey>
|
|
21
|
+
|
|
22
|
+
storeDir defaults to ~/.openclaw/plugins/identity`);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
async function main() {
|
|
26
|
+
const printToken = process.argv.includes("--print-token");
|
|
27
|
+
const args = process.argv.slice(2).filter((a) => a !== "--print-token");
|
|
28
|
+
if (args.length < 1 || args.length > 2)
|
|
29
|
+
usage();
|
|
30
|
+
const storeDir = args.length === 2
|
|
31
|
+
? path.resolve(args[0])
|
|
32
|
+
: path.join(os.homedir(), ".openclaw", "plugins", "identity");
|
|
33
|
+
const sessionKey = args.length === 2 ? args[1] : args[0];
|
|
34
|
+
initEncryptionKey(storeDir);
|
|
35
|
+
const session = await getSession(storeDir, sessionKey);
|
|
36
|
+
if (!session) {
|
|
37
|
+
console.log(JSON.stringify({ ok: false, reason: "no session or expired", storeDir, sessionKey }, null, 2));
|
|
38
|
+
process.exit(2);
|
|
39
|
+
}
|
|
40
|
+
const tokenPreview = printToken
|
|
41
|
+
? session.userToken
|
|
42
|
+
: `${session.userToken.slice(0, 12)}… (${session.userToken.length} chars)`;
|
|
43
|
+
console.log(JSON.stringify({
|
|
44
|
+
ok: true,
|
|
45
|
+
storeDir,
|
|
46
|
+
sessionKey,
|
|
47
|
+
sub: session.sub,
|
|
48
|
+
loginAt: session.loginAt,
|
|
49
|
+
expiresAt: session.expiresAt ?? null,
|
|
50
|
+
hasRefreshToken: Boolean(session.refreshToken),
|
|
51
|
+
claims: session.claims ?? null,
|
|
52
|
+
userToken: tokenPreview,
|
|
53
|
+
}, null, 2));
|
|
54
|
+
}
|
|
55
|
+
main().catch((err) => {
|
|
56
|
+
console.error(err);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
});
|
|
@@ -15,6 +15,10 @@ export type OIDCConfigForCommand = {
|
|
|
15
15
|
clientSecret?: string;
|
|
16
16
|
scope?: string;
|
|
17
17
|
callbackUrl: string;
|
|
18
|
+
/** UserPool UID (available when resolved dynamically via resolveOIDCConfig). */
|
|
19
|
+
poolUid?: string;
|
|
20
|
+
/** First identity provider cached at config resolve time. */
|
|
21
|
+
identityProvider?: string;
|
|
18
22
|
};
|
|
19
23
|
export type IdentityActionsLogger = {
|
|
20
24
|
info?: (msg: string) => void;
|
|
@@ -28,11 +32,13 @@ export type IdentityActionsDeps = {
|
|
|
28
32
|
getOidcConfigForRefresh?: () => Promise<OIDCConfigForRefresh>;
|
|
29
33
|
configWorkloadName?: string;
|
|
30
34
|
identityClient?: IdentityClientInterface;
|
|
35
|
+
workloadPoolName?: string;
|
|
36
|
+
userPoolName?: string;
|
|
31
37
|
logger?: IdentityActionsLogger;
|
|
32
38
|
pluginConfig?: PluginConfig;
|
|
33
39
|
sendCredentialMessage?: (targetOrSessionKey: SessionKeyDeliveryTarget | string, text: string) => Promise<void>;
|
|
34
40
|
};
|
|
35
|
-
export type FetchFlow = "oauth2-user" | "oauth2-m2m" | "apikey";
|
|
41
|
+
export type FetchFlow = "oauth2-user" | "oauth2-m2m" | "apikey" | "user";
|
|
36
42
|
export type StatusResult = {
|
|
37
43
|
loggedIn: boolean;
|
|
38
44
|
sub: string | null;
|
|
@@ -69,14 +75,15 @@ export type LogoutResult = {
|
|
|
69
75
|
ok: boolean;
|
|
70
76
|
};
|
|
71
77
|
export declare function runLogout(deps: IdentityActionsDeps, sessionKey: string): Promise<LogoutResult>;
|
|
78
|
+
export type ProviderRow = {
|
|
79
|
+
name: string;
|
|
80
|
+
type: string;
|
|
81
|
+
flow?: string;
|
|
82
|
+
status: string;
|
|
83
|
+
binding?: string;
|
|
84
|
+
};
|
|
72
85
|
export type ListCredentialsResult = {
|
|
73
|
-
providers:
|
|
74
|
-
name: string;
|
|
75
|
-
type: string;
|
|
76
|
-
flow?: string;
|
|
77
|
-
status: string;
|
|
78
|
-
binding?: string;
|
|
79
|
-
}>;
|
|
86
|
+
providers: ProviderRow[];
|
|
80
87
|
storedOnly: Array<{
|
|
81
88
|
name: string;
|
|
82
89
|
status: string;
|
|
@@ -89,8 +96,21 @@ export type ListCredentialsResult = {
|
|
|
89
96
|
export type ListCredentialsFilter = {
|
|
90
97
|
name?: string;
|
|
91
98
|
flow?: string;
|
|
99
|
+
type?: string;
|
|
92
100
|
};
|
|
93
101
|
export declare function runListCredentials(deps: IdentityActionsDeps, sessionKey: string, page?: number, filter?: ListCredentialsFilter): Promise<ListCredentialsResult>;
|
|
102
|
+
export type RoleProviderRow = {
|
|
103
|
+
name: string;
|
|
104
|
+
identitySource?: string;
|
|
105
|
+
};
|
|
106
|
+
export type ListRoleCredentialsResult = {
|
|
107
|
+
providers: RoleProviderRow[];
|
|
108
|
+
page: number;
|
|
109
|
+
hasMore: boolean;
|
|
110
|
+
};
|
|
111
|
+
export declare function runListRoleCredentials(deps: IdentityActionsDeps, sessionKey: string, filter?: {
|
|
112
|
+
name?: string;
|
|
113
|
+
}): Promise<ListRoleCredentialsResult>;
|
|
94
114
|
export type ListTipsResult = {
|
|
95
115
|
tips: Array<{
|
|
96
116
|
sessionKey: string;
|
|
@@ -148,4 +168,50 @@ export type UnsetBindingResult = {
|
|
|
148
168
|
export declare function runUnsetBinding(deps: IdentityActionsDeps, sessionKey: string, params: {
|
|
149
169
|
provider: string;
|
|
150
170
|
}): Promise<UnsetBindingResult>;
|
|
171
|
+
export type GetRoleCredentialsActionResult = {
|
|
172
|
+
kind: "success";
|
|
173
|
+
credentials: {
|
|
174
|
+
AccessKeyId: string;
|
|
175
|
+
SecretAccessKey: string;
|
|
176
|
+
SessionToken: string;
|
|
177
|
+
Expiration?: string;
|
|
178
|
+
};
|
|
179
|
+
} | {
|
|
180
|
+
kind: "error";
|
|
181
|
+
message: string;
|
|
182
|
+
};
|
|
183
|
+
export declare function runGetRoleCredentials(deps: IdentityActionsDeps, sessionKey: string, params: {
|
|
184
|
+
providerName: string;
|
|
185
|
+
useTip?: boolean;
|
|
186
|
+
config?: import("openclaw/plugin-sdk").OpenClawConfig;
|
|
187
|
+
}): Promise<GetRoleCredentialsActionResult>;
|
|
188
|
+
export type GetTipTokenResult = {
|
|
189
|
+
kind: "success";
|
|
190
|
+
tipToken: string;
|
|
191
|
+
sub: string;
|
|
192
|
+
issuedAt: number;
|
|
193
|
+
expiresAt: number;
|
|
194
|
+
} | {
|
|
195
|
+
kind: "error";
|
|
196
|
+
message: string;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Return the current TIP JWT for the session (refresh/obtain via user token if needed).
|
|
200
|
+
*/
|
|
201
|
+
export declare function runGetTipToken(deps: IdentityActionsDeps, sessionKey: string, config?: OpenClawConfig): Promise<GetTipTokenResult>;
|
|
202
|
+
export type GetSessionTokenResult = {
|
|
203
|
+
kind: "success";
|
|
204
|
+
/** OIDC id_token stored for the session. */
|
|
205
|
+
sessionIdToken: string;
|
|
206
|
+
sub: string;
|
|
207
|
+
loginAt: number;
|
|
208
|
+
expiresAt?: number;
|
|
209
|
+
} | {
|
|
210
|
+
kind: "error";
|
|
211
|
+
message: string;
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* Return the OIDC id_token (user / session identity token) for the session.
|
|
215
|
+
*/
|
|
216
|
+
export declare function runGetSessionToken(deps: IdentityActionsDeps, sessionKey: string): Promise<GetSessionTokenResult>;
|
|
151
217
|
//# sourceMappingURL=identity-actions.d.ts.map
|