Skip to main content

OAuth Endpoints

email-connector implements a complete OAuth 2.0 authorization server with PKCE support.

Server Metadata

Discover all OAuth endpoints via RFC 8414.
GET /oauth/meta
Response
{
  "issuer": "https://email-connector.fly.dev",
  "authorization_endpoint": "https://email-connector.fly.dev/oauth/authorize",
  "token_endpoint": "https://email-connector.fly.dev/oauth/token",
  "revocation_endpoint": "https://email-connector.fly.dev/oauth/revoke",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["client_secret_post"]
}

Authorization

Start the OAuth flow. Claude opens this in a browser popup.
GET /oauth/authorize
Query Parameters
ParameterRequiredDescription
client_idYesOAuth client ID
redirect_uriYesMust be in the allowlist
response_typeYesMust be code
code_challengeYesBASE64URL(SHA256(code_verifier))
code_challenge_methodYesMust be S256
stateYesCSRF protection token
Allowed Redirect URIs
  • https://claude.ai/api/mcp/auth_callback
  • https://claude.com/api/mcp/auth_callback
  • http://localhost:6274/oauth/callback
  • http://localhost:6274/oauth/callback/debug
Response Renders the email setup form (HTML). Error Responses
StatusCause
400Invalid response_type, missing PKCE, invalid redirect_uri, or missing state
401Invalid client_id

Connect

Submit email credentials from the setup form. Not called directly by Claude.
POST /oauth/connect
Content-Type: application/x-www-form-urlencoded
Body Parameters
ParameterRequiredDescription
stateYesState from the authorization request
providerYesEmail provider (icloud, outlook, yahoo, fastmail, protonmail, generic)
addressYesEmail address
passwordYesApp-specific password
imap_hostNoCustom IMAP hostname (generic provider)
imap_portNoCustom IMAP port
imap_tlsNotrue or false
smtp_hostNoCustom SMTP hostname
smtp_portNoCustom SMTP port
smtp_secureNotrue or false
On Success Redirects to redirect_uri?code=<auth_code>&state=<state>. On Failure Re-renders the setup form with a user-friendly error message. Credentials are validated via a live IMAP connection before any code is issued.

Token Exchange

Exchange an authorization code for an access token.
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
Body Parameters
ParameterRequiredDescription
grant_typeYesMust be authorization_code
codeYesAuthorization code from callback
client_idYesOAuth client ID
client_secretYesOAuth client secret
code_verifierYesPKCE code verifier (original random string)
redirect_uriNoMust match the original authorization request
Success Response (200)
{
  "access_token": "64-char-hex-token",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "scope": "email:read email:write"
}
Error Responses
StatusErrorCause
400unsupported_grant_typeNot authorization_code
400invalid_requestMissing code_verifier
400invalid_grantCode expired, used, or PKCE mismatch
401invalid_clientWrong client_id or client_secret

Revocation

Revoke an access token.
POST /oauth/revoke
Content-Type: application/json
Body
{
  "token": "<access_token>"
}
Response (200)
{
  "revoked": true
}
Always returns 200 regardless of whether the token existed. This prevents token existence probing.