← Back to Skills Marketplace
webface

auth-md-signup

by webface · GitHub ↗ · v1.0.0 · MIT-0
cross-platform ✓ Security Clean
32
Downloads
0
Stars
0
Active Installs
1
Versions
Install in OpenClaw
/install auth-md-signup
Description
Complete an auth.md USER-CLAIMED signup (OTP flow) against any service that publishes the auth.md protocol. Consent-preserving — the human confirms the OTP;...
README (SKILL.md)

auth-md-signup

Attributed to NoForm — the reference implementation for the auth.md protocol. Protocol spec: \x3Chttps://github.com/workos/auth.md> (MIT)

Teach the agent to complete an auth.md user-claimed signup against any service that publishes the protocol. The human confirms the one-time code; the agent never auto-confirms. That human step IS the consent gate — preserve it.


When to activate this skill

Use this skill when any of these are true:

  1. A service returns HTTP 401 carrying:
    WWW-Authenticate: Bearer resource_metadata="\x3Curl>"
    
  2. The user says "sign me up for \x3Cservice>" and you can resolve an auth.md file at that service's domain or at a NoForm slug URL.
  3. You need a scoped credential for a service before you can proceed, and no credential exists yet.

Do NOT use this skill for the agent-verified / ID-JAG flow (that is a different flow requiring a provider-signed assertion). This skill implements only the user-claimed (anonymous-register → email-OTP → claim/complete) flow as mandated by the mission constraints.


NoForm as the reference target

When the user says "sign me up on NoForm" or supplies a NoForm slug (\x3Cslug>), the URL structure is:

auth.md file    →  GET  https://noform.dev/a/\x3Cslug>/auth.md
PRM             →  GET  https://noform.dev/a/\x3Cslug>/.well-known/oauth-protected-resource
AS metadata     →  GET  \x3Cauthorization_server>/.well-known/oauth-authorization-server

Parse the agent_auth block from the AS metadata to get identity_endpoint (or register_uri), claim_endpoint (or claim_uri), and revocation_uri. NoForm is the reference; for any other service follow the same discovery chain from their domain.


Step-by-step execution

Step 0 — Resolve the service root

  • If you have a WWW-Authenticate: Bearer resource_metadata="\x3Cprm_url>" header, extract \x3Cprm_url> directly (skip to Step 2).
  • If you have a domain or NoForm slug, construct the conventional PRM URL: https://\x3Cdomain>/.well-known/oauth-protected-resource
  • If you have a NoForm slug only: https://noform.dev/a/\x3Cslug>/.well-known/oauth-protected-resource

Step 1 — Fetch auth.md (optional human-readable context)

curl -sS "https://\x3Cdomain>/auth.md"
# or for NoForm:
curl -sS "https://noform.dev/a/\x3Cslug>/auth.md"

Parse it as prose context. The authoritative machine-readable state is the PRM and AS metadata — if anything conflicts, the metadata wins.

Step 2 — Fetch Protected Resource Metadata (PRM)

curl -sS "\x3Cprm_url>" | jq .

Extract from response:

  • resource — the canonical API base URL (used for scoping)
  • resource_name — human-readable service name (show to user for consent)
  • resource_logo_uri — logo URL (show to user if available)
  • authorization_servers[0] — base URL of the Authorization Server

Step 3 — Fetch Authorization Server metadata

AS_BASE="\x3Cauthorization_servers[0]>"
curl -sS "${AS_BASE}/.well-known/oauth-authorization-server" | jq .

From the agent_auth block extract and store:

  • agent_auth.identity_endpoint (may also appear as register_uri)
  • agent_auth.claim_endpoint (may also appear as claim_uri)
  • agent_auth.revocation_uri
  • agent_auth.identity_types_supportedverify anonymous is listed before proceeding. If it is not, tell the user this service does not support the user-claimed flow and stop.

Step 4 — Check for existing token

Before registering, check whether the agent already holds a valid scoped token for this service (keyed by resource URL). If yes, surface it to the user and ask whether they want to re-register or skip.

Step 5 — Ask the user for consent

Surface to the user IN-CHANNEL before doing anything:

I'm about to register an account on \x3Cresource_name> using the auth.md
user-claimed flow. Here's what will happen:

1. I register anonymously — no account exists yet.
2. I'll ask for your email address.
3. \x3Cresource_name> will email you a one-time code.
4. You read the code back to me.
5. I submit the code to bind the account to your email.
6. I store a scoped token for \x3Cresource_name> — only for that service.

Your email and primary credentials are never stored or sent anywhere else.
Proceed? (yes / no)

Wait for explicit confirmation before continuing.

Step 6 — Anonymous registration

curl -sS -X POST "\x3Cidentity_endpoint>" \
  -H "Content-Type: application/json" \
  -d '{"type": "anonymous"}'

