Skip to main content
Version 0.3Draft

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 state and code_challenge before the redirect.
  • Validate state on callback to prevent CSRF.
  • Exchange the code for tokens server-side (never in the browser).
  • Create or update the user's local session using the ID token claims.

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.

note

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 acr claim in the ID token to confirm the assurance level was met.
  • If acr does not match the required level, reject the session and redirect to /mga/sps/oauth/oauth20/authorize again.

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.

Important

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:

ParameterRequiredDescription
client_idYesYour 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​

JourneyTriggers re-auth?Consent screen shown?MFA shown?App controls?
First-time sign-inYes (new user)Yes (always)If enrolled + requiredscope, acr_values
Returning sign-in (session)NoNo (if previously consented)Noprompt, max_age
MFA challengeYesIf first visitYes (required by app or risk)acr_values
LuxID VerifiedYesYes (includes verified claims)Yes (LuxTrust)scope, acr_values
LuxID Pro (federation)Yes (via org IdP)If first visitVia org IdPlogin_hint (domain)
Account linkingN/A (account mgmt)N/AYes (re-auth required)None
LogoutN/AN/AN/Aclient_id (user-driven via /auth/logout)

Created 2026-05-22 · Updated 2026-07-03