Skip to main content

Authorization Flow

LWD implements the OAuth 2.0 Authorization Code flow with optional PKCE support. This is the standard flow for web and mobile apps.


Full flow diagram


Step 1 — Authorization request

Redirect the user to:

GET https://auth.loginwithdomain.com/oauth/authorize
?client_id=YOUR_CLIENT_ID
&redirect_uri=https://yourapp.com/callback
&response_type=code
&scope=openid
&state=RANDOM_STATE
&code_challenge=CODE_CHALLENGE (PKCE, recommended)
&code_challenge_method=S256 (PKCE)
ParameterRequiredDescription
client_idyesYour registered client ID
redirect_uriyesMust exactly match a registered URI
response_typeyesAlways code
scopeyesSpace-separated scopes (e.g. openid)
staterecommendedOpaque value to prevent CSRF
code_challengerecommendedPKCE challenge (Base64URL SHA-256 of verifier)
code_challenge_methodrecommendedAlways S256 when using PKCE

Step 2 — User authenticates

LWD shows a domain input. The user enters their domain. LWD looks up the SP record in DNS and either handles authentication itself or redirects to the external SP.

After authentication, if the app requires consent and the user hasn't granted it before, a consent screen is shown listing the requested scopes.


Step 3 — Authorization code

After consent, LWD redirects back to your redirect_uri:

https://yourapp.com/callback?code=AUTH_CODE&state=STATE

The code expires after 10 minutes.


Step 4 — Token exchange

Exchange the code for tokens at the token endpoint:

POST /oauth/token
Content-Type: application/x-www-form-urlencoded
Authorization: Basic BASE64(client_id:client_secret)

grant_type=authorization_code
&code=AUTH_CODE
&redirect_uri=https://yourapp.com/callback
&code_verifier=PKCE_VERIFIER

See Token Endpoint for the full response format.


PKCE

PKCE (Proof Key for Code Exchange) is strongly recommended for all clients, especially public ones (SPAs, mobile apps) that cannot securely store a client secret.

// Generate verifier
const verifier = randomBytes(32).toString("base64url");

// Compute challenge
const challenge = createHash("sha256").update(verifier).digest("base64url");

// Include in authorization request
?code_challenge=CHALLENGE&code_challenge_method=S256

// Include in token exchange
&code_verifier=VERIFIER