Skip to content

workos/auth.md

Repository files navigation

auth.md

A reference implementation of agentic registration — a protocol for agents to authenticate to services on behalf of users. Three roles: an agent acting for a user, an agent provider that mints identity assertions (ID-JAGs), and a service that accepts those assertions, when available, and issues credentials. If the agent is not associated with a user identity, or the agent provider does not support ID-JAGs, the service uses an OTP-based claim flow to authenticate the agent instead.

This repo includes sample implementations for both the agent provider and agent service side of agentic registration, and includes a sample AUTH.md file, which the agent service would host, instructing agents how to authenticate with the service.

Layout

.
├── AUTH.md            ← skill manifest agents read
├── agent-services/    ← sample resource server + authorization server
├── agent-providers/   ← sample agent IdP that mints ID-JAGs
└── shared/            ← shared workspace package (ports, types)

Where to go next

  • You're an agent or want an auth.md templateAUTH.md — procedural recipe (discover → register → claim → use → handle revoke).
  • You're implementing a serviceagent-services/README.md — full implementation guide, sequence diagrams, error tables.
  • You're implementing an IdPagent-providers/README.md — minting ID-JAGs, publishing JWKS, sending revocation events.

Quickstart

pnpm install
pnpm dev

Service at http://localhost:8000, provider at http://localhost:4000. The service home page walks the three registration flows interactively. Use pnpm dev:service or pnpm dev:provider to run one side at a time.

System Flows

Three registration flows share the /agent/auth endpoint. Pick the one that matches what the agent has on hand.

Discovery

Hosted at /.well-known/oauth-authorization-server:

{
  "resource": "https://api.service.com/",
  "authorization_servers": ["https://auth.service.com/"],
  "scopes_supported": ["api.read", "api.write"],
  "bearer_methods_supported": ["header"],
  "agent_auth": {
    "skill": "https://service.com/auth.md",
    "register_uri": "https://auth.service.com/agent/auth",
    "claim_uri": "https://auth.service.com/agent/auth/claim",
    "revocation_uri": "https://auth.service.com/agent/auth/revoke",
    "identity_types_supported": ["anonymous", "identity_assertion"],
    "anonymous": {
      "credential_types_supported": ["api_key"]
    },
    "identity_assertion": {
      "assertion_types_supported": [
        "urn:ietf:params:oauth:token-type:id-jag",
        "verified_email"
      ],
      "credential_types_supported": ["access_token", "api_key"]
    },
    "events_supported": [
      "https://schemas.workos.com/events/agent/auth/identity/assertion/revoked"
    ]
  }
}

Identity Assertion (ID-JAG)

sequenceDiagram
    actor User
    participant Agent
    participant Provider as Agent Provider
    participant Service

    Agent->>Service: GET /api/resource
    Service-->>Agent: 401 Unauthorized<br/>WWW-Authenticate: Bearer resource_metadata="..."

    Agent->>Service: GET /.well-known/oauth-protected-resource
    Service-->>Agent: 200 OK (PRM with authorization_servers)
    Agent->>Service: GET /.well-known/oauth-authorization-server
    Service-->>Agent: 200 OK (AS metadata with agent_auth block)

    Agent->>User: Consent to assert identity to audience?
    User-->>Agent: Consent granted

    Agent->>Provider: Request audience-specific ID-JAG
    Provider-->>Agent: 200 OK (ID-JAG)

    Agent->>Service: POST /agent/auth<br/>{ type: identity_assertion, assertion: ID-JAG }
    Service->>Provider: GET /.well-known/jwks.json
    Provider-->>Service: 200 OK (JSON Web Key Set)
    Service->>Service: Verify signature + claims, match user
    Service-->>Agent: 200 OK (credentials)
Loading

Verified-Email Identity Assertion

sequenceDiagram
    actor User
    participant Agent
    participant Service

    Agent->>Service: POST /agent/auth<br/>{ type: identity_assertion, assertion_type: verified_email, assertion: email }
    Service->>User: Send claim-view email (one-time URL)
    Service-->>Agent: 200 OK (claim_token, no credential)
    User->>Service: GET /agent/auth/claim/view?token=...
    Service-->>User: 6-digit OTP page
    User-->>Agent: Reads OTP back
    Agent->>Service: POST /agent/auth/claim/complete<br/>{ claim_token, otp }
    Service-->>Agent: 200 OK (credential)
Loading

Anonymous Registration with OTP Claim

sequenceDiagram
    actor User
    participant Agent
    participant Service

    Agent->>Service: POST /agent/auth<br/>{ type: anonymous, requested_credential_type: api_key }
    Service->>Service: Create agent principal, scoped API key, claim record
    Service-->>Agent: 200 OK (api_key, claim_token)

    Note over Agent: Agent operates with pre-claim scopes

    User-->>Agent: Wants to take ownership
    Agent->>Service: POST /agent/auth/claim<br/>{ claim_token, email }
    Service->>User: Send claim-view email (one-time URL)
    User->>Service: GET /agent/auth/claim/view?token=...
    Service-->>User: 6-digit OTP page
    User-->>Agent: Reads OTP back
    Agent->>Service: POST /agent/auth/claim/complete<br/>{ claim_token, otp }
    Service->>Service: Swap API key perms (pre-claim → post-claim)
    Service-->>Agent: 200 OK { status: claimed }
Loading

About

An open protocol that lets agents register for services on behalf of users — discoverable through a Markdown file at your domain.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors