Skip to main content
Version 0.4Draft

Identity fundamentals

Overview

This page covers the foundational identity concepts that underpin every LuxID integration. It is intentionally protocol-agnostic: the same concepts apply whether your application uses OIDC, OAuth 2.0, or SAML 2.0. Later sections apply these concepts to each protocol in detail.


The AAA triad: authentication, authorisation, and auditing

Modern identity systems are built on three distinct concerns, each with a different answer to a different question.

Authentication

Who are you?

Authentication is the process of verifying that an entity (a human, a service, a device) is who they claim to be. In LuxID's model, authentication produces a cryptographically signed assertion - the ID Token - that states: "This person, identified by sub X, authenticated at time T using methods M, at auth_level L."

Authentication is a moment in time. It answers a historical question: did this authentication event really happen, and can you trust the assertion? It says nothing about what the authenticated party is permitted to do.

Authorisation

What are you allowed to do?

Authorisation determines which resources or operations an authenticated principal may access. In OAuth 2.0, authorisation is expressed through scopes (coarse-grained permissions attached to an Access Token) and claims (fine-grained attributes about the user that the application uses to make access decisions).

LuxID itself performs authorisation in two ways:

  1. Scope-based: the Access Token's scope field tells the Resource Server (e.g. the UserInfo endpoint) which claims the bearer may retrieve.
  2. Group-based: LuxID Partners can define Groups that are conveyed in the ID Token, allowing applications to implement role-based access control without maintaining a separate user directory.

Your application remains responsible for its own authorisation decisions. LuxID tells you who the user is and what they have consented to share. Deciding what they may do in your system is your responsibility.

Auditing

What happened, when, and who did it?

Auditing is the persistent record of authentication and authorisation events. LuxID maintains an event log on its side covering authentication outcomes and account-lifecycle events. A subset of these events is exposed to Partners through the Event Hub (see Events and Event Hub for the exact event types currently emitted). Your application should maintain its own access logs correlated against LuxID's session identifiers and the Transaction ID shown on the LuxID authentication error dialog (see the identifiers reference for how the Transaction ID, Support ID, and Global Transaction ID differ).

The distinction matters for compliance: high-assurance scenarios require not just strong authentication but auditability - the ability to prove that a specific person authenticated at a specific time.


Federation

Can I trust an identity asserted by a third party?

Federation is a trust relationship between two identity systems. Instead of re-verifying a user from scratch, System B accepts an identity assertion from System A, provided both systems have agreed on a trust framework in advance.

LuxID supports federation in two directions:

  • Inbound (LuxID Pro): An organisation (e.g. a corporate customer of a LuxID Partner) operates its own IdP. Via LuxID Pro, that corporate IdP becomes a trusted source of identity assertions. Users authenticate against their corporate IdP; LuxID maps the resulting identity to a LuxID Account and issues standard OIDC tokens to the Partner's application. From the application's perspective, the flow is identical to a direct LuxID authentication.
  • Outbound: LuxID is itself a trusted IdP for LuxID Partners. This is the standard integration case - Partners are relying parties in a federation with LuxID as the authority.

Federation is built on established standards: OIDC and SAML 2.0 both define federation protocols. LuxID's federation uses these standards rather than proprietary mechanisms.

See Roles in the ecosystem for a description of the Federation entity and how LuxID Pro works at the data-model level.


Sessions vs tokens

This distinction is critical and frequently confused. Sessions and tokens are two different mechanisms for maintaining state across HTTP requests, with different security properties.

Server-side sessions

A session is a server-side record. When a user authenticates, the server creates a session object in its own storage (database, cache, memory) and returns a session identifier - typically a cookie - to the browser. On subsequent requests, the browser sends the session ID; the server looks it up and retrieves the session state.

Properties of sessions:

  • Revocable immediately: the server can delete the session record and the session ID becomes worthless.
  • Stateful: the server must maintain storage proportional to the number of active sessions.
  • Opaque to clients: the session ID is a random token; clients cannot read session state without querying the server.

