Tagos
Docs

Sign in with Tagos (OIDC)

Standard OpenID Connect Authorization Code flow with PKCE (S256). Confidential clients only for now — register in the Developer Console.

Users authenticate with their unified Tagos Account— the same identity used for Tagos Mail and the rest of the ecosystem.

Endpoints

Issuer
https://oauth.tagos.email
Authorize
https://oauth.tagos.email/oauth2/authorize
Token
https://oauth.tagos.email/oauth2/token
UserInfo
https://oauth.tagos.email/oauth2/userinfo

Prefer discovery over hardcoding paths — the document is the contract.

What is secret

  • client_id and redirect URIs are public.
  • client_secret is shown once at create/rotate — store it server-side only.
  • Never put the secret in a browser SPA or mobile binary.

1. Register an app

  1. Open Console → OAuth apps.
  2. Set a display name (shown on Tagos sign-in as "Continue to …").
  3. Add exact redirect URIs (HTTPS in production; http://127.0.0.1 ok for local).
  4. Copy the client secret immediately.

2. Send the user to authorize

Required: response_type=code, client_id, redirect_uri, scope (must include openid; optional profile email), code_challenge + code_challenge_method=S256. Recommended: state, nonce.

# Generate PKCE (example)
VERIFIER=$(openssl rand -base64 32 | tr -d '=+/' | cut -c1-43)
CHALLENGE=$(printf '%s' "$VERIFIER" | openssl dgst -sha256 -binary | openssl base64 -A | tr '+/' '-_' | tr -d '=')

# Redirect the browser to:
https://oauth.tagos.email/oauth2/authorize?\
  response_type=code\
  &client_id=YOUR_CLIENT_ID\
  &redirect_uri=https%3A%2F%2Fyour.app%2Fcallback\
  &scope=openid%20email%20profile\
  &state=RANDOM\
  &code_challenge=$CHALLENGE\
  &code_challenge_method=S256

3. Exchange the code

From your backend only. Auth methods: client_secret_post or client_secret_basic.

curl -sS -X POST 'https://oauth.tagos.email/oauth2/token' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code' \
  -d 'code=CODE_FROM_CALLBACK' \
  -d 'redirect_uri=https://your.app/callback' \
  -d 'client_id=YOUR_CLIENT_ID' \
  -d 'client_secret=YOUR_CLIENT_SECRET' \
  -d 'code_verifier=VERIFIER_FROM_STEP_2'

Example successful response (shape; values truncated):

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "r_...",
  "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}

expires_in is typically 900 seconds (15 minutes) for access tokens — always read the field, do not hardcode. id_token is RS256; sub is the Tagos account UUID — use that as your stable user id.

4. Call UserInfo (optional)

curl -sS 'https://oauth.tagos.email/oauth2/userinfo' \
  -H 'Authorization: Bearer ACCESS_TOKEN'

Library tip

Any OIDC client that supports discovery + Authorization Code + PKCE S256 works (e.g. Auth.js / NextAuth with an OIDC provider pointing at the issuer above). Do not invent custom crypto — use the library's PKCE helpers.

Revocation

Users can revoke your app under Tagos Account → Connected apps. After revoke, refresh/introspect fail; your own session cookie is independent until you check tokens again. Token revoke endpoint: https://oauth.tagos.email/oauth2/revoke.