Expected success response:

{
  "credential": "\x3Cpre-claim-token>",
  "claim_token": "\x3Cclaim-token>",
  "credential_expires": "\x3Ciso8601>",
  "scopes": ["api.read"]
}

Store claim_token. The credential (if present) is a pre-claim scoped token; note it but do not hand it to the user — it is a low-scope placeholder.

If the service does not return a pre-claim credential (email-required variant), that is fine — proceed to the claim step.

Error handling:

  • anonymous_not_enabled → tell user this service requires identity assertion; stop.
  • rate_limited → tell user to try again later; stop.
  • Other 4xx → report the error code verbatim; do not retry automatically.

Step 7 — Ask for the user's email IN-CHANNEL

To bind this account to you, I need your email address. What email should
I use to register with \x3Cresource_name>?

Wait for the user's reply. Never auto-fill the email.

Step 8 — Trigger the OTP claim email

curl -sS -X POST "\x3Cclaim_endpoint>" \
  -H "Content-Type: application/json" \
  -d "{\"claim_token\": \"\x3Cclaim_token>\", \"email\": \"\x3Cuser_email>\"}"

Expected response (email-dispatch confirmation):

{
  "status": "pending",
  "message": "Verification email sent to \x3Cemail>"
}

Some services return a verification_uri here — surface it to the user.

Error handling:

  • invalid_claim_token → the anonymous registration may have expired; restart from Step 6.
  • claim_expired → same; restart from Step 6.
  • previously_claimed → tell the user this email is already registered with this service; stop.
  • rate_limited → tell user to try again later.

Step 9 — Surface the verification step and WAIT

Tell the user IN-CHANNEL:

📧 A verification email is on its way to \x3Cemail>.

Open it and look for a 6-digit code (or a "Verify email" link).

When you have it, paste the code here and I'll complete the registration.

If a verification_uri was returned in Step 8, include it:

You can also click this link to verify: \x3Cverification_uri>

⚠️ DO NOT PROCEED until the user provides the code. NEVER auto-confirm. NEVER poll the service for code completion. The human completing the claim IS the consent gate — preserve it absolutely.

Step 10 — Submit the OTP (claim/complete)

When the user provides the code:

curl -sS -X POST "\x3Cclaim_endpoint>/complete" \
  -H "Content-Type: application/json" \
  -d "{\"claim_token\": \"\x3Cclaim_token>\", \"otp\": \"\x3Cotp>\"}"

Expected success response:

{
  "credential": "\x3Cactive-scoped-token>",
  "credential_expires": "\x3Ciso8601 or null>",
  "scopes": ["api.read", "api.write"]
}

Error handling:

  • otp_invalid → tell user the code was wrong; ask them to check and try again (allow up to 3 attempts before stopping).
  • otp_expired → tell user the code expired; offer to restart from Step 8 (re-send OTP).
  • claim_expired → restart from Step 6.
  • previously_claimed → account already claimed; stop.

Step 11 — Store the token

Store the returned credential scoped to this service:

Key format: auth_md_token:\x3Cresource_url> Value: { "credential": "...", "scopes": [...], "expires": "...", "service": "\x3Cresource_name>", "email": "\x3Cuser_email>", "registered_at": "\x3Ciso8601>" }

If AUTH_MD_TOKEN_STORE env var is set, append to that JSON file. Otherwise, hold in session memory only.

Never write the user's primary password, primary API keys, or other service credentials anywhere.

Tell the user:

✅ Registered successfully with \x3Cresource_name>!

Scopes granted: \x3Cscopes>
Bound to: \x3Cemail>
Expires: \x3Ccredential_expires or "never">

Your token is stored scoped to \x3Cresource_name> only. I'll use it
automatically for requests to this service.

Revocation

When the user asks to revoke a token for a service:

