How OAuth Verify Works
Understand the protocol and the trust boundary before copying snippets.
On this page
Lifecycle
BROWSER YOUR BACKEND KEYRA USER
│ │ │ │
│ Start (publishable cp_*) │ │ │
├────────────────────────────────────────────────►│ │
│ authorize_url │ │ │
│◄────────────────────────────────────────────────┤ │
│ Open popup/redirect │ │ │
│ │ │◄─── verify ────────┤
│ authorization code │ │ │
│◄────────────────────────────────────────────────┤ │
│ Token exchange (PKCE) │ │ │
├────────────────────────────────────────────────►│ │
│ access_token │ │ │
│ (= verification_token) │ │ │
│◄────────────────────────────────────────────────┤ │
│ POST token to backend │ │ │
├─────────────────────────►│ │ │
│ │ POST /verify/validate│ │
│ ├─────────────────────►│ │
│ │ valid + user │ │
│ │◄─────────────────────┤ │
│ │ Create YOUR session │ │
│ Set app session cookie │ │ │
│◄─────────────────────────┤ │ │- Browser (or your server) starts authorization with PKCE +
state. - KEYRA returns an
authorize_urlto the hosted verification UI. - User completes verification on their device.
- Browser receives an authorization
code(popuppostMessageor redirect query). - Browser exchanges code +
code_verifieratPOST /oauth/token. - Browser sends
access_tokento your backend. - Backend calls
POST /verify/validate(single-use) then creates your session.
Two start endpoints
KEYRA exposes two public start handlers that insert into the same hosted_login_challenges table. They are not thin aliases — defaults and response shapes differ.
/oauth/authorize/init | /verify/start | |
|---|---|---|
| Used by | @keyra/web-sdk createKeyraAuth | Paste script; createKeyraServer / Java verification |
| Default scope | openid profile phone | verify |
| Response id field | auth_request_id | verification_id (+ auth_request_id) |
| Extra status field | — | status: "pending" |
Challenge lifetime defaults to ~600s (configurable via HOSTED_LOGIN_CHALLENGE_TTL_SECONDS, clamped 120–3600).
Tokens
| Name | Meaning |
|---|---|
access_token | Returned by /oauth/token. Used for userinfo Bearer and validate. |
verification_token / verificationToken | Same value as access_token — aliased by paste script and Web SDK for DX. |
Authorization code | Short-lived code from hosted UI; exchanged with PKCE verifier. |
Who does what
| Actor | Does | Must not |
|---|---|---|
| Browser | Start with publishable id; PKCE; popup/redirect; token exchange; POST token to your API | Hold secret keys; treat browser success as final login |
| Your backend | /verify/validate; map user; create session | Skip validate |
| KEYRA | Hosted verify UI; issue code/token; consume on validate | Create your app session cookie |
State & PKCE
state is required by the start APIs. Web SDK and paste script generate it and verify it on callback (CSRF protection). PKCE S256 is required — see PKCE.
