Skip to main content
GET
OAuth callback (provider redirects here)
The provider redirects the browser here after the user consents. The server validates the returned state against the recurso_oauth_state cookie set by GET /auth/oauth/{provider}/start (constant-time compare), exchanges code for a token using the bound PKCE verifier, fetches the user’s profile, and requires a verified email (Google: email_verified is true; GitHub: a primary, verified email). It then finds or creates the account:
  1. An existing linked identity logs in.
  2. An existing user with the same verified email is linked to the new identity and logged in.
  3. A brand-new email creates a tenant and its owner user, the same as POST /auth/register.
On success the server sets the recurso_session cookie — identical to a password login — and 302s to the dashboard root. On any failure other than a state mismatch it 302s to {DASHBOARD_URL}/login?error=oauth; the redirect target is always the configured dashboard URL, never a caller-supplied one. The state cookie is cleared whichever way the attempt ends, so each start is single-use. You do not call this endpoint yourself — register it as the provider’s redirect URI (https://api.recurso.dev/auth/oauth/{provider}/callback).

Path Parameters

Query Parameters

Example Request

Example Response

There is no response body. A successful login answers 302 Found with the session cookie:
A failed exchange, an unverified email, an expired (older than 10 minutes) or missing state cookie, or a login error all answer 302 Found with Location: https://app.recurso.dev/login?error=oauth.

Errors

Errors use the standard envelope — see Errors.

Authorizations

Authorization
string
header
required

Path Parameters

provider
enum<string>
required
Available options:
google,
github

Query Parameters

code
string
state
string

Response

Redirect to the dashboard on success, or to the login error page on failure. Sets the session cookie on success.