Identity Broker
The identity broker enables private identity verification without public posting. It supports three proof methods and integrates with the audit log, alert router, and session engine.
Why?
OpenClaw verification often depends on public posting (e.g., tweeting a verification code). This is:
- Privacy-invasive: Account ownership becomes public knowledge
- Friction-heavy: Requires posting and then deleting content
- Insecure: Verification codes visible to anyone watching the feed
Clauth provides private alternatives with lower friction and stronger assurance.
Proof Methods
Signed Challenge
The primary method for agent-driven flows. Zero user friction.
Flow:- Third-party site calls
POST /clauth/v1/identity/challenge:
{
"skillId": "my-agent",
"provider": "github",
"accountId": "octocat",
"method": "signed-challenge"
}
- Clauth generates a random 32-byte challenge token and returns:
{
"challengeId": "uuid",
"challenge": "base64url-token",
"expiresAt": "2025-01-15T10:10:00Z"
}
- Agent calls
POST /clauth/v1/identity/verifywith the credential handle as proof:
{
"challengeId": "uuid",
"proof": "github-main"
}
- Clauth uses the stored credential to call the provider's identity endpoint:
- GitHub: GET https://api.github.com/user — checks login field
- Twitter: GET https://api.twitter.com/2/users/me — checks data.username
- Slack: POST https://slack.com/api/auth.test — checks user_id
- If the provider confirms the account matches
accountId, the challenge is markedverified.
- Third-party polls
GET /clauth/v1/identity/challenge/:id/status:
{
"status": "verified",
"verifiedAt": "2025-01-15T10:05:00Z"
}
Security: The credential never leaves the daemon. Ownership is proved by demonstrating the ability to authenticate against the provider API.
OAuth Flow
Standard OAuth2 authorization flow with identity verification.
Flow:- Create challenge with
method: "oauth":
{
"skillId": "my-agent",
"provider": "github",
"accountId": "octocat",
"method": "oauth"
}
- Response includes an
oauthUrl:
{
"challengeId": "uuid",
"challenge": "base64url-token",
"expiresAt": "2025-01-15T10:10:00Z",
"oauthUrl": "https://github.com/login/oauth/authorize?client_id=...&state=uuid:hmac&..."
}
- User opens the
oauthUrlin a browser and authorizes the OAuth app.
- Provider redirects to
GET /clauth/v1/identity/oauth/callback?state=uuid:hmac&code=xxx.
- Clauth:
- Validates the HMAC-signed state parameter
- Exchanges the authorization code for an access token
- Calls the provider's identity endpoint with the new token
- Verifies the account matches accountId
- Marks the challenge as verified
- User sees a confirmation page in the browser.
CLAUTH_GITHUB_CLIENT_ID/CLAUTH_GITHUB_CLIENT_SECRETCLAUTH_TWITTER_CLIENT_ID/CLAUTH_TWITTER_CLIENT_SECRET
Email Challenge
Simple code-based verification.
Flow:- Create challenge with
method: "email":
{
"skillId": "my-agent",
"provider": "email",
"accountId": "user@example.com",
"method": "email"
}
- Clauth generates a challenge code (returned in the response).
- The calling application sends the code to the user's email (delivery is the caller's responsibility).
- User submits the code via
POST /clauth/v1/identity/verify:
{
"challengeId": "uuid",
"proof": "the-challenge-code"
}
- Clauth verifies exact match of code and marks as
verified.
Verified Proofs
Successfully verified challenges produce identity proofs. Each proof contains:
{
"challengeId": "uuid",
"provider": "github",
"accountId": "octocat",
"method": "signed-challenge",
"verifiedAt": "2025-01-15T10:05:00Z",
"signature": "hmac-hex"
}
The signature is an HMAC-SHA256 of challengeId:provider:accountId:method using the vault master key. This prevents proof forgery even if the state file is compromised.
Listing Proofs
GET /clauth/v1/identity/proofs
GET /clauth/v1/identity/proofs?skillId=my-agent
Revoking Proofs
Admin-only:
DELETE /clauth/v1/admin/identity/proofs/:challengeId
CLI Usage
# Create a challenge
npm run cli -- identity challenge --provider github --accountId octocat
Submit proof
npm run cli -- identity verify --challengeId <id> --proof <handle-or-code>
List verified proofs
npm run cli -- identity list
npm run cli -- identity list --skill my-agent
Revoke a proof
npm run cli -- identity revoke --proofId <challengeId>
Client SDK
import { ClauthClient } from "clauth/client";
const clauth = new ClauthClient({
skillId: "my-agent",
skillToken: "issued-token"
});
// Create challenge
const challenge = await clauth.createIdentityChallenge("github", "octocat");
// Submit proof (signed-challenge method)
const result = await clauth.verifyIdentity(challenge.challengeId, "github-main");
console.log(result.status); // "verified"
// Poll status
const status = await clauth.getIdentityStatus(challenge.challengeId);
// List proofs
const proofs = await clauth.listIdentityProofs();
Supported Providers
| Provider | Signed Challenge | OAuth | Verification Endpoint |
| GitHub | Yes | Yes | GET /user (checks login) |
| Yes | Yes | GET /2/users/me (checks data.username) | |
| Slack | Yes | No | POST auth.test (checks user_id) |
| No | No | Code match only |
Audit Events
All identity operations are logged:
identity.challenge— Challenge createdidentity.verify— Verification attempted (outcome:identity_verifiedorfailed)identity.revoke— Proof revoked
Alert Integration
On successful verification, an info-level alert is dispatched:
{
"severity": "info",
"category": "identity",
"message": "Identity verified: github/octocat",
"metadata": {
"challengeId": "uuid",
"method": "signed-challenge"
}
}