Skip to content

OpenID Connect

IDToken acts as an OpenID Connect (OIDC) Provider, enabling any OIDC-compliant application to accept IDToken authentication using standard protocols. This provides integration with cloud services (Google Workspace, Microsoft 365, etc.), SaaS platforms, and modern web applications without custom integration code.

IDToken already issues signed JWTs with identity claims — OIDC formalizes this into a standard protocol that any application can consume. While the direct JWT integration works well for custom applications, OIDC enables:

  • Cloud service SSO — Google Workspace, Microsoft 365, Slack, GitHub, and thousands of SaaS applications support OIDC out of the box
  • Standard discovery — applications auto-configure by fetching /.well-known/openid-configuration
  • Interoperability — any OIDC client library (in any language) works without custom code
  • Compliance — OIDC is a recognized standard for identity federation in enterprise and government contexts

The OIDC layer sits on top of the existing X.1280 authentication flow, just as the SAML IdP does. The same OTP + mobile face verification produces an OIDC id_token instead of (or in addition to) a JWT or SAML assertion.

Client AppIDToken (OP)Mobile App1. /authorize (code flow)2. Login pageEnter tokenId3. X.1280 (OTP + face)4. Auth verified5. Redirect + auth code6. POST /token (code)7. id_token + access_tokenUser authenticated
EndpointMethodDescription
/.well-known/openid-configurationGETOIDC discovery document
/oidc/authorizeGETAuthorization endpoint (starts auth flow)
/oidc/tokenPOSTToken endpoint (exchanges code for tokens)
/oidc/userinfoGETUserInfo endpoint (returns identity claims)
/.well-known/jwks.jsonGETJSON Web Key Set (existing endpoint)
/oidc/end-sessionGET/POSTRP-initiated logout

The OIDC discovery document at /.well-known/openid-configuration advertises the provider’s capabilities:

{
"issuer": "https://auth.idtoken.id3.eu",
"authorization_endpoint": "https://auth.idtoken.id3.eu/oidc/authorize",
"token_endpoint": "https://auth.idtoken.id3.eu/oidc/token",
"userinfo_endpoint": "https://auth.idtoken.id3.eu/oidc/userinfo",
"jwks_uri": "https://auth.idtoken.id3.eu/.well-known/jwks.json",
"end_session_endpoint": "https://auth.idtoken.id3.eu/oidc/end-session",
"scopes_supported": [
"openid", "profile", "email",
"identity:name", "identity:date_of_birth",
"identity:nationality", "identity:age_over_18",
"identity:age_over_21", "identity:trust_level"
],
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code"],
"subject_types_supported": ["public", "pairwise"],
"id_token_signing_alg_values_supported": ["ES256"],
"token_endpoint_auth_methods_supported": [
"client_secret_basic", "client_secret_post"
],
"claims_supported": [
"sub", "name", "given_name", "family_name",
"birthdate", "nationality", "age_over_18",
"age_over_21", "trust_level"
]
}

IDToken uses the Authorization Code Flow (the most secure OIDC flow):

  1. The client redirects the user to /oidc/authorize with the requested scopes
  2. IDToken displays the login page (enter tokenId)
  3. The standard X.1280 authentication flow runs (OTP + mobile face verification)
  4. On success, IDToken redirects back to the client with an authorization code
  5. The client exchanges the code for an id_token and access_token via the /oidc/token endpoint
  6. Optionally, the client calls /oidc/userinfo for additional claims
GET /oidc/authorize?
response_type=code
&client_id=bar-le-central
&redirect_uri=https://bar-le-central.fr/callback
&scope=openid identity:name identity:age_over_18
&state=random-csrf-token
&nonce=random-replay-protection
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"id_token": "eyJhbGciOiJFUzI1NiIs...",
"scope": "openid identity:name identity:age_over_18"
}

The id_token is a JWT (ES256-signed) containing identity claims mapped to OIDC standard claim names where possible:

