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:

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:
  1. Third-party site calls POST /clauth/v1/identity/challenge:

   {

"skillId": "my-agent",

"provider": "github",

"accountId": "octocat",

"method": "signed-challenge"

}

  1. Clauth generates a random 32-byte challenge token and returns:

   {

"challengeId": "uuid",

"challenge": "base64url-token",

"expiresAt": "2025-01-15T10:10:00Z"

}

  1. Agent calls POST /clauth/v1/identity/verify with the credential handle as proof:

   {

"challengeId": "uuid",

"proof": "github-main"

}

  1. 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

  1. If the provider confirms the account matches accountId, the challenge is marked verified.
  1. 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:
  1. Create challenge with method: "oauth":

   {

"skillId": "my-agent",

"provider": "github",

"accountId": "octocat",

"method": "oauth"

}

  1. 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&..."

}

  1. User opens the oauthUrl in a browser and authorizes the OAuth app.
  1. Provider redirects to GET /clauth/v1/identity/oauth/callback?state=uuid:hmac&code=xxx.
  1. 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

  1. User sees a confirmation page in the browser.
Prerequisites: Requires OAuth app credentials: Security: State parameter is HMAC-signed with the vault master key to prevent CSRF attacks.

Email Challenge

Simple code-based verification.

Flow:
  1. Create challenge with method: "email":

   {

"skillId": "my-agent",

"provider": "email",

"accountId": "user@example.com",

"method": "email"

}

  1. Clauth generates a challenge code (returned in the response).
  1. The calling application sends the code to the user's email (delivery is the caller's responsibility).
  1. User submits the code via POST /clauth/v1/identity/verify:

   {

"challengeId": "uuid",

"proof": "the-challenge-code"

}

  1. Clauth verifies exact match of code and marks as verified.
Security: The challenge code is a 32-byte random token. Challenge expires in 10 minutes.

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

ProviderSigned ChallengeOAuthVerification Endpoint

GitHubYesYesGET /user (checks login)
TwitterYesYesGET /2/users/me (checks data.username)
SlackYesNoPOST auth.test (checks user_id)
EmailNoNoCode match only

Audit Events

All identity operations are logged:

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"

}

}