How sign-in works

The authorization code flow with PKCE as the SDK runs it, step by step, with every party and every artefact named and what is checked where.

Signing in with UNET is the OpenID Connect authorization code flow with PKCE. The SDK runs all of it for you; this page explains what happens so you can debug it, and so you know what is safe to trust.

The parties

PartyWhat it isWhat it does
Your appThe page or script that uses the SDKStarts the sign-in, finishes it on the return page, keeps the session
The SDK@unet/id-web, running in your appMakes the requests, keeps the secrets of the flow, checks what comes back
UNET IDThe OpenID provider on the UNET API (https://api.unet.ovh/oidc by default)Describes itself (discovery), hands out codes and tokens, answers for the profile
The sign-in pageA page on unet.socialSigns the person in (password, authenticator code, security key or passkey) and asks them to allow your app
The person's browserWhere all of it is seenCarries the person between your app and unet.social

Your app never sees a password, a key or an authenticator code. It only receives a one-time code, and trades it for tokens.

The sequence

StepWhoWhat happens
1SDKReads the provider's discovery document and checks it (see below). It is cached for an hour.
2SDKCreates a random state and a random PKCE verifier, computes the challenge, and saves state, verifier and your returnTo as the pending sign-in.
3BrowserIs redirected to the authorization endpoint with your App ID, return URL, scopes, state and challenge.
4Sign-in pageSigns the person in. If they are already signed in to UNET in this browser, the page skips the sign-in form and shows who they are signed in as.
5Sign-in pageShows what your app asks for. The person allows or denies. (Skipped for UNET's own apps.)
6BrowserIs redirected back to your return URL with a one-time code, your state, and the issuer in iss.
7SDKChecks the pending sign-in against what came back (state, age, iss), then sends code and verifier to the token endpoint.
8UNET IDChecks that the verifier matches the challenge from step 3 and returns an access token, usually a refresh token, and an ID token.
9SDKSaves the tokens, asks the userinfo endpoint for the profile with the access token, and resolves handleRedirectCallback() with the user.

In code, steps 1 to 3 are signIn() and steps 7 to 9 are handleRedirectCallback(). Steps 4 to 6 happen on unet.social. See the quickstart for the code and the sign-in guide for the options.

What each piece is

ArtefactWhat it isWhere it livesLifetime
stateA random value that ties the answer to your requestPending sign-in, in the SDK's storageUntil the callback, at most 15 minutes
verifierA random secret (32 bytes) that only the SDK knowsPending sign-inSame
challengeThe SHA-256 of the verifier, sent in step 3In the redirect address onlyOne sign-in
codeA one-time proof that the person allowed your appThe return URLUsed once; the server keeps it for 10 minutes at most
Access tokenWhat authorizes calls on the person's behalfThe SDK's storageOne hour
Refresh tokenGets a new access token without asking the person againThe SDK's storageSee Tokens
ID tokenA signed statement of who signed in, for your serverThe SDK's storageOne hour
Discovery documentThe addresses of the provider's endpointsThe SDK's storage (cache)One hour

The default storage is sessionStorage; the SDK's keys start with unet-id: followed by your App ID. See Sessions and storage for the alternatives.

Why PKCE

A public app (a page or a mobile app) cannot keep a secret, so it has no client secret to prove who is exchanging the code. PKCE closes the gap: only the party that created the verifier can redeem the code, because the server compares it with the challenge it saw in step 3. A code stolen from the return URL is useless without the verifier, which never left the SDK's storage.

What is checked, and where

CheckWhereWhat it stops
The discovery document names the issuer you configured, and its authorization, token, userinfo and revocation endpoints are on that issuer's origin over httpsSDK, step 1 (also for a cached copy)A tampered or poisoned document sending the code and tokens elsewhere. A failure is discovery_invalid.
The issuer you configured is https (or http on localhost)SDK, constructorSending tokens over an unprotected connection. A failure is config.
state matches and the pending sign-in is younger than 15 minutesSDK, step 7A forged return, or a stale one. A failure is StateMismatch.
iss equals the configured issuer, when the server sends itSDK, step 7A response from a different provider. A failure is issuer_mismatch.
The verifier matches the challengeUNET ID, step 8A stolen code.
The return URL is exactly one you registeredUNET ID, step 3Sending the code to an address you do not control.
Your app asks only for permissions it registeredUNET ID, step 3 (new apps)An app growing its access without the console. A failure is invalid_scope.

Security keys and 2FA

The sign-in happens on unet.social, not in your app, so whatever the person uses there works for your app without any change: a password, an authenticator code, a security key or a passkey. Your app does not need to know which.

After sign-in

  • The SDK refreshes the access token a minute before it expires, using the refresh token. See Tokens.
  • If the person removes your app in their settings, the next refresh fails and the session ends with SessionExpired.
  • If your server needs to know who signed in, it must verify what the browser sends. See Verify on your server.