Skip to main content
Version 0.4Draft

Plan and design

Why design first

LuxID integrations involve decisions that are expensive to change after go-live. The sub assigned to a user is Sphere-scoped and stable only as long as the Subscription exists; changing Spheres mid-flight breaks user identity linkage. Protocol choice affects which libraries and infrastructure you need. The minimum auth_level you require shapes the user journey. Make these calls deliberately before writing production code.

Work through the checklist at the end of this page before starting implementation.

Decision 1 - protocol: OIDC or SAML

CriterionRecommendation
New web or mobile applicationOIDC
SaaS platform with a built-in SAML SP connectorSAML (no custom code needed)
SaaS platform with a built-in OIDC connectorOIDC
Need API access tokensOIDC (OAuth 2.0 layer)
Legacy enterprise application with SAML-only supportSAML
Mobile / native appOIDC
Server-to-server (no user present)Partner API (X-Client-Id / X-Client-Secret headers) - LuxID's OIDC tenant does not support the Client Credentials grant

Default: choose OIDC. It has richer library support across all languages, simpler debugging (JWTs are human-readable), and is the direction the industry is standardising on. SAML is the right choice when your platform's connector makes it the path of least resistance - see Quick Integrations for platform-specific guides.

Full protocol documentation: OpenID Connect | SAML 2.0.

Decision 2 - required auth_level

Declare the minimum auth_level your application requires. LuxID enforces step-up authentication when the user's current session does not meet the requirement.

auth_levelSecond factor requiredTypical use case
2None (password only)Low-risk personalisation, reading public content
3 or 4OTP (SMS/voice) or TOTPConsumer e-commerce, account management, most B2C apps
8PasskeyPhishing-resistant passwordless sign-in
9LuxTrust (qualified authentication)Identity-verified onboarding, regulated actions. Note: enforcing LuxTrust as the required second factor is a paid add-on. OTP, TOTP and passkeys are included in the base service. If a user voluntarily configures LuxTrust on their account, that is the user's choice and is not invoiced to the Partner.

Questions to answer:

  • Does your application perform actions with legal or financial consequences? If yes, consider requiring auth_level 9.
  • Does your application store or process sensitive personal data? If yes, consider requiring at least auth_level 3 or 4.
  • Is your application subject to a regulatory framework (PSD2, AML, GDPR data subject actions)? Check what authentication strength that framework requires and pick the corresponding auth_level - and note that LuxID does not issue formal eIDAS LoA assertions, so frameworks demanding qualified means may require LuxTrust, a notified eID, or the EUDI Wallet directly.
  • Can some features require a higher auth_level than others (step-up)? If yes, plan for step-up flows.

For the full auth_level scale and how it relates to eIDAS LoA, see Authentication levels.

Decision 3 - MFA policy and step-up

Even if your baseline auth_level is 2 or 3/4, you may want to trigger step-up authentication for specific high-risk actions (changing email address, authorising a payment, exporting personal data).

Design questions:

  • Which actions in your application warrant step-up?
  • What is the target auth_level for each action?
  • How will your application signal to LuxID that step-up is required? (via the acr_values parameter on the authorisation request)
  • How will you handle the case where the user cannot complete step-up (e.g. lost second factor)?

Plan step-up flows before building your UI. Retrofitting step-up into an existing session model is complex.

Decision 4 - claim minimisation

Request only the claims your application genuinely needs. Rationale:

  • Consent friction - every claim you request appears on the user's consent screen. Unnecessary claims increase abandonment.
  • Data liability - every claim you receive is personal data you are responsible for under GDPR (EU) 2016/679 (opens in a new tab). Minimise what you store.
  • LuxID Agreement scope - your LuxID Agreement may restrict which claims you may request. Requesting out-of-scope claims will fail.

For each claim, ask: "Does my application break if this claim is absent?" If no, do not request it.

Claims available from LuxID: sub, name, given_name, family_name, birthdate, updated_at, email, email_verified, phone_number, phone_number_verified. (The age_over_16 claim is defined in the schema but is not currently offered.)

Decision 5 - Sphere strategy

The Sphere determines which sub value a user receives in your application. This is the most consequential identity architecture decision, because sub is how you link LuxID users to records in your own database.

Sphere scenarioEffectWhen to use
Dedicated Sphere per ApplicationEach app sees a unique sub for the same userDefault for isolated apps; maximum privacy isolation
Shared Sphere across your Partner's ApplicationsAll apps under your Partner see the same subWhen you want to link user records across your own apps without asking users to re-link
Shared Sphere across your Organisation's PartnersAll Partners in your Organisation see the same subWhen you operate multiple distinct services and want a unified user identity across all of them

Key constraints:

  • Sphere assignment is set at Application registration time. Changing it later means existing users get a new sub - breaking any foreign-key relationships you have built.
  • Revoking the last Subscription in a Sphere and re-subscribing (e.g. if a user deletes and recreates their account) yields a new sub. Treat sub as stable but not eternal.
  • Sharing a Sphere across Partners creates a cross-Partner user linkage. Ensure your LuxID Agreement and privacy policy cover this.

Recommendation for most new integrations: start with a dedicated Sphere. You can add Applications to it later. Do not share across Partners unless you have a clear architectural reason.

Decision 6 - session lifetime strategy

Your application manages its own session independently of LuxID's tokens. Define your session strategy explicitly.

