Skip to content

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.

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

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.

Wallet AppIDToken (Issuer)Mobile App1. Request credential (type + scopes)2. Login pageEnter tokenId3. X.1280 (OTP + face)4. Auth verified5. Build VCFilter claims + sign6. Verifiable Credential (vc+jwt)7. Stored in walletPresent anywhereCredential held
  1. A wallet or relying party requests a specific credential type with scopes
  2. IDToken authenticates the user via the standard X.1280 flow (OTP + mobile face verification)
  3. After authentication, IDToken builds a scope-filtered Verifiable Credential
  4. The signed VC is returned to the wallet for storage
  5. The user can present the credential to any verifier, online or offline

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:

PropertyValue
JWT header typvc+jwt
JWT header algES256 (ECDSA P-256)
issIssuer DID (did:web:auth.idtoken.id3.eu)
subHolder’s tokenId
jtiUnique credential identifier (UUID)
nbfIssuance timestamp
expExpiration timestamp
vcThe Verifiable Credential claim object

The vc claim contains the W3C-compliant credential structure with @context, type, credentialSubject, evidence, and credentialStatus.

IDToken supports three credential types, each mapping to the existing scope system:

Credential TypeScopes UsedClaims in credentialSubject
IDTokenIdentityCredentialidentity:fullgivenName, familyName, dateOfBirth, nationality, documentNumber, trustLevel
IDTokenAgeVerificationidentity:age_verificationageOver18, givenName, familyName
IDTokenBasicIdentityidentity:basicgivenName, 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.

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"
}]
}
}

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 FieldDescription
typeVisibleDigitalSeal — the credential source
standardISO 22376 — the VDS international standard
verificationMethodECDSA-P256 — the signature algorithm used to verify the VDS
schemeOperatorThe scheme operator that governs the issuing CA (e.g., Otentik)
manifestIdThe 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.

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 FieldValue
typeBitstringStatusListEntry
statusPurposerevocation
statusListIndexThe credential’s position in the bitstring
statusListCredentialURL 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.

IDToken uses a did:web Decentralized Identifier as the VC issuer:

did:web:auth.idtoken.id3.eu

The 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
{
"@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"]
}

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:full for IDTokenIdentityCredential)
  • 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 credentialSubject will 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).

FeatureVerifiable CredentialsOIDCSAML
Token formatJWT-VC (vc+jwt)JWT (id_token)XML assertion
StandardW3C VC Data Model 2.0OpenID Connect CoreSAML 2.0
Holder storageWallet app (persistent)Browser sessionBrowser session
Offline verificationYes (signature + cached status list)No (requires token endpoint)No (requires IdP metadata)
Selective disclosureVia scopes → credentialSubjectVia scopes → claimsVia attribute mapping
Issuer identityDID (did:web:)HTTPS issuer URLSAML Entity ID
SigningES256 (ECDSA P-256)ES256 (ECDSA P-256)RSA-SHA256 or ECDSA
RevocationBitstring Status ListToken expiryAssertion expiry
Best forDigital wallets, eIDAS 2.0, offlineCloud services, modern web appsEnterprise 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.

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.