LuxID maintains its own server-side session for the user's login at login.luxid.lu. This session enables Single Sign-On: once a user has authenticated with LuxID, subsequent authorisation requests from any LuxID Partner in the same browser session can be satisfied without re-prompting for credentials (subject to the auth_level the Partner application requires - LuxID will step the user up if the existing session does not meet it).

Bearer tokens

A token is a self-contained credential. The most common form in LuxID integrations is the JSON Web Token (JWT). A JWT encodes claims (assertions) in a signed payload. Any party that holds the token and can verify its signature can trust the claims without contacting LuxID.

Properties of tokens:

  • Stateless: LuxID does not need to look anything up to validate a token; the signature is sufficient.
  • Short-lived by design: because tokens cannot be instantly revoked (without a revocation list), they carry a short expiry (exp claim). LuxID Access Tokens are short-lived; read the exp claim (or expires_in from the token response) for the value that applies.
  • Bearer credentials: whoever holds the token can use it. Protect tokens accordingly.

Why both exist in OIDC

An OIDC authentication flow produces tokens (ID Token, Access Token, optionally Refresh Token). Your application may then choose to establish its own server-side session for its own purposes - for example, to maintain user state between pages without re-validating the ID Token on every request. These are two separate layers:

  • LuxID's session (at login.luxid.lu): controls whether the user must re-authenticate with LuxID.
  • Your application's session (at your domain): controls how long your application trusts a completed LuxID authentication.

See Session management for guidance on aligning these two layers correctly.


Why open standards

LuxID implements open, published standards for every protocol interaction. This is a deliberate architectural decision with concrete benefits for Partners.

Interoperability

Open standards define precise wire formats, message structures, and error codes. Any OIDC-compliant library can integrate with LuxID; you are not constrained to a proprietary SDK. This matters especially in polyglot environments: your backend, mobile app, and web frontend can each use a different library, and they will all interoperate correctly.

Audit-ability

Because the standards are public, the security community has reviewed them exhaustively. Vulnerabilities are documented (see OAuth 2.0 Security Best Current Practice, RFC 9700 (opens in a new tab)), mitigations are specified, and compliant libraries implement those mitigations. Using a proprietary protocol means trusting one vendor's security review; using an open standard means benefiting from the scrutiny of thousands of implementers.

Library availability

Every major programming language has at least one well-maintained OIDC/OAuth 2.0 library. You do not need to implement token parsing, signature verification, or PKCE yourself. See Add Login for recommended libraries per stack.

No vendor lock-in

If your organisation later needs to integrate with a different IdP, or if LuxID's endpoints change, the migration cost is low: your application already speaks standard OIDC. The integration layer is thin and replaceable.

The standards LuxID implements

StandardIdentifierPurpose
OpenID Connect Core 1.0openid.net/specs/openid-connect-core-1_0.html (opens in a new tab)Authentication layer on top of OAuth 2.0
OAuth 2.0RFC 6749 (opens in a new tab)Authorisation framework; token issuance
OAuth 2.0 PKCERFC 7636 (opens in a new tab)Code interception attack prevention
OAuth 2.0 Token IntrospectionRFC 7662 (opens in a new tab)Server-side token validation
OAuth 2.0 Token RevocationRFC 7009 (opens in a new tab)Explicit token invalidation
OAuth 2.0 for Native AppsRFC 8252 (opens in a new tab)Mobile/desktop app security requirements
OAuth 2.0 Security BCPRFC 9700 (opens in a new tab)Current best practice; attack mitigations
OIDC DiscoveryRFC 8414 (opens in a new tab)Metadata endpoint (/.well-known/openid-configuration)
JSON Web TokenRFC 7519 (opens in a new tab)Token format
JSON Web SignatureRFC 7515 (opens in a new tab)Token signing (RS256)
JSON Web Key SetRFC 7517 (opens in a new tab)Public key distribution (JWKS endpoint)
SAML 2.0 CoreOASIS sstc-saml-core-errata-2.0 (opens in a new tab)Assertion format for SAML integrations
WebAuthn Level 3W3C TR/webauthn-3 (opens in a new tab)Passkey / FIDO2 authenticator protocol
eIDAS Assurance LevelsCELEX:32015R1502 (opens in a new tab)Level of assurance definitions

