OAuthMCPBridge.Artifact (oauth_mcp_bridge v0.1.0-dev.0)

Copy Markdown View Source

Purpose-scoped OAuth artifacts, each a macaroon (OAuthMCPBridge.Macaroon) — fully stateless, so nothing is lost across scale-to-zero restarts and there is no database or volume.

The structured payload lives in the (integrity-protected) macaroon identifier; two caveats carry policy: purpose=<p> and exp=<unix>. A holder may attenuate by appending a tighter exp= caveat (the soonest bound wins, since every caveat must hold). Any caveat the verifier doesn't recognize fails closed, so attenuation can only ever narrow authority.

  • :client — dynamic-registration client_id → %{"uris" => [...], "name" => ...}
  • :state — GitHub-leg context → client_id, redirect_uri, PKCE, client state
  • :code — our authorization code → client + PKCE + resolved login
  • :access — the MCP bearer token → %{"sub" => login}
  • :refresh — long-lived renewal credential → %{"sub" => login}; lets a client silently mint a new :access token without a GitHub round-trip (OAuth 2.1 practice: short access-token TTL + refresh token, rather than one long-lived access token). Being stateless, a refresh isn't re-checked against the whitelist/org membership — it trusts the sub the original code exchange already verified — so tightening the whitelist doesn't revoke an outstanding refresh token before its own exp.

The root key is read at runtime from :persistent_term ({:oauth_mcp_bridge, :token_secret}) — set this before starting, e.g. in your Application.start/2.

Summary

Functions

Access-token lifetime (seconds) for the expires_in field.

Mint a bearer string for purpose carrying payload.

Verify signature + purpose + expiry; return the payload map.

Functions

access_ttl()

Access-token lifetime (seconds) for the expires_in field.

mint(purpose, payload)

@spec mint(atom(), map()) :: String.t()

Mint a bearer string for purpose carrying payload.

verify(purpose, token)

@spec verify(atom(), String.t()) :: {:ok, map()} | :error

Verify signature + purpose + expiry; return the payload map.