Skip to main content
Version 0.3Draft

Delegated authorisation

Overview

Delegated authorisation is the pattern where an application acts on behalf of a user at another service, doing something the user has permission to do, without the user being present at each operation.

In OAuth 2.0 terms, this is the core promise of the framework: the access token represents the user's delegated permission to a specific application for a specific scope.

This page covers advanced delegation patterns that go beyond a single application calling a single API:

  • Standard user-delegated access tokens - the OAuth 2.0 baseline.
  • Token exchange (RFC 8693 (opens in a new tab)) - trading one token for another.
  • Refresh token scoping rules within an application and across applications.
  • Cross-application delegation via the Partner API.
  • On-behalf-of flows for backend services that act on user data without direct user interaction.

Standard user-delegated authorisation

This is the baseline OAuth 2.0 pattern, described in RFC 6749 (opens in a new tab) and implemented in LuxID's Authorization Code flow.

When a user authenticates with your application, LuxID issues an access token that represents:

  • Who the user is (sub claim).
  • What your application is allowed to do on the user's behalf (scope).
  • For how long (exp).

Your application presents this access token to resource servers (APIs) to act on the user's behalf. The resource server validates the token and grants access according to the scopes.

The key properties of user-delegated tokens:

  • The access token is bound to the user (sub) and bound to the application (aud / client_id).
  • The user can revoke this delegation at any time from LuxID Account (opens in a new tab).
  • The application can revoke the delegation via the Revocation endpoint.
  • The scope is limited at consent time - the user agreed to specific claims and actions, not unlimited access.

Refresh Token scoping rules

Refresh tokens in LuxID are scoped as follows:

Within the same Application (multiple backend instances)

A refresh token issued to your application can be used by any backend process that shares the same client_id. This supports:

  • Horizontal scaling: any backend server can call the Token endpoint with the same refresh token.
  • Deployment rotation: a newly deployed server can pick up an active refresh token issued by a previous deployment.

Constraint: the client_id must be identical. The UAT and Production registrations of the same Application have different client_id values and their refresh tokens are not interchangeable.

Across different Applications

Refresh tokens are not transferable across applications. A refresh token issued to Application A cannot be presented by Application B. Attempting to do so will return invalid_client.

This boundary is enforced at the LuxID server level and cannot be bypassed. It protects users by ensuring that granting access to one application never implicitly grants access to another.

Sharing user data across Applications

If you need to share user data across your own applications, the correct pattern is:

  1. Each application obtains its own access token via its own authorisation flow.
  2. Use the Partner API to query user data server-to-server using Partner API credentials (not user-delegated tokens).
  3. Or use token exchange (see below) to obtain a new token scoped to the target application's audience.

Token exchange (RFC 8693)

RFC 8693 - OAuth 2.0 Token Exchange (opens in a new tab) defines a standard mechanism for exchanging one token for another - trading a user access token for a new token scoped to a different audience - without requiring the user to re-authenticate.

Not available today

LuxID's discovery document advertises only the authorization_code and refresh_token grant types - token exchange (RFC 8693) is not currently available. The pattern below is kept as reference. If your integration needs token exchange, contact LuxID, and re-check grant_types_supported at https://login.luxid.lu/.well-known/openid-configuration (opens in a new tab) before building against it.

Canonical use case - authenticated webview

A mobile application holds an access token for its own audience. It needs to open an embedded webview pointing at a sibling service within the same Sphere (for example, a self-service portal). Token exchange lets the mobile app obtain a fresh access token scoped to the webview's audience, so the embedded webview opens already authenticated. The user does not see a second sign-in screen.

Flow

Request

curl -X POST \
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange&client_id=<your_client_id>&subject_token=<existing_access_token>&subject_token_type=urn:ietf:params:oauth:token-type:access_token&audience=<target_audience>" \
"https://login.luxid.lu/mga/sps/oauth/oauth20/token"

Parameters

ParameterValueDescription
grant_typeurn:ietf:params:oauth:grant-type:token-exchangeIdentifies this as an RFC 8693 token exchange request
client_idYour Application's Client IDThe requesting Application. Must already hold a valid access token for the subject
subject_tokenExisting access tokenThe access token to exchange
subject_token_typeurn:ietf:params:oauth:token-type:access_tokenDeclares the type of the subject token
audienceTarget service audience identifierThe audience of the new token - the relying party that will receive and validate it

Response

The token endpoint returns a standard token response. The access_token in the response is scoped to the requested audience and preserves the user's identity (sub). The original token is not revoked.

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 600,
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
}

Additional use cases

  • A gateway service exchanges a user token for a narrower-scoped token before calling a downstream microservice.
  • A backend service needs to act on the user's behalf in a different security context (on-behalf-of pattern; see below).

Cross-references

  • For the token that feeds into this flow, see OAuth 2.0 for APIs.
  • For token claims anatomy, see Tokens and claims.
  • The Partner API is a distinct mechanism: it uses Client ID + Client Secret headers for server-to-server queries, not OAuth tokens or grant types. Use the Partner API when you need to query or modify user data without a live user session; use token exchange when you need a user-delegated token for a different audience.

On-behalf-of flow for backend services

An on-behalf-of (OBO) flow is a token exchange variant where Service A presents a user token to LuxID and receives a new token that allows Service A to act as the user when calling Service B.

The new token preserves the user's identity (sub) while being scoped and audited for Service B. Service B can introspect the token and confirm it represents the user acting via Service A.


Cross-Application use cases via the Partner API

For scenarios where you need to query or modify user data on behalf of a user across multiple applications without a live user session, the Partner API provides server-to-server endpoints using Partner API credentials.

Partner API credentials are separate from user-delegated tokens - they represent your organisation's authorisation to manage data within the LuxID data model, not a specific user's delegated permission.

Typical Partner API delegation patterns:

  • Subscription query: check whether a user has an active Subscription with your application without requiring a token from that user. Useful for background jobs.
  • Consent query: check what claims a user has consented to share, server-side.
  • Event-driven updates (planned): reacting to events such as subscription.revoked or user.email.changed to update your own database without calling UserInfo is a planned Event Hub capability - today the Event Hub emits only ClaimValuesChanged. See Events and Event Hub.

See the Partner API documentation for the full endpoint reference.


Choosing the right delegation pattern

ScenarioRecommended pattern
Application acts on user data during an active sessionStandard access token (Authorization Code flow)
Application acts on user data in background jobsPartner API server-to-server
Service A needs to call Service B as the userToken exchange (RFC 8693)
Multiple instances of the same app share tokensRefresh token reuse (same client_id)
Share user data across two of your own appsEach app authenticates independently; use Partner API for cross-app queries
User revokes accessRevocation endpoint (plus the planned subscription.revoked webhook)

Security considerations

Principle of least privilege

Always request the minimum scope necessary. A token with read:profile cannot be used to modify user data. If a downstream service only needs to read the user's name, do not issue it a token with write scopes.

Token binding

Access tokens are bound to the issuing application's client_id. A resource server that validates the aud claim will reject tokens not intended for it. Always configure your resource servers to validate aud.

Propagation chain transparency

When tokens are exchanged or propagated across services, the audit trail must remain visible. LuxID logs all Token endpoint calls including exchange requests. See Logs and audit trails.

Revocation propagates upward

If a user revokes their Subscription for Application A, all tokens associated with Application A are invalidated - including any tokens Application A may have exchanged for downstream services. Design your services to handle 401 Unauthorized responses gracefully at every layer.


Updated 2026-07-03