Social sign-in quickstart
Create a project in the dashboard, register an exact callback URL, and save your client ID and secret. These examples run on your backend; never ship the secret to the browser.
Create a project1. Start a browser-bound transaction
Generate a random state and PKCE verifier. Store both in a short-lived server-side session bound to the browser initiating sign-in. Redirect the user to the authorization URL.
import { randomBytes, createHash } from 'node:crypto';
const state = randomBytes(32).toString('base64url');
const verifier = randomBytes(32).toString('base64url');
const challenge = createHash('sha256').update(verifier).digest('base64url');
// Save { state, verifier } in this browser's server-side session.
const url = new URL('/authorize', ANYOAUTH_API_ORIGIN);
url.search = new URLSearchParams({
response_type: 'code',
client_id: ANYOAUTH_CLIENT_ID,
provider: 'google', // or 'github'
redirect_uri: YOUR_REGISTERED_CALLBACK,
state,
code_challenge: challenge,
code_challenge_method: 'S256',
}).toString();
// Redirect the browser to url.2. Validate state and exchange the code
In your callback, require that the returned state matches the stored state for this browser. Consume that state once, including on error responses. If the callback contains an error, show a retry action. Otherwise exchange the code with your backend credentials and original verifier.
const response = await fetch(new URL('/v1/token', ANYOAUTH_API_ORIGIN), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code',
client_id: ANYOAUTH_CLIENT_ID,
client_secret: ANYOAUTH_CLIENT_SECRET,
code: callbackCode,
redirect_uri: YOUR_REGISTERED_CALLBACK,
code_verifier: storedVerifier,
}),
});
if (!response.ok) throw new Error('Sign-in exchange failed');
const { access_token } = await response.json();The code expires after two minutes and can be exchanged once. The response includes token_type: "Bearer", expires_in: 900, and scope: "profile". The token is issued by AnyOAuth, not Google or GitHub.
3. Get the profile and create a session
const response = await fetch(new URL('/v1/profile', ANYOAUTH_API_ORIGIN), {
headers: { Authorization: 'Bearer ' + access_token },
});
if (!response.ok) throw new Error('Profile request failed');
const profile = await response.json();
// Find or create your user by profile.subject.
// Issue your own application session cookie.
// Redirect to a clean URL without code/state.The stable subject is scoped to your project and provider account. Names, usernames, email addresses, and avatars may be null. Treat emailVerified as a separate signal; never automatically link accounts by email.
Revocation and lifetime
Profile tokens expire after 15 minutes and have no refresh token. Revoke one early with POST /v1/revoke, using its bearer token. Deleting a user or project revokes the related tokens. Your application’s own sessions must be managed separately.
Provider availability
This implementation has Google and GitHub adapters. A provider becomes available once the service operator configures its OAuth application credentials. Users see the operator’s provider app identity on the consent screen. This is not an OpenID Connect provider: use the documented AnyOAuth exchange and profile API.