ParameterConsideration
Application session lifetimeHow long should a user stay logged in to your app without re-authenticating? Align with your security policy.
Access token refreshAccess tokens are short-lived. Use the refresh token to obtain new ones silently.
Refresh token lifetimeRefresh tokens are long-lived. After expiry the user must re-authenticate.
Idle timeoutShould inactivity trigger a logout? Implement this in your application layer, not in LuxID.
LuxID SSO sessionUsers may already have an active LuxID session from another Partner. If so, LuxID's Universal Login will complete silently (no password prompt). You cannot control this - design your UX to accommodate it.

Decision 7 - logout strategy

Logout in a federated system has two distinct concepts:

Local logout - invalidate your application's session only. The user remains logged in to LuxID and may silently re-authenticate if they visit your login page again. Use this for low-sensitivity applications where convenience outweighs security.

User-driven LuxID sign-out - after invalidating your local session, redirect the user to https://login.luxid.lu/auth/logout?client_id=<your_client_id>. LuxID shows a confirmation screen naming your application and the user chooses whether to end the LuxID session. LuxID does not expose an OIDC end_session_endpoint and does not implement RP-Initiated Logout - a single application cannot unilaterally terminate the shared LuxID SSO session. Use this for sensitive applications, shared devices, or when your terms require it.

Design questions:

  • What should the user see after logout? A confirmation page? The login page? Your home page?
  • Should logout be triggered by inactivity?
  • Is your application used on shared devices (kiosks, library computers)? If yes, federated logout is essential.
  • Do you need to handle back-channel logout notifications from LuxID?

Decision 8 - error handling philosophy

Federated authentication introduces failure modes that do not exist in username/password systems. Plan for:

FailureRecommended handling
User cancels at LuxID loginShow a friendly "Sign-in cancelled" message; offer to retry
access_denied from LuxIDExplain the user declined consent; do not retry automatically
Token validation failureLog the error; do not expose token details to the user; ask them to retry
Network error on token exchangeRetry with exponential backoff (max 3 attempts); then show a support message
Refresh token expiredRedirect to login; do not silently fail with a blank page
LuxID service unavailableShow a clear, friendly error and a retry option; do not expose internal error details to the user

Never expose raw OAuth error codes or token contents to end users. Log them server-side with a correlation ID and show a user-friendly message.

See Common errors for the full error code reference.

Decision 9 - branding and UX strategy

LuxID provides the Universal Login page (hosted at https://login.luxid.lu (opens in a new tab)). You do not control the login UI. You do control:

  • The login button in your application (must follow LuxID brand guidelines)
  • The consent experience before and after the LuxID redirect
  • The post-login landing page and onboarding flow
  • Links to your Terms and Conditions and Privacy Information shown on the consent screen (optional)
  • Additional explicit consents you ask LuxID to present on the consent screen, for example "Allow email usage for newsletters"
Do not build your own login or sign-up UI

Your application should only present the "Sign in with LuxID" button. Do not show your own username/password fields or a "Create an account" prompt - both authentication and new-account creation are handled entirely on the LuxID Universal Login page after the redirect.

Design questions:

  • Have you read the Login button guidelines?
  • Is "Sign in with LuxID" your primary or secondary authentication method? Primary: make the button prominent. Secondary: place it after your primary method.
  • What happens on first sign-in for a new user? Do you need a local provisioning / onboarding flow in your application after receiving the token? (This concerns your own user record - the LuxID Account itself is created on the Universal Login page, not by your application.) See Mapping identities to your application for how to link LuxID users to your own user records and keep the IdP pluggable.

Pre-implementation design checklist

Work through this checklist before writing production code. Each item maps to a decision above.

Protocol

  • Chosen protocol: OIDC or SAML
  • Chosen flow: Authorization Code + PKCE (OIDC) or SP-initiated (SAML)
  • OIDC library selected and evaluated for security maintenance

Authentication strength and MFA

  • Baseline minimum auth_level defined (2 = password only, 3/4 = password + MFA, 8 = passkey, 9 = LuxTrust)
  • Step-up actions identified (if any)
  • MFA methods your application will promote to users documented

Claims

  • Claim list reviewed and minimised to genuine need
  • All requested claims are within LuxID Agreement scope
  • Consent screen copy reviewed for clarity

Identity architecture

  • Sphere strategy decided (dedicated / shared Partner / shared Organisation)
  • sub → internal user ID mapping strategy documented
  • Account linking strategy defined (what happens when a user who already has an account in your system signs in with LuxID for the first time?)

Session and tokens

  • Application session lifetime defined
  • Refresh token storage strategy documented (server-side only, encrypted)
  • Idle timeout policy defined
  • Logout strategy chosen (local or federated)
  • Post-logout redirect URI registered

Error handling

  • Error scenarios enumerated and UX copy written for each
  • Server-side error logging with correlation IDs planned
  • Support escalation path documented (user sees a message, what next?)

Security

  • HTTPS enforced on all redirect URIs (production)
  • JWKS key rotation handling planned (library-managed or explicit cache refresh)
  • Client Secret storage reviewed (environment variable / secret manager, not source code)
  • PKCE implemented (even for confidential clients)
  • state and nonce validation implemented

Branding

  • Login button reviewed against Login button guidelines
  • First-login / onboarding flow designed
  • Post-logout page designed

Security review

Next steps

Updated 2026-06-18