IDToken ScopeOIDC ClaimTypeDescription
openidsubstringSubject identifier (tokenId)
identity:namegiven_name, family_name, namestringFull name from VDS
identity:date_of_birthbirthdatestringISO 8601 date
identity:nationalitynationalitystring3-letter ISO code (custom claim)
identity:age_over_18age_over_18booleanDerived from birthdate (custom claim)
identity:age_over_21age_over_21booleanDerived from birthdate (custom claim)
identity:trust_leveltrust_levelnumber1 (self), 2 (operator), 3 (eIDAS)
identity:photopicturestringBase64-encoded portrait (restricted)
{
"iss": "https://auth.idtoken.id3.eu",
"sub": "vds-token-uuid",
"aud": "bar-le-central",
"exp": 1705316400,
"iat": 1705312800,
"nonce": "random-replay-protection",
"given_name": "Jean",
"family_name": "Dupont",
"name": "Jean Dupont",
"age_over_18": true,
"trust_level": 3,
"acr": "urn:idtoken:acr:face-oob-high"
}

Where possible, IDToken maps to OIDC standard claims. Claims without a standard equivalent use IDToken-specific names:

CategoryStandard Claims UsedCustom Claims
Namegiven_name, family_name, name
Birthbirthdate
Photopicture
Nationalitynationality
Age verificationage_over_18, age_over_21, age_range
Trusttrust_level
Identityis_eu_citizen, name_initial
TypeBehaviorUse Case
publicsub = tokenId (same across all clients)Default; enables cross-service identity linking
pairwisesub = HMAC(tokenId, client_id)Privacy-preserving; different sub per client, preventing cross-service tracking

The subject type is configured per client registration.

OIDC clients (Relying Parties) are registered with the IDToken operator. Each client record defines:

FieldDescription
client_idUnique identifier for the client application
client_secretSecret for token endpoint authentication
redirect_urisAllowed callback URLs (strict matching)
allowed_scopesMaximum scopes this client can request
subject_typepublic or pairwise
id_token_signed_response_algES256 (default, ECDSA P-256)
token_endpoint_auth_methodclient_secret_basic or client_secret_post

OIDC scopes map directly to the IDToken selective disclosure system:

  • The openid scope is always required (returns sub)
  • Identity scopes (identity:name, identity:age_over_18, etc.) control which claims appear in the id_token and /oidc/userinfo response
  • The mobile app shows the consent screen with the requested scopes
  • The user can deny individual scopes — the id_token will only contain approved claims
  • Granted scopes are cryptographically bound to the user’s ECDSA signature
OIDC Standard ScopeMaps ToClaims Returned
openidsub
profileidentity:namegiven_name, family_name, name
emailNot available (VDS contains no email)

For identity claims beyond standard OIDC scopes, use IDToken’s native scopes (identity:age_over_18, identity:nationality, etc.) alongside openid.

The acr (Authentication Context Class Reference) claim in the id_token reflects the trust level:

Trust LevelACR Value
1 (self-issued)urn:idtoken:acr:face-oob-low
2 (operator-verified)urn:idtoken:acr:face-oob-substantial
3 (NFC + eIDAS)urn:idtoken:acr:face-oob-high

Clients can request a minimum ACR via the acr_values parameter in the authorization request.

The /oidc/userinfo endpoint returns identity claims for the authenticated user:

Terminal window
GET /oidc/userinfo
Authorization: Bearer {access_token}
{
"sub": "vds-token-uuid",
"given_name": "Jean",
"family_name": "Dupont",
"name": "Jean Dupont",
"birthdate": "1985-06-15",
"nationality": "FRA",
"age_over_18": true,
"trust_level": 3
}

The response contains only claims matching the scopes granted during authentication.

FeatureOIDCSAML
Token formatJWT (compact, JSON)XML assertion (verbose)
TransportJSON over HTTPSXML over HTTP POST
Discovery/.well-known/openid-configurationIdP metadata XML
Best forModern web/mobile apps, cloud servicesLegacy enterprise systems
SigningES256 (ECDSA P-256)RSA-SHA256 or ECDSA-SHA256
Selective disclosureNative (via scopes)Via attribute mapping

Both OIDC and SAML use the same underlying X.1280 authentication flow. The choice depends on what the relying party supports.