OpenID Connect Security
This document provides a comprehensive overview of OpenID Connect and OAuth 2.0 security options in LemonLDAP::NG.
Supported Security Specifications
LemonLDAP::NG implements security recommendations from:
OpenID Connect Core 1.0 - Authentication and security requirements
OpenID Connect Back-Channel Logout 1.0
RFC 7636 - Proof Key for Code Exchange (PKCE)
RFC 7662 - OAuth 2.0 Token Introspection
RFC 9068 - JWT Profile for OAuth 2.0 Access Tokens
RFC 9701 - JWT Response for OAuth 2.0 Token Introspection
RFC 9207 - OAuth 2.0 Authorization Server Issuer Identification
RFC 9700 - OAuth 2.0 Security Best Current Practice
ANSSI Guidelines and France-Connect+ compliance - French National Cybersecurity Agency recommendations
RFC 6749 (OAuth 2.0 - authorization code flow, state parameter)
RFC 6750 (Bearer Token Usage)
RFC 7515/7516 (JWS/JWE signatures and encryption)
RFC 7518 (JSON Web Algorithms)
Quick Reference
Feature |
Specification |
OP Config |
RP Config |
|---|---|---|---|
PKCE |
RFC 7636 |
Require PKCE (per RP) |
PKCE required (per OP) |
Issuer verification |
RFC 9207 |
Always enabled (auto) |
Issuer required |
State parameter |
RFC 6749 |
Require state |
Always sent (auto) |
Nonce parameter |
OIDC Core |
Require nonce |
Use nonce |
JWS signatures |
RFC 7515 |
ID Token signature alg |
Check JWT signature |
JWE encryption |
RFC 7516 |
Encryption algorithms |
N/A |
Hashed tokens |
ANSSI R21/R25 |
Hashed session storage |
N/A |
Token endpoint auth |
RFC 6749 |
Token endpoint auth method |
Token endpoint auth method |
Request objects |
OIDC Core |
Require JWS for auth requests |
Auth method for code request |
OP Security Configuration
This section covers all security options to configure when LemonLDAP::NG acts as an OpenID Connect Provider.
Flows
RFC 9700 Recommendation: Use the Authorization Code flow instead of Implicit or Hybrid flows.
Configuration: OpenID Connect Service > Security:
Disable
Allow Implicit GrantDisable
Allow Hybrid GrantEnable only
Allow Authorization Code Grant(default)
PKCE
Proof Key for Code Exchange (RFC 7636) prevents authorization code interception attacks.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options > Security:
Require PKCE: Set to
Onto require code_challenge at token endpoint
Tip
For public clients (mobile apps, SPAs), PKCE is essential. Enable it for all clients when possible.
State and Nonce
The state parameter is generated by the RP (client) and sent in the authorization request. The OP returns it unchanged in the authorization response. The RP then verifies that it matches the original value stored in the user’s session. This prevents CSRF attacks by ensuring the response corresponds to a request initiated by the user.
The nonce parameter is also generated by the RP and sent in the authorization request. The OP includes it in the ID Token it issues. The RP verifies that the nonce in the ID Token matches the one it sent. This prevents replay attacks by ensuring each ID Token is bound to a specific authorization request.
As an OP, you can require that RPs include these parameters in their authorization requests.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options > Security:
Require “state” in authorization request: Reject requests without state (ANSSI R12)
Require “nonce” in authorization request: Reject requests without nonce (ANSSI R16)
Redirect URI Validation
RFC 9700 Recommendation: Use exact redirect URI matching, no wildcards.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Basic options:
Allowed redirection addresses for login: Space-separated list of exact URIs
Token Security
Token Endpoint Authentication
ANSSI R23 Recommendation: Use asymmetric authentication (private_key_jwt) over symmetric methods.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options > Security:
Token endpoint authentication method:
client_secret_basic- HTTP Basic Auth (default)client_secret_post- Secret in POST bodyclient_secret_jwt- HMAC-signed JWTprivate_key_jwt- Asymmetric signed JWT (recommended)tls_client_auth- mTLS client certificate (RFC 8705, since 3.0.0)
mTLS Client Authentication (RFC 8705)
Mutual TLS (mTLS) authentication allows OAuth 2.0 clients to authenticate using TLS client certificates instead of a shared secret. This is described in RFC 8705.
Web Server Configuration
The web server (Apache/Nginx) must be configured to request and validate client certificates on the following endpoints:
/oauth2/token- Token endpoint/oauth2/introspect- Introspection endpoint/oauth2/revoke- Revocation endpoint
See Mutual TLS Authentication for Apache and Nginx configuration examples on how to request client certificates and pass them to LemonLDAP::NG via environment variables.
LemonLDAP::NG Configuration
Configuration is done per Relying Party in OpenID Connect Relying Parties > RP name > Options > mTLS:
Certificate identifier type: Select the type of certificate attribute to match:
SAN DNS (default): DNS name in the Subject Alternative Name extension
Subject DN: Distinguished name of the certificate subject (e.g.,
CN=myclient,O=Example,C=FR)SAN Email: Email address in the SAN extension
SAN IP: IP address in the SAN extension
SAN URI: URI in the SAN extension
Expected certificate identifier: The expected value for the selected identifier type
Both fields should be configured when using tls_client_auth method.
The web server must export one of the following environment variables
(the ones chosen to identify clients):
SSL_CLIENT_S_DN: Client certificate Subject DNSSL_CLIENT_SAN_DNS_0: First DNS SAN entrySSL_CLIENT_SAN_Email_0: First Email SAN entrySSL_CLIENT_SAN_IP_0: First IP SAN entrySSL_CLIENT_SAN_URI_0: First URI SAN entry
Important
SSL_CLIENT_S_DN must always be exported by the web server, even when
another identifier type (SAN DNS, Email, IP or URI) is used for matching.
LemonLDAP::NG relies on the presence of this variable to detect that the
tls_client_auth method is being used and to trigger the mTLS logic. If it
is missing, the token endpoint request silently falls back to the none
authentication method.
Note
Web servers do not all expose the same certificate variables out of the box:
Nginx only exposes the Subject DN (
$ssl_client_s_dn→SSL_CLIENT_S_DN). SAN entries are not available natively, so with Nginx you should either use the Subject DN identifier type, or extract and export the required SAN value yourself.Apache exposes
SSL_CLIENT_S_DN,SSL_CLIENT_SAN_DNS_nandSSL_CLIENT_SAN_Email_n. SAN IP and SAN URI are not exported natively and would require a custom configuration to be used as identifiers.
Web Server Configuration Examples
The endpoints (/oauth2/token, /oauth2/introspect, /oauth2/revoke)
must request a client certificate and pass its attributes to LemonLDAP::NG.
Use optional verification so that clients authenticating with another method
(client_secret_basic, private_key_jwt, …) are still accepted.
With Apache:
SSLVerifyClient optional
SSLVerifyDepth 10
SSLCACertificateFile /etc/apache2/ssl/ca.crt
# Export SSL_CLIENT_S_DN, SSL_CLIENT_SAN_DNS_n, SSL_CLIENT_SAN_Email_n, ...
SSLOptions +StdEnvVars +ExportCertData
With Nginx, only the Subject DN is available natively; forward it so that the mTLS logic is triggered and Subject DN matching works:
ssl_verify_client optional;
ssl_verify_depth 10;
ssl_client_certificate /etc/nginx/ssl/ca.pem;
# Always forward the Subject DN: it triggers the mTLS logic and
# enables the "Subject DN" identifier type
fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn;
Note
Nginx does not expose the certificate SAN entries. To use a SAN DNS,
SAN Email, SAN IP or SAN URI identifier type with Nginx, you must
extract the value from the client certificate yourself (for example from
$ssl_client_escaped_cert) and forward it as SSL_CLIENT_SAN_DNS_0,
SSL_CLIENT_SAN_Email_0, etc. Otherwise, use the Subject DN type.
See Mutual TLS Authentication for more complete Apache and Nginx virtual host examples.
Hashed Token Storage
Store tokens as hashes to prevent exposure in case of database compromise (ANSSI R21/R25).
Configuration: General Parameters > Advanced parameters > Security:
Hashed session storage: Set to
On
Attention
This breaks existing OIDC offline sessions and is incompatible with SOAP-mode Proxy authentication.
You can use the tool convertSessions to convert existing sessions.
Access Token Lifetime and Refresh Tokens
ANSSI R33 Recommendation: Limit access token validity to reduce exposure in case of token theft.
Best practices:
Enable refresh tokens even for online sessions. This allows setting a short access token lifetime (e.g., 10 minutes) while maintaining user sessions through token refresh. If an access token is stolen, it will expire quickly.
Enable refresh token rotation if the client supports it. A new refresh token is issued on each use, and the previous one is invalidated. This limits the impact of a stolen refresh token. This applies to both online and offline refresh tokens.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options:
Advanced> Use refresh tokensSecurity> Invalidate refresh tokens after use
Configuration: OpenID Connect Service > Timeouts:
Access Tokens: Set to a short duration (e.g., 600 seconds / 10 minutes)
Refresh Tokens: Set according to desired session duration
Algorithms
ID Token Signature
ID Tokens are signed by default using RS256.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options > Algorithms:
ID Token signature algorithm:
Avoid:
none,HS256(HMAC-based)Recommended:
RS256(default),RS384,RS512,ES256,ES384,ES512,PS256,PS384,PS512,EdDSA
Note
Elliptic curve algorithms (ES*) added in 2.19.0 for France-Connect+ compliance.
JWT Encryption
Added for France-Connect+ compliance.
For sensitive data, encrypt tokens in addition to signing. Encryption can be applied to:
ID Token: returned in token endpoint responses
UserInfo: returned by the UserInfo endpoint
Access Token: if using JWT format (RFC 9068)
Introspection response: if using JWT format (RFC 9701, since 2.23.0)
Attention
The RP must expose its public encryption keys via its JWKS (JSON Web Key Set) endpoint for the OP to encrypt data.
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options > Algorithms:
ID Token Encryption key management algorithm
ID Token Encryption content encryption algorithm
Access Token Encryption algorithms (if JWT format)
UserInfo Encryption algorithms
Introspection Encryption algorithms (if JWT format, since 2.23.0)
Other Options
Metadata Discovery (ANSSI R48)
The OpenID Connect discovery endpoint (/.well-known/openid-configuration) exposes OP configuration. In high-security environments, you may want to disable it to reduce information exposure.
Configuration: OpenID Connect Service > Security:
Don’t display metadata
Warning
Disabling discovery is non-standard and may break applications that rely on automatic OP configuration. Only disable this if all your RPs support manual configuration.
Dynamic Registration (ANSSI R49)
Dynamic client registration allows RPs to register automatically without administrator approval. This should be disabled in production environments to maintain control over authorized clients.
Configuration: OpenID Connect Service > Dynamic registration:
Activation: Off (default)
Secret Management (ANSSI R35-R37)
Client secrets must be managed securely:
Use cryptographically random secrets with good entropy (use
pwgen -s 32oropenssl rand -base64 32)Use a unique secret per RP
Plan regular secret rotation
Logging (ANSSI R32)
Access tokens should not appear in logs to prevent token theft from log files.
Configuration: Set log level to info or notice. Tokens are only visible at debug level.
RP Security Configuration
This section covers all security options to configure when LemonLDAP::NG acts as an OpenID Connect Relying Party.
PKCE
Proof Key for Code Exchange (RFC 7636) prevents authorization code interception attacks by binding the authorization code to the client that requested it.
Configuration (per Provider): OpenID Connect Providers > OP name > Options > Configuration:
PKCE required: Set to
Onto always use PKCE in authorization requests
Issuer Verification (RFC 9207)
RFC 9207 prevents mix-up attacks by including the iss parameter in authorization responses.
Configuration (per Provider): OpenID Connect Providers > OP name > Options > Configuration:
Issuer required (RFC 9207): When enabled, the RP will:
Verify the
issparameter matches the expected issuer (if present)Reject responses without
iss(when required)
Attention
Enable this option when connecting to OPs that support RFC 9207 to protect against mix-up attacks.
Nonce
The nonce prevents replay attacks (see State and Nonce for details).
Configuration (per Provider): OpenID Connect Providers > OP name > Options > Protocol:
Use nonce: On (default)
Token Security
Configuration (per Provider): OpenID Connect Providers > OP name > Options > Protocol:
Token endpoint authentication method: Use
private_key_jwt(recommended)Authentication method for authorization code request: Prefer asymmetric algorithms
Signature algorithm for authorization code authentication: Set explicit algorithm
JWT Verification
Configuration (per Provider): OpenID Connect Providers > OP name > Options > Protocol:
Check JWT signature: Set to
On
Built-in Security Features
These security features are automatically implemented without configuration:
Feature |
Description |
Reference |
|---|---|---|
State parameter (RP) |
Always sent in authorization requests |
RFC 6749, ANSSI R10 |
Secure random generation |
State, nonce, auth codes, tokens use cryptographic random |
ANSSI R11/R15/R18/R24 |
Domain verification |
Automatic domain name verification |
ANSSI R6 |
Session cookies |
SSO uses secure session cookies |
ANSSI R13 |
Open redirect protection |
URI validation prevents open redirects |
ANSSI R17 |
Authorization code binding |
Auth codes bound to OIDC client |
ANSSI R20 |
One-time auth codes |
Used auth codes are invalidated |
ANSSI R30 |
ID Token validation |
Integrity and claims verification |
ANSSI R26/R28 |
Authentication level |
ACR/AMR support for level verification |
ANSSI R29 |
Bearer token handling |
Access tokens via Authorization header |
ANSSI R31 |
Token timeouts |
Configurable validity limits |
ANSSI R33 |
UserInfo cross-check |
UserInfo validated against ID Token |
ANSSI R34 |
Event logging |
Important events logged |
ANSSI R47 |
Issuer parameter (OP) |
RFC 9207 |
RFC 9207 |
Compliance Reference
ANSSI Guidelines
The Agence Nationale de la Sécurité des Systèmes d’Information (ANSSI) published recommendations for securing OpenID Connect.
Compliance Matrix
Category |
Recommendations |
LemonLDAP::NG Implementation |
|---|---|---|
Flow Security |
R1 |
Disable Implicit/Hybrid (configurable) |
TLS/Crypto |
R3-R8 |
HTTPS required, JWS algorithms configurable |
Auth Request |
R9-R16 |
State/nonce automatic (RP) or required (OP 2.19.0) |
Auth Code |
R17-R22 |
Automatic: random, bound, one-time, hashed (opt) |
Token Security |
R23-R25 |
Token endpoint auth methods, hashed storage (opt) |
ID Token |
R26-R30 |
Automatic validation and verification |
Access Token |
R31-R34 |
Automatic: header, timeouts, cross-check |
Secrets |
R35-R41 |
Per-RP secrets recommended |
Algorithms |
R42-R44 |
Configurable per RP, ES* since 2.19.0 |
Operations |
R45-R51 |
Logging, discovery toggle, no dynamic reg |
Complete ANSSI Recommendations Reference
Below is the complete list of ANSSI recommendations (in French, as in the original document):
R1 Utiliser en priorité la cinématique authorization code pour les applications Web
R2 Mettre en place une politique de sécurité
R3 Mettre en œuvre HTTPS
R4 Appliquer les recommandations de sécurité relatives à TLS
R5 Imposer aux clients OIDC des suites cryptographiques recommandées pour les communications serveur à serveur
R6 Vérifier le nom de domaine
R7 Utiliser le certificate pinning
R8 Utiliser un JWS protégé par un HMAC
R8+ Utiliser un JWS protégé par une signature
R9 Imposer un mode de transmission des paramètres dans une demande d’authentification
R10 Systématiser l’envoi du paramètre state
R11 Générer aléatoirement le paramètre state
R12 Détecter les demandes d’authentification sans le paramètre state
R13 Utiliser les cookies de session
R14 Systématiser l’envoi du paramètre nonce
R15 Générer aléatoirement le paramètre nonce
R16 Détecter les demandes d’authentification sans le paramètre nonce
R17 Se protéger contre les redirections ouvertes
R18 Générer aléatoirement les authorization code
R19 Limiter la durée de vie d’un authorization code
R20 Associer le code authorization code au client OIDC
R21 Stocker les authorization code sous forme d’empreinte
R22 Vérifier le paramètre state associé à la session de l’utilisateur
R23 Utiliser une authentification du client OIDC adaptée
R24 Générer aléatoirement les access token
R25 Stocker les access token sous formes d’empreintes
R26 Vérifier l’intégrité de l’ID Token
R27 Utiliser un secret partagé différent du client_secret pour générer le HMAC de l’ID Token
R28 Vérifier les informations d’un ID Token
R29 Vérifier le niveau d’authentification de l’utilisateur
R30 Rendre inutilisables les authorization code
R31 Transmettre les access token par l’entête Authorization
R32 Ne pas écrire dans les journaux les access token
R33 Restreindre la durée de validité d’un access token
R34 Croiser les informations du UserInfo et de l’ID Token
R35 Générer aléatoirement les secrets d’authentification partagés
R36 Renouveler les secrets d’authentification partagés
R37 Utiliser un secret différent par client OIDC
R38 Restreindre l’accès au secret d’authentification
R39 Utiliser des certificats pour authentifier les JWS
R40 Restreindre l’accès à la clé privée de signature
R41 Vérifier la révocation des certificats
R42 Utiliser des fonctions de hachage recommandées
R43 Utiliser des mécanismes de signature recommandés
R44 Fixer l’algorithme utilisé pour le JWS
R45 Sécuriser l’application Web OIDC
R46 Mettre en oeuvre un système de journalisation
R47 Journaliser les évènements importants
R48 Désactiver la découverte automatisée
R49 Ne pas utiliser l’enrôlement automatisé
R50 Sécuriser l’interface Web de configuration d’un client OIDC
R51 Vérifier l’identité des fournisseurs de service
France-Connect+
France-Connect+ requires specific security options:
JWE encryption: ID Token and UserInfo encryption support
Elliptic curve algorithms: ES256, ES384, ES512 for signatures
RFC Coverage
RFC 9700 - Security Best Current Practice
RFC 9700 (formerly draft-ietf-oauth-security-topics) defines best current practices for OAuth 2.0 security.
Key recommendations implemented:
Authorization Code flow only (configurable)
PKCE support (configurable per RP/OP)
Exact redirect URI matching
Secure token handling
RFC 9207 - Issuer Identification
OP:
issparameter automatically included in all authorization responsesRP: Configurable verification of
issparameter
RFC 7636 - PKCE
OP: Require PKCE per RP
RP: Enable PKCE per OP
RFC 9701 - JWT Response for Token Introspection
RFC 9701 allows returning introspection responses as signed (and optionally encrypted) JWTs instead of plain JSON. This provides:
Integrity: The response is signed, ensuring it hasn’t been tampered with
Confidentiality: Optional encryption protects sensitive token metadata
Non-repudiation: The signature proves the response came from the authorization server
Configuration (per Relying Party): OpenID Connect Relying Parties > RP name > Options > Algorithms:
Introspection response format: Select signature algorithm (RS256, ES256, etc.)
Introspection Encryption key management algorithm: Optional encryption
Introspection Encryption content encryption algorithm: Encryption content algorithm
Security Checklists
OP Security Checklist
[ ] Disable Implicit and Hybrid flows
[ ] Enable PKCE requirement for all RPs
[ ] Require state and nonce parameters
[ ] Use private_key_jwt for token endpoint authentication
[ ] Configure ID Token signature algorithm (RS256 or ES256)
[ ] Enable hashed session storage
[ ] Set appropriate token timeouts
[ ] Use unique secrets per RP
[ ] Disable dynamic registration (unless needed)
[ ] Configure appropriate log level
[ ] Protect Manager access
[ ] Use HTTPS only
RP Security Checklist
[ ] Enable PKCE
[ ] Enable Issuer verification (RFC 9207)
[ ] Enable nonce
[ ] Use private_key_jwt for token endpoint authentication
[ ] Enable JWT signature verification
[ ] Use appropriate ACR values
[ ] Configure proper redirect URIs
[ ] Use HTTPS only
