ONE LOGIN. THREE EXPLICIT IDS.

IDENTITY,
THAT WORKS.

One sign-in layer for browser, CLI, and device apps. Keep continuity across your products, or give every client its own private user ID.

GOOGLEGITHUBTWITTERETHEREUMPASSKEYCODE + PKCEDEVICE FLOW

ONE LOGIN.
NO IDENTITY GUESSING.

Email is profile data, not a key. Every token names exactly which identity contract it carries.

provider_sub
pid_twitter_5a8f...

Provider-global and correlatable across Triad clients that receive it, without exposing the upstream ID.

account_sub
acc_4da6c809...

Broker-global. Correlates one Triad account across clients.

pairwise_sub
pws_9c0e7b2a...

Stable inside one app. Different client, different identifier.

ASK FOR LESS.
REVEAL LESS.

A client chooses its request. Triad shows the complete list before approval, and shares nothing beyond it.

DEFAULT REQUEST

IDENTITY ONLY

scope=openid

No raw provider ID, wallet, authenticated chain data, passkey credential, public key, email, handle, name, avatar, or provider access token.

OPTIONAL CLAIM SCOPES

email
email + email_verified
handle
preferred_username
name
name
avatar
picture
wallet
wallet
chains
chains
chain_id
chain_id
cred
cred
pubkey
pubkey
cosekey
cosekey

POINT. REDIRECT. VERIFY.

Triad derives the client from the callback origin, then binds the exact URI and S256 verifier.

GET /api/auth/oauth2/authorize01 / 03
?client_id=issued-client-id
&redirect_uri=https://example.com/oauth/callback
&scope=openid
&resource=https://resource.example/
&code_challenge=...
&code_challenge_method=S256
  1. Register a public client.The authorization server returns the exact client ID used by every later step.
  2. Exchange once.Your app exchanges the short-lived code with its PKCE verifier.
  3. Verify locally.Check ES256, issuer, audience, and expiry against the published JWKS.

AUTHORIZE
ANOTHER DEVICE.

Show a short code on the device. The user opens Triad in a browser and approves either a Triad session or scoped OAuth tokens for a registered client.

OPEN DEVICE VERIFICATION →