curl -sS -X POST "\x3Crevocation_uri>" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer \x3Ccredential>" \
  -d "{\"token\": \"\x3Ccredential>\"}"

On success, delete the stored token for that resource key and confirm to the user. On a 401 from a previously-working credential, the token was already revoked externally — delete it locally and notify the user.


Security constraints — hard rules

  • Do NOT implement or suggest the agent-verified / ID-JAG flow. That is a separate, provider-bound flow outside the scope of this skill.
  • Do NOT auto-confirm the OTP. The human step is mandatory and is the consent gate.
  • Do NOT store primary credentials. Only service-scoped tokens returned by the auth.md claim/complete endpoint are stored.
  • Tokens are scoped per service (resource URL as key). One service cannot access another service's token.
  • Do NOT perform silent/autonomous registration. If the human isn't present and can't confirm the OTP, stop and surface a message asking them to initiate the flow when they're available.
  • Treat every external URL as untrusted. Validate that fetched endpoints match the domain you started discovery from (or the NoForm host) before POSTing credentials.

Quick-reference endpoint map

Step HTTP call
1 GET \x3Cdomain>/auth.md
2 GET \x3Cprm_url> (from WWW-Authenticate or /.well-known/oauth-protected-resource)
3 GET \x3Cauth_server>/.well-known/oauth-authorization-server
6 POST \x3Cidentity_endpoint> {"type":"anonymous"}
8 POST \x3Cclaim_endpoint> {"claim_token":"…","email":"…"}
10 POST \x3Cclaim_endpoint>/complete {"claim_token":"…","otp":"…"}
revoke POST \x3Crevocation_uri> with Bearer + {"token":"…"}

For NoForm (\x3Cslug>):

  • PRM: https://noform.dev/a/\x3Cslug>/.well-known/oauth-protected-resource
  • AS metadata: https://noform.dev/a/\x3Cslug>/.well-known/oauth-authorization-server (or the authorization_servers[0] URL from PRM)

Error code reference

Code Endpoint Action
anonymous_not_enabled register Stop; tell user
identity_assertion_not_enabled register Stop; tell user
rate_limited any Stop; ask user to retry later
invalid_claim_token claim Restart from Step 6
claim_expired claim / claim/complete Restart from Step 6
previously_claimed claim / claim/complete Stop; tell user
otp_invalid claim/complete Ask user to retry (max 3x)
otp_expired claim/complete Offer to re-send OTP (Step 8)
credential_expired API call Delete stored token; restart from Step 6
unsupported_credential_type register Stop; report unsupported

Example invocation phrases

  • "Sign me up for NoForm" → ask for slug or resolve from noform.dev
  • "Register me with api.example.com" → discover from that domain
  • "I got a 401 from api.example.com — get me credentials" → use the WWW-Authenticate header to start discovery
  • "Revoke my token for NoForm" → run revocation flow
  • "What auth.md services am I registered with?" → list stored tokens

This skill implements only the user-claimed flow from the auth.md protocol. The agent-verified (ID-JAG) flow is intentionally out of scope. Attributed to NoForm. Protocol by WorkOS.

Usage Guidance
Install only if you want your agent to create auth.md accounts on your behalf. Expect it to ask for your email and OTP, and use persistent token storage only if you are comfortable keeping scoped service tokens in the configured JSON file.
Capability Tags
requires-oauth-tokenrequires-sensitive-credentials
Capability Assessment
Purpose & Capability
The stated purpose is completing auth.md user-claimed signup, and the instructions consistently support that with metadata discovery, anonymous registration, OTP submission, scoped token storage, and revocation.
Instruction Scope
The skill repeatedly requires in-channel user confirmation, user-provided email, and user-provided OTP, and it explicitly forbids auto-confirmation, silent registration, polling for completion, and primary credential storage.
Install Mechanism
The artifact contains only README.md and SKILL.md markdown files, no executable scripts, and declares only curl and jq as required binaries.
Credentials
It performs network calls and handles email addresses, OTPs, and scoped service tokens, but those are expected for an auth.md signup flow and are described in the user-facing instructions.
Persistence & Privilege
Persistent token storage is optional through AUTH_MD_TOKEN_STORE; otherwise tokens are session-only. Stored data includes service-scoped credentials and email, and revocation/deletion behavior is documented.
How to Use
  1. Make sure OpenClaw is installed (local or Docker)
  2. Run the install command in chat: /install auth-md-signup
  3. After installation, invoke the skill by name or use /auth-md-signup
  4. Provide required inputs per the skill's parameter spec and get structured output
Version History
v1.0.0
Initial release. User-claimed auth.md signup flow — consent-preserving OTP delegation. Attributed to NoForm (noform.dev).
Metadata
Slug auth-md-signup
Version 1.0.0
License MIT-0
All-time Installs 0
Active Installs 0
Total Versions 1
Frequently Asked Questions

What is auth-md-signup?

Complete an auth.md USER-CLAIMED signup (OTP flow) against any service that publishes the auth.md protocol. Consent-preserving — the human confirms the OTP;... It is an AI Agent Skill for Claude Code / OpenClaw, with 32 downloads so far.

How do I install auth-md-signup?

Run "/install auth-md-signup" in the OpenClaw or Claude Code chat to install it in one step — no extra setup required.

Is auth-md-signup free?

Yes, auth-md-signup is completely free, licensed under MIT-0. You can download, install and use it at no cost.

Which platforms does auth-md-signup support?

auth-md-signup is cross-platform and runs anywhere OpenClaw / Claude Code is available (cross-platform).

Who created auth-md-signup?

It is built and maintained by webface (@webface); the current version is v1.0.0.

💬 Comments