User journey patterns
Source: https://docs.luxid.lu/en/developers/ux/user-journey-patterns/
Last updated: 2026-07-03
Overview
This page documents the end-to-end user journeys for the most common LuxID authentication scenarios. Each journey includes a sequence diagram and a plain-language description of what the user experiences at each step.
Use these diagrams to:
- Communicate the sign-in flow to product teams and designers.
- Identify where your application is responsible for handling state.
- Set correct user expectations in onboarding and help content.
The diagrams use the following actors:
- User - the person signing in
- App - your partner application (browser or native client)
- LuxID - the LuxID authorisation server at
https://login.luxid.lu - AS - your application's server (back-end)
Journey 1: first-time sign-in (account creation)
A user who does not yet have a LuxID Account encounters "Sign in with LuxID" for the first time.
sequenceDiagram
accTitle: First-time sign-in flow
accDescr: A first-time user clicks "Sign in with LuxID", creates an account, verifies their email, approves consent, and is returned to the partner application signed in via the OIDC authorization code flow.
participant U as User
participant App as App (browser)
participant LuxID as login.luxid.lu
participant AS as App server
U->>App: Clicks "Sign in with LuxID"
App->>LuxID: GET /mga/sps/oauth/oauth20/authorize<br>(client_id, redirect_uri, scope, state, code_challenge)
LuxID->>App: Show login page
App->>U: Display login page
U->>App: Clicks "Create an account"
App->>LuxID: Navigate to registration flow
LuxID->>U: Registration form (email, password, name)
U->>LuxID: Submits registration form
LuxID->>U: Verification email sent
U->>LuxID: Clicks verification link in email
LuxID->>App: Show consent screen (requested scopes)
U->>App: Approves consent
App->>LuxID: Consent granted
LuxID->>App: Redirect to redirect_uri?code=AUTH_CODE&state=STATE
App->>AS: POST /callback (code, state)
AS->>LuxID: POST /mga/sps/oauth/oauth20/token (code, code_verifier)
LuxID->>AS: ID token + access token (+ refresh token)
AS->>App: Session established
App->>U: Signed in - welcome to the application
What the user experiences: They click the sign-in button, land on the LuxID page, choose to create an account, verify their email, approve the consent screen, and are returned to your application - signed in and ready to use it.
Your application's responsibilities:
- Generate and store
stateandcode_challengebefore the redirect. - Validate
stateon callback to prevent CSRF. - Exchange the
codefor tokens server-side (never in the browser). - Create or update the user's local session using the ID token claims.
Journey 2: returning sign-in (session cookie present)
A user who already has a LuxID Account and an active session on login.luxid.lu signs in again on a device where they previously authenticated.
sequenceDiagram
accTitle: Returning sign-in with active session
accDescr: A returning user with an active LuxID session cookie clicks "Sign in with LuxID" and is signed back into the partner application in a single click, with no password entry or MFA challenge.
participant U as User
participant App as App (browser)
participant LuxID as login.luxid.lu
participant AS as App server
U->>App: Clicks "Sign in with LuxID"
App->>LuxID: GET /mga/sps/oauth/oauth20/authorize<br>(client_id, redirect_uri, scope, state, code_challenge)
LuxID->>LuxID: Detects existing session cookie
LuxID->>App: Redirect to redirect_uri?code=AUTH_CODE&state=STATE
App->>AS: POST /callback (code, state)
AS->>LuxID: POST /mga/sps/oauth/oauth20/token (code, code_verifier)
LuxID->>AS: ID token + access token
AS->>App: Session established
App->>U: Signed in (no password entry required)
What the user experiences: A single click on "Sign in with LuxID" and they are immediately returned to your application - no password entry, no MFA challenge. The entire round-trip takes under two seconds.
If the user has previously consented to your application's requested scopes, the consent screen is also skipped. The flow is entirely transparent.
Journey 3: sign-in with MFA challenge
A user signs in with a password, then faces a second-factor challenge - either because your application requested acr_values=urn:luxid:acr:level:substantial or because LuxID's risk engine triggered a step-up. (The canonical acr_values form is urn:luxid:acr:level:low|substantial|high; the accepted request values are agreed per Partner during onboarding.)
sequenceDiagram
accTitle: Sign-in with MFA challenge
accDescr: A user enters their password and then completes a second-factor challenge (SMS OTP, TOTP, or passkey), and LuxID returns an ID token with an assurance level of substantial to the partner application.
participant U as User
participant App as App (browser)
participant LuxID as login.luxid.lu
participant AS as App server
U->>App: Clicks "Sign in with LuxID"
App->>LuxID: GET /mga/sps/oauth/oauth20/authorize<br>(acr_values=urn:luxid:acr:level:substantial, ...)
LuxID->>U: Show login page
U->>LuxID: Enters email and password
LuxID->>LuxID: Password correct - MFA required
LuxID->>U: Show MFA challenge<br>(default method: SMS OTP or TOTP or passkey)
U->>LuxID: Completes MFA challenge
LuxID->>LuxID: MFA verified - assurance level = substantial
LuxID->>App: Show consent screen (if first visit)
U->>App: Approves consent
LuxID->>App: Redirect to redirect_uri?code=AUTH_CODE
App->>AS: POST /callback (code, state)
AS->>LuxID: POST /mga/sps/oauth/oauth20/token
LuxID->>AS: ID token (acr=urn:luxid:acr:level:substantial) + access token
AS->>App: Session established
App->>U: Signed in
What the user experiences: They enter their password, then complete a second verification step (confirm an SMS code, enter a TOTP code, or use a passkey). The extra step is framed by LuxID as "Verify it's you."
Your application's responsibilities:
- Check the
acrclaim in the ID token to confirm the assurance level was met. - If
acrdoes not match the required level, reject the session and redirect to/mga/sps/oauth/oauth20/authorizeagain.
Journey 4: sign-in with LuxID Verified identity
A user who has completed LuxID Verified (identity proofing via LuxTrust) signs in to an application that requires a verified identity.
sequenceDiagram
accTitle: Sign-in with LuxID Verified identity
accDescr: A user who has completed LuxID Verified authenticates with their password and LuxTrust second factor, and LuxID returns a high-assurance ID token carrying verified identity attributes to the partner application.
participant U as User
participant App as App (browser)
participant LuxID as login.luxid.lu
participant AS as App server
U->>App: Clicks "Sign in with LuxID"
App->>LuxID: GET /mga/sps/oauth/oauth20/authorize<br>(scope=openid profile email, acr_values=urn:luxid:acr:level:high)
LuxID->>U: Show login page
U->>LuxID: Authenticates (password + LuxTrust 2FA)
LuxID->>LuxID: Enforces high assurance (LuxTrust-verified identity)
LuxID->>U: Consent screen
U->>App: Approves
LuxID->>App: Redirect with auth code
App->>AS: Exchange code for tokens
AS->>LuxID: POST /mga/sps/oauth/oauth20/token
LuxID->>AS: ID token (acr=urn:luxid:acr:level:high)
AS->>App: Session with verified identity attributes
App->>U: Access granted to identity-sensitive feature
What the user experiences: A standard sign-in flow with their LuxTrust second factor. They may see additional claims on the consent screen (verified name, date of birth) that were obtained during identity proofing.
For the full feature reference, see LuxID Verified.
Journey 5: sign-in via LuxID Pro (enterprise federation)
A user whose organisation has federated access configured via LuxID Pro. They sign in with their organisational identity, which is mapped through LuxID.
sequenceDiagram
accTitle: Sign-in via LuxID Pro enterprise federation
accDescr: A user enters their organisation email, LuxID detects the federated domain and redirects to the organisation IdP for authentication, then maps the organisation identity to a LuxID Account and returns a LuxID-issued token to the partner application.
participant U as User
participant App as App (browser)
participant LuxID as login.luxid.lu
participant IdP as Organisation IdP<br>(via LuxID Pro)
participant AS as App server
U->>App: Clicks "Sign in with LuxID"
App->>LuxID: GET /mga/sps/oauth/oauth20/authorize
LuxID->>U: Login page - user enters organisation email
LuxID->>LuxID: Detects organisation domain → LuxID Pro federation
LuxID->>IdP: Redirect to organisation IdP (SAML/OIDC)
U->>IdP: Authenticates with organisation credentials
IdP->>LuxID: Assertion / token
LuxID->>LuxID: Maps organisation identity to LuxID Account
LuxID->>U: Consent screen (if first visit from this app)
U->>App: Approves
LuxID->>App: Redirect with auth code
App->>AS: Token exchange
AS->>LuxID: POST /mga/sps/oauth/oauth20/token
LuxID->>AS: ID token (sub = LuxID user ID, federation attributes)
AS->>App: Session established
App->>U: Signed in with organisation account
What the user experiences: They enter their work email address. LuxID recognises the domain as a federated organisation and redirects them to their organisation's identity provider. After authenticating there (possibly with their organisation's MFA), they are returned to your application via LuxID. The partner application always receives a LuxID-issued token - it does not interact with the organisation IdP directly.
Journey 6: account linking (adding a second authentication method)
An existing user adds a passkey to their LuxID Account. This happens at https://account.luxid.lu/ - outside your application - but the result affects how the user signs in to your application on future visits.
sequenceDiagram
accTitle: Account linking - adding a passkey
accDescr: An existing user signs in to account.luxid.lu, adds a new passkey by confirming with a biometric or PIN, and LuxID registers the WebAuthn credential so it is offered automatically on future sign-ins to any partner app.
participant U as User
participant AccMgmt as account.luxid.lu
participant LuxID as login.luxid.lu
U->>AccMgmt: Signs in to account.luxid.lu
AccMgmt->>LuxID: Authorise (account management scope)
LuxID->>U: Login page
U->>LuxID: Authenticates (password + existing 2FA)
LuxID->>AccMgmt: Tokens
AccMgmt->>U: Account settings page
U->>AccMgmt: Navigates to Security → Add passkey
AccMgmt->>U: "Create a passkey for this device?"
U->>AccMgmt: Confirms with biometric / PIN
AccMgmt->>LuxID: Register new WebAuthn credential
LuxID->>AccMgmt: Credential registered
AccMgmt->>U: "Passkey added successfully"
Note over U,LuxID: On next sign-in to any partner app,<br>the passkey is offered automatically
What the user experiences: They manage their authentication methods in their LuxID Account, not inside any particular partner application. The change applies across all partner applications automatically.
Your application's responsibilities: None - this journey is entirely within LuxID. If you want to nudge users to add a second factor, link them to https://account.luxid.lu/ > Security with a brief explanation.
Journey 7: logout and POST-logout redirect
A user signs out of your application. Your application always clears its own session; the user can additionally choose to end the shared LuxID session.
sequenceDiagram
accTitle: Logout and post-logout redirect
accDescr: A user clicks "Sign out", the application clears its local session and redirects to the LuxID logout confirmation screen, where the user chooses whether to end the shared LuxID session.
participant U as User
participant App as App (browser)
participant LuxID as login.luxid.lu
participant AS as App server
U->>App: Clicks "Sign out"
App->>AS: POST /logout (clear application session)
AS->>App: Application session cleared
App->>LuxID: Redirect to /auth/logout?client_id=YOUR_CLIENT_ID
LuxID->>U: Logout confirmation screen<br>(shows your application name)
U->>LuxID: Confirms "Log out of LuxID"
LuxID->>LuxID: Invalidates LuxID session cookie
LuxID->>U: "You have signed out" page
What the user experiences: they click "Sign out", the application clears its local session, and LuxID presents a confirmation screen naming the application. If the user confirms, the shared LuxID session ends and any subsequent sign-in requires re-entering credentials. If they do not, only the application session was cleared.
Clearing your application's own session is not enough to end the LuxID session - and LuxID does not expose an OIDC end_session_endpoint, so you cannot terminate the LuxID session silently on the user's behalf. As the shared SSO authority for many Partners, LuxID puts the decision to end the global session in the user's hands via the /auth/logout confirmation screen.
Parameters:
| Parameter | Required | Description |
|---|---|---|
client_id | Yes | Your Application's OIDC client_id. LuxID uses it to display your application name on the confirmation screen |
See Session management for the full discussion of why LuxID does not offer silent RP-initiated logout.
Journey summary table
| Journey | Triggers re-auth? | Consent screen shown? | MFA shown? | App controls? |
|---|---|---|---|---|
| First-time sign-in | Yes (new user) | Yes (always) | If enrolled + required | scope, acr_values |
| Returning sign-in (session) | No | No (if previously consented) | No | prompt, max_age |
| MFA challenge | Yes | If first visit | Yes (required by app or risk) | acr_values |
| LuxID Verified | Yes | Yes (includes verified claims) | Yes (LuxTrust) | scope, acr_values |
| LuxID Pro (federation) | Yes (via org IdP) | If first visit | Via org IdP | login_hint (domain) |
| Account linking | N/A (account mgmt) | N/A | Yes (re-auth required) | None |
| Logout | N/A | N/A | N/A | client_id (user-driven via /auth/logout) |
Related pages
- Add Login - OIDC parameters and token exchange
- Universal Login UX - session reuse and
prompt=login - Multi-factor UX - per-method MFA UX
- Passwordless and passkey UX - passkey flows in detail
- LuxID Verified - identity verification feature