JSON web tokens in practice

LuxID's ID Token and (optionally) Access Token are JSON Web Tokens (JWTs), defined in RFC 7519 (opens in a new tab). Understanding their structure is essential for correct validation.

Structure

A JWT is three Base64url-encoded JSON objects separated by dots:

<header>.<payload>.<signature>

Header - declares the token type and signing algorithm:

{
"alg": "RS256",
"typ": "JWT",
"kid": "OIDC-LUXID-signing-key-1"
}
  • alg: RS256 - RSA signature with SHA-256. LuxID signs all JWTs with RS256.
  • kid: the key identifier. Use this to select the correct key from the JWKS endpoint when verifying the signature.

Payload - the claims (illustrative values from a captured LuxID Account self-service sign-in):

{
"iss": "https://login.luxid.lu",
"sub": "a3f8b2c1-7e4d-4a1b-9c0f-5d2e8b3a6f1c",
"aud": "LuxID_Selfcare",
"exp": 1779026226,
"iat": 1779022626,
"auth_time": 1779022593,
"nonce": "31dd020d-8294-4dae-8095-e8a51e061cc9",
"acr": "urn:luxid:acr:level:substantial",
"amr": ["fido"],
"given_name": "John",
"family_name": "DOE",
"email": "jdoe@example.com",
"email_verified": true
}

A few notes on this example:

  • aud: LuxID_Selfcare is the real client_id of LuxID's own self-service Account application. Your Partner Application has its own client_id.
  • nonce echoes the value the client sent in its authorisation request - here a UUIDv4 from the captured /mga/sps/oauth/oauth20/authorize query string.
  • acr: "urn:luxid:acr:level:substantial" corresponds to auth_level 8 (passkey, phishing-resistant passwordless). See Authentication levels for the full scale.
  • amr: ["fido"] indicates the authentication method was WebAuthn / passkey.
  • The timestamps (iat, exp, auth_time) are Unix seconds; auth_time is when the LuxID session was created, iat is when the token was issued, exp is one hour after iat.
  • sub is an opaque pairwise identifier (Sphere-scoped) - the value above is illustrative, not the real sub for this user.

Signature - the RS256 signature over <header>.<payload>, computed with LuxID's private key.

Validation rules

Always validate all of the following before trusting any claim in an ID Token:

  1. Signature: fetch the JWKS from https://login.luxid.lu/mga/sps/oauth/oauth20/jwks/OIDC-LUXID, select the key by kid, and verify the RS256 signature. A token with an invalid signature must be rejected immediately.
  2. iss: must be exactly https://login.luxid.lu.
  3. aud: must contain your application's client_id. Reject tokens issued to other clients.
  4. exp: must be in the future (server clock; allow a small skew of at most 60 seconds).
  5. iat: should be recent (reject tokens issued far in the past - this limits replay attacks).
  6. nonce: if you sent a nonce in the authorisation request, the token must carry the same value. Verify it against the value stored in the user's session.

All compliant OIDC libraries perform these checks automatically. Do not bypass them.

JWKS endpoint

LuxID publishes its public keys at:

https://login.luxid.lu/mga/sps/oauth/oauth20/jwks/OIDC-LUXID

Cache the JWKS response (respect Cache-Control headers) and refresh when you encounter an unknown kid. Do not fetch the JWKS on every token validation - this is a network call you can avoid.

See Tokens and claims for the complete claim catalogue and per-token validation guidance.


Summary

ConceptOne-line definition
AuthenticationVerifying credentials; produces a signed assertion
AuthorisationDetermining permissions; uses scopes and claims
AuditingThe tamper-evident record of what happened
FederationTrusting identity assertions from another system
SessionServer-side state; instantly revocable, stateful
TokenSelf-contained bearer credential; stateless, short-lived
JWTThree-part signed JSON structure; always validate signature, iss, aud, exp, nonce
Open standardsInteroperability, auditability, library availability, no lock-in
Updated 2026-07-03