Skip to main content
7 min read

Authentication

How Claude.ai gets a token, what scopes mean, and what happens behind the sign-in screen.

TL;DR

Claude uses OAuth 2.1 with PKCE and RFC 8707 resource indicators. It never sees your password or API key. Access tokens are short-lived (1 hour) RS256 JWTs, audience-bound to 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. 1.

    Claude discovers our metadata

    Claude fetches /.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server. This tells Claude where to register, authorize, and exchange tokens.

  2. 2.

    Claude registers as an OAuth client

    Using RFC 7591 Dynamic Client Registration, Claude POSTs to /register. We issue a client_id (no secret — Claude is a public client using PKCE).

  3. 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 to abm.dev/sign-in and back here.

  4. 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. 5.

    Claude exchanges code for token

    Claude POSTs to /token with the authorization code and a PKCE code_verifier. We verify the challenge (SHA-256), mint a 1-hour RS256 JWT, and issue a 30-day refresh token.

  6. 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:readread

Read enrichments, campaigns, jobs, and results

Lists and fetches: enrichment jobs, campaigns, people-finder jobs, batch enrichments, writeback previews, publication status.

abm:writewrite

Create and mutate platform resources

Creates enrichments, previews and confirms campaigns, approves results, writes back to CRM, cancels jobs.

abm:linkedinwrite

Act 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 &mdash; Claude does not see your LinkedIn password or cookies.

abm:enrichwrite

Spend 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:generatewrite

Generate and publish content

AI content generation jobs and publication to destinations (Email, Webflow CMS, CRM Activity).

abm:adminadmin

Admin-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:

Access token (decoded)
{
  "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
}
  • aud is always exactly https://mcp.abm.dev (no trailing slash).
  • org_id is your ABM.dev workspace UUID — the MCP server uses this to scope every upstream API call.
  • exp - iat is 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 /revoke with 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 resource parameter — RFC 8707 audience binding is strict.

Continue