npm package: @m1a0rz/claw-identity
Description: Claw Identity: UserPool (用户池) login, TIP token (工作负载令牌), credential hosting (凭据托管 OAuth2/API key), optional tool/skill permission control (CheckPermission) and risk approval. Integrates with Volcengine 智能体身份和权限管理平台.
Latest version: 0.4.7

# Claw Identity Plugin

UserPool OIDC login, TIP (Trusted Identity Provider) token via Identity GetWorkloadAccessTokenForJWT, credential 3LO (GetResourceOauth2Token/Oauth2Callback), and session management for OpenClaw.

> 中文文档请参阅 [README-cn.md](README-cn.md)

Integrates with [Volcengine Agent Identity and Permission Management](https://www.volcengine.com/docs/86848).

## Features

- **OIDC Login**: `/identityclw login` returns IdP auth URL (no HTTP start endpoint). User opens URL, IdP redirects to `/clawidentity/oauth/callback`.
- **TIP Token**: `before_agent_start` hook fetches TIP token when session has a logged-in user.
- **Credential 3LO**: `/identityclw fetch <provider>` returns auth URL. IdP redirects to Identity-provided callback (control-plane config).
- **Credential Binding**: `/identityclw set <provider> <envVar>` binds stored credential to env var. Credentials are securely injected per-tool-call, isolated between concurrent multi-user sessions.
- **Encrypted Session Storage**: `sessions.json` is encrypted at rest (AES-256-GCM). Plaintext sessions from older versions are auto-migrated on first load.
- **In-memory TIP Cache**: TIP tokens are stored only in memory (no disk persistence). They are short-lived and re-obtained from the user's session token on demand.
- **Dynamic UserPool**: Resolve OIDC config by `userPoolName` + `clientName` (no manual clientId).
- **Credentials**: Load AK/SK from env, file, or STS AssumeRole (veadk-style).

## HTTP Endpoints

Only the OIDC login callback is exposed. Credential OAuth uses Identity callback. All other logic runs in slash commands.

| Path | Method | Description |
| --- | --- | --- |
| `/clawidentity/oauth/callback` | GET | OIDC login callback (IdP redirects here) |

## Slash Commands

Single command `/identityclw` (alias `/idclw`) with subcommands. Default with no args: `status`.

| Subcommand | Description |
| --- | --- |
| _(none)_ | Show help. |
| `whoami` | Show current session identity (sub, TIP status). |
| `login` | If logged in: refresh TIP. If not: return OIDC IdP URL to open. |
| `status` | Show login status, TIP, credentials. Tries to refresh TIP when session exists. |
| `logout` | Clear session and TIP for current session. |
| `list-tips` | List all valid TIP tokens with delegation chain, expiry, and env bindings. |
| `config` | Show identity plugin config (sensitive values redacted). |
| `list-credentials` or `list [page]` | List providers from control plane (paginated) and your credentials with bound env. Use `list 2` to load more. |
| `list-roles` | List STS role credential providers (not OAuth/API key). Optional name prefix filter. |
| `get-role <provider> [--use-tip] [--show-secrets]` | Get temporary STS credentials for a role provider (masked by default). |
| `fetch <provider> [--flow=...]` | Add credential. Flow auto-inferred from provider type (api_key/oauth2/m2m); override with `--flow`. |
| `set <provider> <envVar>` | Bind credential to env var for tool injection. If no credential, import from `process.env[envVar]`. |
| `unset <provider>` | Remove env binding for provider. |
| `approve <approval_id>` | Approve a pending high-risk tool call. |
| `reject <approval_id>` | Reject a pending high-risk tool call. |

## OIDC Login Flow

1. User sends `/identityclw login` in chat (e.g. Telegram, Discord)
2. Command derives sessionKey from channel/sender, builds IdP authorize URL, stores state
3. Command returns the IdP URL; user opens it in browser
4. User completes login at UserPool IdP
5. IdP redirects to `/clawidentity/oauth/callback` with `code` and `state`
6. Plugin exchanges code, creates session, shows success page and sends message to chat

## Credential Fetch Flow

**OAuth2 (user federation or M2M):**

1. User sends `/identityclw fetch google` or `/identityclw fetch google --flow=oauth2-m2m` (after `/identityclw login`)
2. Command uses TIP to call Identity API; returns auth URL or direct token
3. If auth URL: user opens it; IdP redirects to Identity callback (control-plane provider config)
4. Identity handles callback; token obtained via Identity; user may re-run fetch to pull credential

**API Key:**

1. User sends `/identityclw fetch openai` (provider type api_key in control plane) or `/identityclw fetch openai --flow=apikey`
2. Command uses TIP to call GetResourceApiKey; API key stored directly

Flow is auto-inferred from ListCredentialProviders (Type + Flow). Override with `--flow=oauth2-user|oauth2-m2m|apikey` when needed.

## Installation

```bash
openclaw plugins install @m1a0rz/claw-identity
```

Or with link for development:

```bash
openclaw plugins install --link .
```

## Configuration

Add to `openclaw.json` under `plugins.entries.claw-identity.config`:

```json
{
  "plugins": {
    "entries": {
      "claw-identity": {
        "config": {
          "identity": {
            "endpoint": "https://id.cn-beijing.volcengineapi.com",
            "workloadPoolName": "default",
            "workloadName": "openclaw-agent"
          },
          "userpool": {
            "discoveryUrl": "https://userpool-xxx.userpool.auth.id.cn-beijing.volces.com",
            "clientId": "<client-id>",
            "clientSecret": "<client-secret>",
            "callbackUrl": "https://gateway.example.com/clawidentity/oauth/callback",
            "scope": "openid profile email"
          },
          "authz": {
            "agentCheck": false,
            "toolCheck": false,
            "skillReadCheck": false,
            "requireRiskApproval": false,
            "namespaceName": "default",
            "lowRiskBypass": true,
            "enableLlmRiskCheck": false,
            "approvalTtlSeconds": 300
          }
        }
      }
    }
  }
}
```

See README-cn for full configuration and advanced notes.