Generate a cryptographically random code_verifier string (recommended 43-128 characters) and derive a code_challenge by applying SHA-256 and then Base64URL-encoding the result.
Redirect the user to the authorization endpoint with response_type=code, client_id, redirect_uri, scope, state, code_challenge, and code_challenge_method=S256.
After the user authenticates, the authorization server redirects back with an authorization code; verify the state parameter matches the one you sent to prevent CSRF.
Exchange the authorization code at the token endpoint by POSTing code, redirect_uri, client_id, grant_type=authorization_code, and the original code_verifier (not the challenge).
Receive and securely store the access token and refresh token; for SPAs prefer in-memory storage; for native apps use the platform secure store.
Refresh the access token using the refresh token when it expires, and implement token rotation to detect refresh token reuse.
Known gotchas
Sending code_challenge_method=plain instead of S256 provides minimal security; always use S256 unless the client cannot perform SHA-256 hashing.
The implicit flow (response_type=token) is deprecated for SPAs per RFC 9700 — use authorization code + PKCE instead even without a backend.
Never put the code_verifier in the authorization request URL; it must only appear in the back-channel token exchange POST body.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp