# Integrating AuthCog AuthCog is a hosted identity handoff. Your app sends a visitor to central auth, they sign in with any provider you enabled, and AuthCog hands a verified profile back to your server through a single-use redirect. No passwords and no provider tokens ever reach your app - you start your own session from the profile. ## Flow 1. Generate a random, one-time `state` challenge, store it in the initiating browser's session, and send the visitor to central auth: GET https://auth.authcog.com/d:my-app.com?state=BROWSER_CHALLENGE Optional `redirect_to` returns the visitor to a specific path after sign-in: GET https://auth.authcog.com/d:my-app.com?state=BROWSER_CHALLENGE&redirect_to=/dashboard 2. The visitor signs in. AuthCog redirects the browser back to your site with a short-lived callback hash: GET https://my-app.com/authcog?callback=SECURE_HASH&state=BROWSER_CHALLENGE 3. Verify and consume the matching browser challenge before exchanging the hash server-side for the released identity. Reject a callback whose challenge is missing, mismatched, or already used. GET https://auth.authcog.com/d:my-app.com?user=SECURE_HASH 200 OK { "email": "user@example.com", "name": "Ada Lovelace", "avatar": "https://...", "provider": "google", "realm": null, "issuer": "auth" } Create your own session from this payload. The long prefixes `/domain:` and `/port:` are accepted aliases for `/d:` and `/p:`. ## Realm trust Configure the AuthCog realm your app trusts on your server. Use that same realm host for starting login and exchanging tokens: `auth.authcog.com` for central auth, or `your-realm.authcog.com` for your tenant's providers. Never choose the exchange host from callback parameters or an unverified token payload. An exchange endpoint accepts tokens issued by its own realm or AuthCog's system realm (`auth`). It rejects tokens from other tenants, even when the destination domain and browser challenge match. The POST alternative, `/api/tokens/verify`, applies the same rule using its request host and requires `token` and `domain` parameters. `issuer` identifies the realm that authenticated the login. `realm` identifies the destination membership whose access rules apply. A central login to a tenant site therefore has `issuer: "auth"` and that tenant's subdomain in `realm`. ## What you get back, and where The exchange in step 3 returns JSON: | field | meaning | |----------|-----------------------------------------------------------------| | email | verified email - the primary identifier | | name | display name from the provider | | avatar | avatar URL (dicebear initials when the provider has no picture) | | provider | informational label for how they signed in - see below | | realm | realm subdomain the login belongs to, `null` for central auth | | issuer | authenticating realm subdomain; `auth` for AuthCog itself | **Do not validate `provider`, and never gate sign-in on it.** A successful exchange through your configured realm host proves the issuer is trusted and the token is valid for your domain. `provider` is metadata for your UI ("Signed in with Google"). It is an open set of lowercase slugs and new ones appear as providers are added. Today: `google`, `github`, `microsoft`, `email` (magic link or password), `generic_oidc`, `generic_oauth2`, `saml`, `cloudflare_access`, `google_iap`, `generic_jwt`. Treat anything unrecognized as "signed in". ## Callback hash rules * Single-use - consumed on the first exchange. * Expires 5 minutes after issue. * Bound to the exact domain it was issued for. * Accepted only by an exchange endpoint that trusts its recorded issuer. * Exchange it from your server, never from the browser. An exchange that fails any of those rules returns one response: 400 { "error": "unknown, expired, or already-used callback" } ## Local development For local/dev hosts (`localhost`, `*.lvh.me`, raw IPs) pass the port: GET https://auth.authcog.com/d:my-app.lvh.me/p:8000 A port above 999 is released back over `http`; everything else uses `https`.