Verifiable Credentials
IDToken can issue W3C Verifiable Credentials (VCs) — standardized, cryptographically signed identity assertions that digital wallets can store, present, and verify independently. The VDS remains the root-of-trust; the VC is a standards-compliant wrapper that makes IDToken identity portable across the emerging credential ecosystem.
Why Verifiable Credentials?
Section titled “Why Verifiable Credentials?”IDToken already issues signed JWTs with identity claims — Verifiable Credentials formalize this into the W3C standard that the digital wallet ecosystem is converging on. While direct JWT integration and OpenID Connect work well for web applications, VCs enable:
- Digital wallet storage — users hold their credentials in wallet apps (EUDIW, Google Wallet, Apple Wallet) and present them on demand
- Offline verification — verifiers can check a VC’s signature and status without contacting the issuer in real time
- Selective disclosure — leverages the existing IDToken scope system to issue credentials with only the claims the user consents to share
- eIDAS 2.0 interoperability — the European Digital Identity Wallet (EUDIW) regulation mandates VC-based identity; IDToken VCs are ready for this ecosystem
- Cross-border recognition — VCs issued from a government-anchored VDS carry trust internationally, backed by the ISO 22385 PKI chain
Architecture
Section titled “Architecture”The VC issuance layer sits on top of the existing X.1280 authentication flow, just as OIDC and SAML do. The same OTP + mobile face verification produces a Verifiable Credential instead of (or in addition to) a JWT or SAML assertion.
- A wallet or relying party requests a specific credential type with scopes
- IDToken authenticates the user via the standard X.1280 flow (OTP + mobile face verification)
- After authentication, IDToken builds a scope-filtered Verifiable Credential
- The signed VC is returned to the wallet for storage
- The user can present the credential to any verifier, online or offline
Credential Format
Section titled “Credential Format”IDToken issues VCs in JWT-VC format (vc+jwt) as defined by the W3C Verifiable Credentials Data Model 2.0. This format is a JWT with:
| Property | Value |
|---|---|
JWT header typ | vc+jwt |
JWT header alg | ES256 (ECDSA P-256) |
iss | Issuer DID (did:web:auth.idtoken.id3.eu) |
sub | Holder’s tokenId |
jti | Unique credential identifier (UUID) |
nbf | Issuance timestamp |
exp | Expiration timestamp |
vc | The Verifiable Credential claim object |
The vc claim contains the W3C-compliant credential structure with @context, type, credentialSubject, evidence, and credentialStatus.
Credential Types
Section titled “Credential Types”IDToken supports three credential types, each mapping to the existing scope system:
| Credential Type | Scopes Used | Claims in credentialSubject |
|---|---|---|
IDTokenIdentityCredential | identity:full | givenName, familyName, dateOfBirth, nationality, documentNumber, trustLevel |
IDTokenAgeVerification | identity:age_verification | ageOver18, givenName, familyName |
IDTokenBasicIdentity | identity:basic | givenName, familyName, trustLevel |
The credential type determines which claims appear in the credentialSubject. Just like IDToken’s other integration methods, users see a consent screen on their mobile app and can deny individual scopes.
Example Credential
Section titled “Example Credential”A decoded IDTokenIdentityCredential JWT-VC payload:
{ "iss": "did:web:auth.idtoken.id3.eu", "sub": "vds-token-uuid", "jti": "urn:uuid:3f8c9a7e-1b2d-4e5f-a6b8-c9d0e1f2a3b4", "nbf": 1711324800, "exp": 1711411200, "vc": { "@context": [ "https://www.w3.org/ns/credentials/v2", "https://idtoken.id3.eu/ns/credentials/v1" ], "type": ["VerifiableCredential", "IDTokenIdentityCredential"], "credentialSubject": { "id": "vds-token-uuid", "givenName": "Jean", "familyName": "Dupont", "dateOfBirth": "1985-06-15", "nationality": "FRA", "documentNumber": "12AB34567", "trustLevel": 3 }, "evidence": [{ "type": "VisibleDigitalSeal", "standard": "ISO 22376", "verificationMethod": "ECDSA-P256", "schemeOperator": "Otentik", "manifestId": "0A1B2C" }], "credentialStatus": { "id": "https://auth.idtoken.id3.eu/credentials/status#1234", "type": "BitstringStatusListEntry", "statusPurpose": "revocation", "statusListIndex": "1234", "statusListCredential": "https://auth.idtoken.id3.eu/credentials/status" } }}An IDTokenAgeVerification credential contains only the minimum claims needed:
{ "iss": "did:web:auth.idtoken.id3.eu", "sub": "vds-token-uuid", "jti": "urn:uuid:a1b2c3d4-e5f6-7890-abcd-ef1234567890", "nbf": 1711324800, "exp": 1711411200, "vc": { "@context": [ "https://www.w3.org/ns/credentials/v2", "https://idtoken.id3.eu/ns/credentials/v1" ], "type": ["VerifiableCredential", "IDTokenAgeVerification"], "credentialSubject": { "id": "vds-token-uuid", "ageOver18": true, "givenName": "Jean", "familyName": "Dupont" }, "evidence": [{ "type": "VisibleDigitalSeal", "standard": "ISO 22376", "verificationMethod": "ECDSA-P256", "schemeOperator": "Otentik" }] }}VDS as Evidence
Section titled “VDS as Evidence”Every IDToken VC includes an evidence field that references the Visible Digital Seal verification performed during authentication. This is what makes IDToken VCs fundamentally different from self-asserted credentials:
| Evidence Field | Description |
|---|---|
type | VisibleDigitalSeal — the credential source |
standard | ISO 22376 — the VDS international standard |
verificationMethod | ECDSA-P256 — the signature algorithm used to verify the VDS |
schemeOperator | The scheme operator that governs the issuing CA (e.g., Otentik) |
manifestId | The VDS manifest identifier, linking to the credential schema definition |
The evidence chain establishes that the identity claims originate from a government-issued passport, verified through the ISO 22385 PKI trust chain, not from a user-declared account.
Credential Status
Section titled “Credential Status”IDToken uses the W3C Bitstring Status List for credential revocation. Each issued credential receives a unique index in a published bitstring. When an enrollment is revoked, the corresponding bits are flipped and the status list is updated.
| Status Field | Value |
|---|---|
type | BitstringStatusListEntry |
statusPurpose | revocation |
statusListIndex | The credential’s position in the bitstring |
statusListCredential | URL of the published status list |
The status list is itself a Verifiable Credential (a signed JWT containing the gzipped bitstring), published at a well-known URL. Verifiers fetch and cache it to check revocation status without contacting the issuer for each verification.
Issuer Identity
Section titled “Issuer Identity”IDToken uses a did:web Decentralized Identifier as the VC issuer:
did:web:auth.idtoken.id3.euThe DID resolves to a DID document published at /.well-known/did.json, which contains the same ECDSA P-256 public key already exposed at /.well-known/jwks.json. This means:
- Verifiers resolve the issuer DID by fetching the DID document over HTTPS
- The verification key in the DID document matches the key used to sign the VC
- Key rotation is handled by updating the DID document (same as JWKS rotation)
- No blockchain or distributed ledger is required — trust is anchored in DNS + TLS + the VDS PKI chain
DID Document
Section titled “DID Document”{ "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/jws-2020/v1" ], "id": "did:web:auth.idtoken.id3.eu", "verificationMethod": [{ "id": "did:web:auth.idtoken.id3.eu#key-1", "type": "JsonWebKey2020", "controller": "did:web:auth.idtoken.id3.eu", "publicKeyJwk": { "kty": "EC", "crv": "P-256", "x": "...", "y": "...", "kid": "...", "use": "sig", "alg": "ES256" } }], "assertionMethod": ["did:web:auth.idtoken.id3.eu#key-1"], "authentication": ["did:web:auth.idtoken.id3.eu#key-1"]}Selective Disclosure
Section titled “Selective Disclosure”VC issuance uses the same scope-based selective disclosure system as all other IDToken integration methods:
- The credential type defines required scopes (e.g.,
identity:fullforIDTokenIdentityCredential) - Required scopes expand to atomic scopes, which map to specific claims
- The user’s mobile app shows the consent screen with the requested scopes
- The user can deny individual scopes — the
credentialSubjectwill only contain approved claims - Granted scopes are cryptographically bound to the user’s ECDSA signature during authentication
Derived claims like ageOver18 and isEuCitizen are particularly valuable in VCs — they prove a predicate (e.g., “this person is over 18”) without revealing the underlying data (the actual date of birth).
Comparison with OIDC and SAML
Section titled “Comparison with OIDC and SAML”| Feature | Verifiable Credentials | OIDC | SAML |
|---|---|---|---|
| Token format | JWT-VC (vc+jwt) | JWT (id_token) | XML assertion |
| Standard | W3C VC Data Model 2.0 | OpenID Connect Core | SAML 2.0 |
| Holder storage | Wallet app (persistent) | Browser session | Browser session |
| Offline verification | Yes (signature + cached status list) | No (requires token endpoint) | No (requires IdP metadata) |
| Selective disclosure | Via scopes → credentialSubject | Via scopes → claims | Via attribute mapping |
| Issuer identity | DID (did:web:) | HTTPS issuer URL | SAML Entity ID |
| Signing | ES256 (ECDSA P-256) | ES256 (ECDSA P-256) | RSA-SHA256 or ECDSA |
| Revocation | Bitstring Status List | Token expiry | Assertion expiry |
| Best for | Digital wallets, eIDAS 2.0, offline | Cloud services, modern web apps | Enterprise SSO, legacy systems |
All three methods use the same underlying X.1280 authentication flow. The choice depends on the consuming system’s capabilities and requirements.
OID4VCI Compatibility
Section titled “OID4VCI Compatibility”IDToken publishes credential issuer metadata at /.well-known/openid-credential-issuer, following the OpenID for Verifiable Credential Issuance (OID4VCI) specification. This allows OID4VCI-compatible wallets to discover:
- Which credential types are available
- The supported format (
jwt_vc_json) - The cryptographic suites supported (
ES256) - The credential endpoint URL
{ "credential_issuer": "https://auth.idtoken.id3.eu", "credential_endpoint": "https://auth.idtoken.id3.eu/credentials/issue", "credentials_supported": [ { "format": "jwt_vc_json", "types": ["VerifiableCredential", "IDTokenIdentityCredential"], "cryptographic_binding_methods_supported": ["did:web"], "cryptographic_suites_supported": ["ES256"], "display": [{ "name": "IDToken Identity Credential", "description": "Full identity credential backed by a government-issued VDS", "locale": "en" }] }, { "format": "jwt_vc_json", "types": ["VerifiableCredential", "IDTokenAgeVerification"], "cryptographic_binding_methods_supported": ["did:web"], "cryptographic_suites_supported": ["ES256"], "display": [{ "name": "IDToken Age Verification", "description": "Age verification credential (over 18) without revealing date of birth", "locale": "en" }] }, { "format": "jwt_vc_json", "types": ["VerifiableCredential", "IDTokenBasicIdentity"], "cryptographic_binding_methods_supported": ["did:web"], "cryptographic_suites_supported": ["ES256"], "display": [{ "name": "IDToken Basic Identity", "description": "Minimal identity credential with name and trust level", "locale": "en" }] } ]}This metadata endpoint enables progressive adoption: wallets can discover IDToken as an issuer today, and full OID4VCI protocol support (pre-authorized code flow, credential offers, deferred issuance) can be added incrementally.