Authentication
How Claude.ai gets a token, what scopes mean, and what happens behind the sign-in screen.
TL;DR
https://mcp.abm.dev. Refresh tokens let Claude stay connected for up to 30 days of idle time, and you can revoke them at any time.The OAuth flow, end to end
- 1.
Claude discovers our metadata
Claude fetches
/.well-known/oauth-protected-resourceand/.well-known/oauth-authorization-server. This tells Claude where to register, authorize, and exchange tokens. - 2.
Claude registers as an OAuth client
Using RFC 7591 Dynamic Client Registration, Claude POSTs to
/register. We issue aclient_id(no secret — Claude is a public client using PKCE). - 3.
You sign in to ABM.dev
Claude redirects you to
/authorize?response_type=code&code_challenge=...&resource=https://mcp.abm.dev. We check for a Clerk session; if you aren't signed in, we send you toabm.dev/sign-inand back here. - 4.
You approve the consent screen
You see who's asking (Claude.ai), as whom (your email), at which workspace (your org), and what scopes. A CSRF token binds the approval to your session.
- 5.
Claude exchanges code for token
Claude POSTs to
/tokenwith the authorization code and a PKCEcode_verifier. We verify the challenge (SHA-256), mint a 1-hour RS256 JWT, and issue a 30-day refresh token. - 6.
Claude calls tools
Every MCP request includes
Authorization: Bearer <jwt>. We verify the signature, audience, and expiry, then route to the correct upstream API using your org context.
Scopes
Scopes are fine-grained permissions. You see every scope Claude requests on the consent screen. Default install grants everything except abm:admin.
abm:readreadRead enrichments, campaigns, jobs, and results
Lists and fetches: enrichment jobs, campaigns, people-finder jobs, batch enrichments, writeback previews, publication status.
abm:writewriteCreate and mutate platform resources
Creates enrichments, previews and confirms campaigns, approves results, writes back to CRM, cancels jobs.
abm:linkedinwriteAct on your connected LinkedIn account
Read profiles, feed, search, messaging; post, comment, react, send connection requests. Uses the LinkedIn session you already connected in ABM.dev — Claude does not see your LinkedIn password or cookies.
abm:enrichwriteSpend enrichment credits
Required for any tool that consumes credits (LinkedIn Voyager fetches, Hunter lookups, Perplexity calls, etc.). Credits are deducted from your organisation balance.
abm:generatewriteGenerate and publish content
AI content generation jobs and publication to destinations (Email, Webflow CMS, CRM Activity).
abm:adminadminAdmin-only operations (not currently requested by Claude)
Reserved for destructive or administrative operations. Claude does not request this scope by default.
Access tokens
Access tokens are RS256 JWTs. Decoded, a typical token looks like this:
{
"iss": "https://mcp.abm.dev",
"aud": "https://mcp.abm.dev",
"sub": "user_2abc...XYZ",
"email": "you@example.com",
"org_id": "00000000-0000-0000-0000-000000000001",
"scope": "abm:read abm:write abm:linkedin abm:enrich abm:generate",
"client": "abm-mcp-8f3a...",
"exp": 1761100000,
"iat": 1761096400
}audis always exactlyhttps://mcp.abm.dev(no trailing slash).org_idis your ABM.dev workspace UUID — the MCP server uses this to scope every upstream API call.exp - iatis 3600 seconds.- Signed with a 2048-bit RSA key. The public half is published at
/.well-known/jwks.json.
Refresh tokens
When the 1-hour access token expires, Claude silently exchanges its refresh token for a new one. Refresh tokens are opaque random strings (not JWTs), stored server-side, and valid for 30 days of idle time. Using a refresh token does not extend its own expiry — after 30 days you'll need to re-authorise, which takes one click because your Clerk session is still active.
Revocation
Three ways to cut Claude off:
- Remove the connector in Claude.ai — Claude calls
POST /revokewith the refresh token. The token is invalidated immediately. - Revoke on ABM.dev Settings → Connected apps — invalidates all refresh tokens for your user across every Claude session. Any active access tokens still work until they expire (<= 1 hour).
- Sign out of Clerk on abm.dev — does not revoke existing tokens but prevents Claude from completing a refresh-interactive re-authorisation.
What we never do
- We never pass Claude's token upstream to
api.abm.dev. The MCP service holds its own service credentials. - We never expose your LinkedIn cookies, Clerk session, or HubSpot tokens to Claude.
- We never skip PKCE — S256 is mandatory on every authorization request.
- We never accept a mismatched
resourceparameter — RFC 8707 audience binding is strict.