---
url: 'https://www.corbado.com/fr/blog/comment-construire-verificateur-credentials-verifiables'
title: 'Comment construire un vérificateur d''identifiants numériques (Guide du développeur)'
description: 'Apprenez à construire un vérificateur d''identifiants numériques de A à Z avec Next.js, OpenID4VP et ISO mDoc. Ce guide pas à pas pour les développeurs montre comment créer un vérificateur capable de demander, recevoir et valider des permis de conduire mob'
lang: 'fr'
author: 'Amine'
date: '2025-08-20T15:40:10.087Z'
lastModified: '2026-03-27T07:05:51.239Z'
keywords: 'vérificateur d''identifiants numériques, tutoriel vérificateur, construire un vérificateur'
category: 'Digital Credentials'
---

# Comment construire un vérificateur d'identifiants numériques (Guide du développeur)

## 1. Introduction

Prouver son identité en ligne est un défi constant. Cela nous conduit à dépendre des mots
de passe et à partager des documents sensibles sur des canaux non sécurisés. Pour les
entreprises, la vérification d'identité est devenue un processus lent,
[co](https://www.corbado.com/fr/blog/conformite-cybersecurite)ûteux et sujet à la fraude. Les identifiants
numériques (Digital Credentials) offrent une nouvelle approche qui redonne aux
utilisateurs le contrôle de leurs données. Ils sont l'équivalent numérique d'un
[portefeuille](https://www.corbado.com/fr/blog/garantie-portefeuille-numerique) physique, contenant tout, d'un
permis de conduire à un diplôme universitaire, avec les avantages supplémentaires d'être
sécurisés par cryptographie, de préserver la confidentialité et d'être vérifiables
instantanément.

Ce guide propose aux développeurs un
[tutoriel](https://www.corbado.com/fr/blog/application-crud-react-nodejs-express-mysql) pratique et détaillé pour
construire un vérificateur d'[identifiants numériques](https://www.corbado.com/fr/blog/digital-credentials-api).
Bien que les standards existent, il y a peu de documentation sur leur mise en œuvre. Ce
[tutoriel](https://www.corbado.com/fr/blog/application-crud-react-nodejs-express-mysql) comble cette lacune en
montrant comment construire un vérificateur en utilisant l'API native Digital Credential
du navigateur, [OpenID4VP](https://www.corbado.com/glossary/open-id-4-vp) pour le protocole de présentation, et
le format ISO [mDoc](https://www.corbado.com/glossary/mdoc) (par exemple, pour un
[permis de conduire mobile](https://www.corbado.com/fr/blog/permis-de-conduire-mobile)) comme format
d'identifiant.

Le résultat final sera une application [Next.js](https://www.corbado.com/blog/nextjs-passkeys) simple mais
fonctionnelle, capable de demander, recevoir et vérifier un identifiant numérique à partir
d'un [portefeuille](https://www.corbado.com/fr/blog/garantie-portefeuille-numerique) mobile compatible.

Voici un aperçu rapide de l'application finale en action. Le processus se déroule en
quatre étapes principales :

**Étape 1 : Page initiale** L'utilisateur arrive sur la page initiale et clique sur «
Vérifier avec l'[identité numérique](https://www.corbado.com/fr/glossary/openid-4-vp) » pour lancer le processus.
![Page initiale pour la demande de vérification](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/Screenshot_2025_07_25_at_11_00_33_5217b35c96.png)

**Étape 2 : Demande de confiance** Le navigateur demande à l'utilisateur de confirmer sa
confiance. L'utilisateur clique sur « Continuer » pour poursuivre.
![Fenêtre de demande de confiance du navigateur](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/Screenshot_2025_07_25_at_11_00_39_ba390a8097.png)

**Étape 3 : Scan du QR Code** Un [QR code](https://www.corbado.com/blog/qr-code-login-authentication) est
affiché, que l'utilisateur scanne avec son application de
[portefeuille](https://www.corbado.com/fr/blog/garantie-portefeuille-numerique) compatible.
![QR code à scanner](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/Screenshot_2025_07_25_at_11_00_45_3b30669a10.png)

**Étape 4 : Identifiant décodé** Après une vérification réussie, l'application affiche les
données de l'identifiant décodé.
![Résultat de l'identifiant décodé](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/Screenshot_2025_07_25_at_11_01_36_684f7489cd.png)

### 1.1 Comment ça marche

La magie des [identifiants numériques](https://www.corbado.com/fr/blog/digital-credentials-api) repose sur un
modèle simple mais puissant de « **triangle de confiance** » impliquant trois acteurs clés
:

- **Émetteur :** Une autorité de confiance (par exemple, une agence
  [gouvernementale](https://www.corbado.com/passkeys-for-public-sector), une université ou une banque) qui signe
  cryptographiquement et émet un identifiant pour un utilisateur.
- **Titulaire :** L'utilisateur, qui reçoit l'identifiant et le stocke en toute sécurité
  dans un [portefeuille numérique](https://www.corbado.com/fr/blog/garantie-portefeuille-numerique) personnel sur
  son appareil.
- **Vérificateur :** Une application ou un service qui doit contrôler l'identifiant de
  l'utilisateur.

![Écosystème des identifiants vérifiables du W3C](https://www.w3.org/TR/vc-data-model/diagrams/ecosystem.svg)

Lorsqu'un utilisateur souhaite accéder à un service, il présente l'identifiant depuis son
portefeuille. Le vérificateur peut alors instantanément contrôler son authenticité sans
avoir besoin de contacter directement l'émetteur d'origine.

### 1.2 Pourquoi les vérificateurs sont essentiels (et pourquoi nous sommes ici)

Pour que cet **écosystème d'identité décentralisée** puisse prospérer, le rôle du
**vérificateur** est absolument crucial. Ils sont les gardiens de cette nouvelle
infrastructure de confiance, ceux qui consomment les identifiants et les rendent utiles
dans le monde réel. Comme l'illustre le schéma ci-dessous, un vérificateur complète le
triangle de confiance en demandant, recevant et validant un identifiant auprès du
titulaire.

Si vous êtes développeur, construire un service pour effectuer cette vérification est une
compétence fondamentale pour la prochaine génération d'applications sécurisées et centrées
sur l'utilisateur. Ce guide est conçu pour vous accompagner précisément dans ce processus.
Nous couvrirons tout ce que vous devez savoir pour **construire votre propre vérificateur
d'identifiants vérifiables**, des concepts et standards de base aux détails de mise en
œuvre pas à pas pour valider les signatures et vérifier le statut des identifiants.

> **Vous voulez aller plus vite ?** Vous pouvez trouver le projet complet de ce
> [tutoriel](https://www.corbado.com/fr/blog/application-crud-react-nodejs-express-mysql) sur GitHub. N'hésitez
> pas à le cloner et à l'essayer vous-même :
> [https://github.com/corbado/digital-credentials-example](https://github.com/corbado/digital-credentials-example)

C'est parti.

## 2. Prérequis pour construire un vérificateur

Avant de commencer, assurez-vous d'avoir :

1. **Compréhension de base des identifiants numériques et du mdoc**
    - Ce tutoriel se concentre sur le format **ISO mDoc** (par exemple, pour les permis de
      conduire mobiles) et ne couvre pas d'autres formats comme les identifiants
      vérifiables (VCs) du W3C. Une familiarité avec les concepts de base du
      [mdoc](https://www.corbado.com/glossary/mdoc) sera utile.
2. **Docker et Docker Compose**
    - Notre projet utilise une base de données
      [MySQL](https://www.corbado.com/blog/passkey-webauthn-database-guide) dans un conteneur Docker pour gérer
      l'état de la session OIDC. Assurez-vous que les deux sont installés et en cours
      d'exécution.
3. **Protocole choisi : OpenID4VP**
    - Nous utiliserons le protocole **OpenID4VP** (OpenID for Verifiable Presentations)
      pour le flux d'échange d'identifiants.
4. **Stack technique prête**
    - Utilisation de **TypeScript** (Node.js) pour la logique backend.
    - Utilisation de **Next.js** pour le backend (API routes) et le frontend (UI).
    - Bibliothèques clés : des bibliothèques de décodage [CBOR](https://www.corbado.com/glossary/cbor) pour
      l'analyse du [mdoc](https://www.corbado.com/glossary/mdoc) et un client
      [MySQL](https://www.corbado.com/blog/passkey-webauthn-database-guide).
5. **Identifiants de test et portefeuille**
    - Nous utiliserons le
      **[CMWallet](https://github.com/digitalcredentialsdev/CMWallet/actions/runs/16407676816/artifacts/3574255220)**
      pour [Android](https://www.corbado.com/blog/how-to-enable-passkeys-android), qui comprend les requêtes
      [OpenID4VP](https://www.corbado.com/glossary/open-id-4-vp) et peut présenter des identifiants mdoc.
6. **Connaissances de base en cryptographie**
    - Comprendre les signatures numériques et les concepts de clé publique/privée tels
      qu'ils s'appliquent au mdoc et aux flux OIDC.

---

Nous allons maintenant examiner en détail chacun de ces prérequis, en commençant par les
standards et les protocoles qui sous-tendent ce vérificateur basé sur le mdoc.

### 2.1 Choix des protocoles

Notre vérificateur est construit pour les éléments suivants :

| Standard / Protocole                                                                      | Description                                                                                                                                                                                                                                |
| :---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **[W3C VC](https://www.w3.org/TR/vc-data-model/)**                                        | Le modèle de données des identifiants vérifiables du W3C. Il définit la structure standard des identifiants numériques, y compris les déclarations (claims), les métadonnées et les preuves.                                               |
| **[SD-JWT](https://datatracker.ietf.org/doc/draft-ietf-oauth-selective-disclosure-jwt/)** | Divulgation sélective pour les JWT. Un format pour les VCs basé sur les JSON Web Tokens qui permet aux titulaires de ne divulguer que certaines déclarations d'un identifiant, améliorant ainsi la confidentialité.                        |
| **[ISO mDoc](https://www.iso.org/standard/69084.html)**                                   | ISO/IEC 18013-5. Le standard international pour les permis de conduire mobiles (mDL) et autres identifiants mobiles, définissant les structures de données et les protocoles de communication pour une utilisation en ligne et hors ligne. |
| **OpenID4VP**                                                                             | OpenID for Verifiable Presentations. Un protocole de présentation interopérable basé sur OAuth 2.0. Il définit comment un vérificateur demande des identifiants et comment le portefeuille d'un titulaire les présente.                    |

Pour ce tutoriel, nous utilisons spécifiquement :

- **OpenID4VP** comme protocole pour demander et recevoir les identifiants.
- **ISO mDoc** comme format d'identifiant (par exemple, pour les permis de conduire
  mobiles).

> **Note sur le périmètre :** Bien que nous introduisions brièvement les W3C VC et
> SD-[JWT](https://www.corbado.com/fr/glossary/jwks) pour fournir un contexte plus large, ce tutoriel met en
> œuvre exclusivement les identifiants ISO mDoc via [OpenID4VP](https://www.corbado.com/glossary/open-id-4-vp).
> Les VCs basés sur le W3C sont hors du champ de cet exemple.

#### 2.1.1 ISO mDoc (Mobile Document)

La norme ISO/IEC 18013-5 mDoc définit la structure et l'encodage des documents mobiles
tels que les permis de conduire mobiles (mDL). Les identifiants mDoc sont encodés en
[CBOR](https://www.corbado.com/glossary/cbor), signés cryptographiquement et peuvent être présentés numériquement
pour vérification. Notre vérificateur se concentrera sur le décodage et la validation de
ces identifiants mdoc.

#### 2.1.2 OpenID4VP (OpenID for Verifiable Presentations)

OpenID4VP est un protocole interopérable pour demander et présenter des identifiants
numériques, construit sur [OAuth 2.0](https://www.corbado.com/glossary/oauth2) et OpenID Connect. Dans cette
implémentation, OpenID4VP est utilisé pour :

- Lancer le flux de présentation de l'identifiant (via un
  [QR code](https://www.corbado.com/blog/qr-code-login-authentication) ou une API de navigateur)
- Recevoir l'identifiant mdoc du portefeuille de l'utilisateur
- Assurer un échange d'identifiants sécurisé, avec état et respectueux de la vie privée

### 2.2 Choix de la stack technique

Maintenant que nous avons une compréhension claire des standards et des protocoles, nous
devons choisir la bonne stack technique pour construire notre vérificateur. Nos choix sont
conçus pour la robustesse, l'expérience de développement et la compatibilité avec
l'écosystème web moderne.

#### 2.2.1 Langage : TypeScript

Nous utiliserons **TypeScript** pour notre code frontend et backend. En tant que
sur-ensemble de JavaScript, il ajoute un typage statique, ce qui aide à détecter les
erreurs tôt, améliore la qualité du code et facilite la gestion d'applications complexes.
Dans un contexte sensible à la sécurité comme la vérification d'identifiants, la sécurité
des types est un avantage considérable.

#### 2.2.2 Framework : Next.js

**Next.js** est notre framework de choix car il offre une expérience intégrée et
transparente pour la création d'applications
[full-stack](https://www.corbado.com/fr/blog/application-crud-react-nodejs-express-mysql).

- **Pour le Frontend :** Nous utiliserons [Next.js](https://www.corbado.com/blog/nextjs-passkeys) avec
  [React](https://www.corbado.com/blog/react-passkeys) pour construire l'interface utilisateur où le processus de
  vérification est initié (par exemple, en affichant un QR code).
- **Pour le Backend :** Nous tirerons parti des **API Routes de Next.js** pour créer les
  points de terminaison côté serveur. Ces points de terminaison sont responsables de la
  création de requêtes OpenID4VP valides et d'agir en tant que `redirect_uri` pour
  recevoir et vérifier en toute sécurité la réponse finale du CMWallet.

#### 2.2.3 Bibliothèques clés

Notre implémentation repose sur un ensemble spécifique de bibliothèques pour le frontend
et le backend :

- **next** : Le framework [Next.js](https://www.corbado.com/blog/nextjs-passkeys), utilisé à la fois pour les
  routes API du backend et l'interface utilisateur du frontend.
- **react** et **react-dom** : Alimentent l'interface utilisateur du frontend.
- **cbor-web** : Utilisé pour décoder les identifiants mdoc encodés en
  [CBOR](https://www.corbado.com/glossary/cbor) en objets JavaScript utilisables.
- **mysql2** : Fournit la connectivité à la base de données
  [MySQL](https://www.corbado.com/blog/passkey-webauthn-database-guide) pour stocker les challenges et les
  sessions de vérification.
- **uuid** : Une bibliothèque pour générer des chaînes de challenge uniques (nonces).
- **@types/uuid** : Types TypeScript pour la génération d'UUID.

> **Note sur `openid-client` :** Des vérificateurs plus avancés et prêts pour la
> production pourraient utiliser la bibliothèque `openid-client` pour gérer directement le
> protocole OpenID4VP sur le backend, permettant des fonctionnalités comme un
> `redirect_uri` dynamique. Dans un flux OpenID4VP piloté par le serveur avec un
> `redirect_uri`, `openid-client` serait utilisé pour analyser et valider directement les
> réponses `vp_token`. Pour ce tutoriel, nous utilisons un flux plus simple, médiatisé par
> le navigateur, qui ne le nécessite pas, rendant le processus plus facile à comprendre.

Cette stack technique garantit une implémentation de vérificateur robuste, typée et
évolutive, axée sur l'API Digital Credential du navigateur et le format d'identifiant ISO
mDoc.

### 2.3 Obtenir un portefeuille et des identifiants de test

Pour tester votre vérificateur, vous avez besoin d'un portefeuille mobile capable
d'interagir avec l'API Digital Credential du navigateur.

Nous utiliserons le
**[CMWallet](https://github.com/digitalcredentialsdev/CMWallet/actions/runs/16407676816/artifacts/3574255220)**,
un portefeuille de test robuste et conforme à OpenID4VP pour
[Android](https://www.corbado.com/blog/how-to-enable-passkeys-android).

**Comment installer CMWallet (Android) :**

1. **Téléchargez le fichier APK** en utilisant le lien ci-dessus directement sur votre
   appareil [Android](https://www.corbado.com/blog/how-to-enable-passkeys-android).
2. Ouvrez les **Paramètres > Sécurité** de votre appareil.
3. Activez **« Installer des applications inconnues »** pour le navigateur que vous avez
   utilisé pour télécharger le fichier.
4. Localisez l'APK téléchargé dans votre dossier « Téléchargements » et appuyez dessus
   pour commencer l'installation.
5. Suivez les instructions à l'écran pour terminer l'installation.
6. Ouvrez CMWallet, et vous le trouverez pré-chargé avec des identifiants de test, prêt
   pour le flux de vérification.

> **Note :** N'installez des fichiers APK que de sources que vous jugez fiables. Le lien
> fourni provient du dépôt officiel du projet.

### 2.4 Connaissances en cryptographie

Avant de nous plonger dans l'implémentation, il est essentiel de comprendre les concepts
cryptographiques qui sous-tendent les identifiants vérifiables. C'est ce qui les rend «
vérifiables » et dignes de confiance.

#### 2.4.1 Les signatures numériques : le fondement de la confiance

Au fond, un identifiant vérifiable est un ensemble de déclarations (comme le nom, la date
de naissance, etc.) qui a été signé numériquement par un émetteur. Une signature numérique
offre deux garanties essentielles :

- **Authenticité :** Elle prouve que l'identifiant a bien été créé par l'émetteur et non
  par un imposteur.
- **Intégrité :** Elle prouve que l'identifiant n'a pas été modifié ou altéré depuis sa
  signature.

#### 2.4.2 Cryptographie à clé publique/privée

Les signatures numériques sont créées à l'aide de la cryptographie à clé publique/privée
(également appelée cryptographie asymétrique). Voici comment cela fonctionne dans notre
contexte :

1. **L'émetteur possède une paire de clés :** une clé privée, qui est gardée secrète, et
   une clé publique, qui est mise à la disposition de tous (généralement via son document
   DID).
2. **Signature :** Lorsqu'un émetteur crée un identifiant, il utilise sa **clé privée**
   pour générer une signature numérique unique pour les données spécifiques de cet
   identifiant.
3. **Vérification :** Lorsque notre vérificateur reçoit l'identifiant, il utilise la **clé
   publique** de l'émetteur pour vérifier la signature. Si la vérification réussit, le
   vérificateur sait que l'identifiant est authentique et n'a pas été altéré. Toute
   modification des données de l'identifiant invaliderait la signature.

> **Note sur les DID :** Dans ce tutoriel, nous ne résolvons pas les clés de l'émetteur
> via les DID. En production, les émetteurs exposeraient généralement leurs clés publiques
> via des DID ou d'autres points de terminaison faisant autorité, que le vérificateur
> utiliserait pour la validation cryptographique.

#### 2.4.3 Les identifiants vérifiables en tant que JWT

Les identifiants vérifiables sont souvent formatés en tant que **JSON Web Tokens (JWT)**.
Un [JWT](https://www.corbado.com/fr/glossary/jwks) est un moyen compact et sûr pour les URL de représenter des
déclarations à transférer entre deux parties. Un [JWT](https://www.corbado.com/fr/glossary/jwks) signé (également
connu sous le nom de JWS) se compose de trois parties séparées par des points (`.`) :

- **En-tête :** Contient des métadonnées sur le token, comme l'algorithme de signature
  utilisé (`alg`).
- **Charge utile (Payload) :** Contient les déclarations réelles de l'identifiant
  vérifiable (la déclaration `vc`), y compris l'`issuer`, le `credentialSubject`, etc.
- **Signature :** La signature numérique générée par l'émetteur, qui couvre l'en-tête et
  la charge utile.

```
// Exemple de la structure d'un JWT
[En-tête].[Charge utile].[Signature]
```

> **Note :** Les identifiants vérifiables basés sur JWT sont hors du champ de cet article
> de blog. Cette implémentation se concentre sur les identifiants ISO mDoc et OpenID4VP,
> et non sur les identifiants vérifiables W3C ou les identifiants basés sur JWT.

#### 2.4.4 La présentation vérifiable : prouver la possession

Il ne suffit pas qu'un vérificateur sache qu'un identifiant est valide ; il doit également
savoir que la personne qui _présente_ l'identifiant en est le titulaire légitime. Cela
empêche quelqu'un d'utiliser un identifiant volé.

Ce problème est résolu à l'aide d'une **présentation vérifiable (VP)**. Une VP est une
enveloppe autour d'un ou plusieurs VCs qui est **signée par le titulaire lui-même**.

Le flux est le suivant :

1. Le vérificateur demande à l'utilisateur de présenter un identifiant.
2. Le portefeuille de l'utilisateur crée une présentation vérifiable, y regroupe le(s)
   identifiant(s) requis, et signe l'ensemble de la présentation en utilisant la **clé
   privée du titulaire**.
3. Le portefeuille envoie cette VP signée au vérificateur.

Notre vérificateur doit alors effectuer **deux** vérifications de signature distinctes :

1. **Vérifier le(s) identifiant(s) :** Vérifier la signature de chaque VC à l'intérieur de
   la présentation en utilisant la **clé publique de l'émetteur**. (Prouve que
   l'identifiant est authentique).
2. **Vérifier la présentation :** Vérifier la signature de la VP elle-même en utilisant la
   **clé publique du titulaire**. (Prouve que la personne qui la présente en est le
   propriétaire).

Cette double vérification garantit à la fois l'authenticité de l'identifiant et l'identité
de la personne qui le présente, créant ainsi un modèle de confiance robuste et sécurisé.

> **Note :** Le concept de [présentations vérifiables](https://www.corbado.com/fr/glossary/openid-4-vp) tel que
> défini dans l'écosystème W3C VC est hors du champ de cet article de blog. Le terme
> présentation vérifiable fait ici référence à la réponse `vp_token` d'OpenID4VP, qui se
> comporte de manière similaire à une VP du W3C mais est basée sur la sémantique ISO mDoc
> plutôt que sur le modèle de signature [JSON-LD](https://www.corbado.com/glossary/json-ld) du W3C. Ce guide se
> concentre sur les identifiants ISO mDoc et OpenID4VP, et non sur les présentations
> vérifiables W3C ou la validation de leur signature.

## 3. Vue d'ensemble de l'architecture

Notre architecture de vérificateur utilise l'**API Digital Credential** intégrée au
navigateur comme intermédiaire sécurisé pour connecter notre
[application web](https://www.corbado.com/fr/blog/application-crud-react-nodejs-express-mysql) au **CMWallet**
mobile de l'utilisateur. Cette approche simplifie le flux en laissant le navigateur gérer
l'affichage natif du [QR code](https://www.corbado.com/blog/qr-code-login-authentication) et la communication
avec le portefeuille.

- **Frontend (Next.js & React) :** Un site web léger destiné à l'utilisateur. Son rôle est
  de récupérer un objet de requête de notre backend, de le transmettre à l'API
  `navigator.credentials.get()` du navigateur, de recevoir le résultat et de le
  transmettre à notre backend pour vérification.
- **Backend (API Routes de Next.js) :** Le cœur du vérificateur. Il génère un objet de
  requête valide pour l'API du navigateur et expose un point de terminaison pour recevoir
  la présentation de l'identifiant depuis le frontend pour la validation finale.
- **Navigateur (Credential API) :** Le facilitateur. Il reçoit l'objet de requête de notre
  frontend, comprend le protocole `openid4vp` et génère nativement un QR code. Il attend
  ensuite que le portefeuille renvoie une réponse.
- **CMWallet (Application mobile) :** Le portefeuille de l'utilisateur. Il scanne le QR
  code, traite la requête, obtient le consentement de l'utilisateur et renvoie la réponse
  signée au navigateur.

Voici un diagramme de séquence illustrant le flux complet et précis :

![Flux de vérification utilisant l'API Digital Credentials du navigateur](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/Mermaid_Chart_Create_complex_visual_diagrams_with_text_A_smarter_way_of_creating_diagrams_2025_07_24_233623_1b6ed9b957.svg)

**Explication du flux :**

1. **Initiation :** L'utilisateur clique sur le bouton « Vérifier » sur notre
   **Frontend**.
2. **Objet de requête :** Le frontend appelle notre **Backend** (`/api/verify/start`), qui
   génère un objet de requête contenant la requête (query) et un nonce, puis le renvoie.
3. **Appel à l'API du navigateur :** Le frontend appelle `navigator.credentials.get()`
   avec l'objet de requête.
4. **QR code natif :** Le **Navigateur** voit la requête de protocole `openid4vp` et
   affiche nativement un QR code. La promesse `.get()` est maintenant en attente.

> **Note :** Ce flux de QR code se produit sur les navigateurs de bureau. Sur les
> navigateurs mobiles (Android Chrome avec un flag expérimental activé), le navigateur
> peut communiquer directement avec les portefeuilles compatibles sur le même appareil,
> éliminant ainsi le besoin de scanner un QR code. Pour activer cette fonctionnalité sur
> Android Chrome, accédez à `chrome://flags#web-identity-digital-credentials` et activez
> le flag.

5. **Scan et présentation :** L'utilisateur scanne le QR code avec le **CMWallet**. Le
   portefeuille obtient l'approbation de l'utilisateur et renvoie la présentation
   vérifiable au navigateur.
6. **Résolution de la promesse :** Le navigateur reçoit la réponse, et la promesse
   `.get()` initiale sur le frontend se résout enfin, livrant la charge utile de la
   présentation.
7. **Vérification par le backend :** Le frontend envoie par **POST** la charge utile de la
   présentation au point de terminaison `/api/verify/finish` de notre backend. Le backend
   valide le nonce et l'identifiant.
8. **Résultat :** Le backend renvoie un message final de succès ou d'échec au frontend,
   qui met à jour l'interface utilisateur.

## 4. Construire le vérificateur

Maintenant que nous avons une solide compréhension des standards, des protocoles et du
flux architectural, nous pouvons commencer à construire notre vérificateur.

> **Suivez le guide ou utilisez le code final**
>
> Nous allons maintenant passer en revue la configuration et l'implémentation du code
> étape par étape. Si vous préférez passer directement au produit fini, vous pouvez cloner
> le projet complet depuis notre dépôt GitHub et l'exécuter localement.
>
> ```bash
> git clone https://github.com/corbado/digital-credentials-example.git
> ```

### 4.1 Mise en place du projet

Tout d'abord, nous allons initialiser un nouveau projet Next.js, installer les dépendances
nécessaires et démarrer notre base de données.

#### 4.1.1 Initialisation de l'application Next.js

Ouvrez votre terminal, naviguez vers le répertoire où vous souhaitez créer votre projet,
et exécutez la commande suivante. Nous utilisons l'App Router, TypeScript et Tailwind CSS
pour ce projet.

```bash
npx create-next-app@latest . --ts --eslint --tailwind --app --src-dir --import-alias "@/*" --use-npm
```

Cette commande crée un nouveau squelette d'application Next.js dans votre répertoire
actuel.

#### 4.1.2 Installation des dépendances

Ensuite, nous devons installer les bibliothèques qui géreront le décodage CBOR, les
connexions à la base de données et la génération d'UUID.

```bash
npm install cbor-web mysql2 uuid @types/uuid
```

Cette commande installe :

- `cbor-web` : Pour décoder la charge utile de l'identifiant mdoc.
- `mysql2` : Le client MySQL pour notre base de données.
- `uuid` : Pour générer des chaînes de challenge uniques.
- `@types/uuid` : Les types TypeScript pour la bibliothèque `uuid`.

#### 4.1.3 Démarrage de la base de données

Notre backend nécessite une base de données MySQL pour stocker les données de session
OIDC, garantissant que chaque flux de vérification est sécurisé et avec état. Nous avons
inclus un fichier `docker-compose.yml` pour faciliter cela.

Si vous avez cloné le dépôt, vous pouvez simplement exécuter `docker-compose up -d`. Si
vous construisez à partir de zéro, créez un fichier nommé `docker-compose.yml` avec le
contenu suivant :

```yaml
services:
    mysql:
        image: mysql:8.0
        restart: always
        environment:
            MYSQL_ROOT_PASSWORD: rootpassword
            MYSQL_DATABASE: digital_credentials
            MYSQL_USER: app_user
            MYSQL_PASSWORD: app_password
        ports:
            - "3306:3306"
        volumes:
            - mysql_data:/var/lib/mysql
            - ./sql/init.sql:/docker-entrypoint-initdb.d/init.sql
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
            timeout: 20s
            retries: 10

volumes:
    mysql_data:
```

Cette configuration Docker Compose nécessite également un script d'initialisation SQL.
Créez un répertoire nommé `sql` et à l'intérieur, un fichier nommé `init.sql` avec le
contenu suivant pour configurer les tables nécessaires :

```sql
-- Create database if not exists
CREATE DATABASE IF NOT EXISTS digital_credentials;
USE digital_credentials;

-- Table for storing challenges
CREATE TABLE IF NOT EXISTS challenges (
    id VARCHAR(36) PRIMARY KEY,
    challenge VARCHAR(255) NOT NULL UNIQUE,
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    used BOOLEAN DEFAULT FALSE,
    INDEX idx_challenge (challenge),
    INDEX idx_expires_at (expires_at)
);

-- Table for storing verification sessions
CREATE TABLE IF NOT EXISTS verification_sessions (
    id VARCHAR(36) PRIMARY KEY,
    challenge_id VARCHAR(36),
    status ENUM('pending', 'verified', 'failed', 'expired') DEFAULT 'pending',
    presentation_data JSON,
    verified_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    FOREIGN KEY (challenge_id) REFERENCES challenges(id) ON DELETE CASCADE,
    INDEX idx_challenge_id (challenge_id),
    INDEX idx_status (status)
);

-- Table for storing verified credentials data (optional)
CREATE TABLE IF NOT EXISTS verified_credentials (
    id VARCHAR(36) PRIMARY KEY,
    session_id VARCHAR(36),
    credential_type VARCHAR(255),
    issuer VARCHAR(255),
    subject VARCHAR(255),
    claims JSON,
    verified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (session_id) REFERENCES verification_sessions(id) ON DELETE CASCADE,
    INDEX idx_session_id (session_id),
    INDEX idx_credential_type (credential_type)
);
```

Une fois que les deux fichiers sont en place, ouvrez votre terminal à la racine du projet
et exécutez :

```bash
docker-compose up -d
```

Cette commande démarrera un conteneur MySQL en arrière-plan.

### 4.2 Vue d'ensemble de l'architecture de l'application Next.js

Notre application Next.js est structurée pour séparer les responsabilités entre le
frontend et le backend, bien qu'ils fassent partie du même projet.

- **Frontend (`src/app/page.tsx`) :** Une seule page [React](https://www.corbado.com/blog/react-passkeys) qui
  lance le flux de vérification et affiche le résultat. Elle interagit avec l'API Digital
  Credential du navigateur.
- **Routes API du backend (`src/app/api/verify/...`) :**
    - `start/route.ts` : Génère la requête OpenID4VP et un nonce de sécurité.
    - `finish/route.ts` : Reçoit la présentation du portefeuille (via le navigateur),
      valide le nonce et décode l'identifiant.
- **Bibliothèque (`src/lib/`) :**
    - `database.ts` : Gère toutes les interactions avec la base de données (création de
      challenges, vérification des sessions).
    - `crypto.ts` : Gère le décodage de l'identifiant mDoc basé sur CBOR.

Voici un diagramme illustrant l'architecture interne :

![Architecture interne de NextJS](https://s3.eu-central-1.amazonaws.com/corbado-cloud-staging-website-assets/Mermaid_Chart_Create_complex_visual_diagrams_with_text_A_smarter_way_of_creating_diagrams_2025_07_25_091202_f96ccb049f.svg)

### 4.3 Construire le frontend

Notre frontend est volontairement léger. Sa principale responsabilité est d'agir comme le
déclencheur côté utilisateur pour le flux de vérification et de communiquer à la fois avec
notre backend et les capacités natives de gestion des identifiants du navigateur. Il ne
contient aucune logique de protocole complexe ; tout est délégué.

Plus précisément, le frontend gérera les éléments suivants :

- **Interaction utilisateur :** Fournit une interface simple, comme un bouton « Vérifier
  », pour que l'utilisateur puisse démarrer le processus.
- **Gestion de l'état :** Gère l'état de l'interface utilisateur, en affichant des
  indicateurs de chargement pendant la vérification et en affichant le message final de
  succès ou d'erreur.
- **Communication avec le backend (Requête) :** Appelle `/api/verify/start` et reçoit une
  charge utile JSON structurée (`protocol`, `request`, `state`) décrivant exactement ce
  que le portefeuille doit présenter.
- **Invocation de l'API du navigateur :** Transmet cet objet JSON à
  `navigator.credentials.get()`, qui affiche un QR code natif et attend la réponse du
  portefeuille.
- **Communication avec le backend (Réponse) :** Une fois que l'API du navigateur renvoie
  la présentation vérifiable, elle envoie ces données à notre point de terminaison
  `/api/verify/finish` dans une requête POST pour la validation finale côté serveur.
- **Affichage des résultats :** Met à jour l'interface utilisateur pour informer
  l'utilisateur si la vérification a réussi ou échoué, en fonction de la réponse du
  backend.

La logique principale se trouve dans la fonction `startVerification` :

```typescript
// src/app/page.tsx

const startVerification = async () => {
    setLoading(true);
    setVerificationResult(null);

    try {
        // 1. Vérifier si le navigateur supporte l'API
        if (!navigator.credentials?.get) {
            throw new Error("Le navigateur ne supporte pas l'API Credential.");
        }

        // 2. Demander à notre backend un objet de requête
        const res = await fetch("/api/verify/start");
        const { protocol, request } = await res.json();

        // 3. Transmettre cet objet au navigateur – cela déclenche le QR code natif
        const credential = await (navigator.credentials as any).get({
            mediation: "required",
            digital: {
                requests: [
                    {
                        protocol, // "openid4vp"
                        data: request, // contient dcql_query, nonce, etc.
                    },
                ],
            },
        });

        // 4. Transférer la réponse du portefeuille (du navigateur) à notre point de terminaison finish pour les vérifications côté serveur
        const verifyRes = await fetch("/api/verify/finish", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(credential),
        });

        const result = await verifyRes.json();

        if (verifyRes.ok && result.verified) {
            setVerificationResult(`Succès : ${result.message}`);
        } else {
            throw new Error(result.message || "La vérification a échoué.");
        }
    } catch (err) {
        setVerificationResult(`Erreur : ${(err as Error).message}`);
    } finally {
        setLoading(false);
    }
};
```

Cette fonction montre les quatre étapes clés de la logique du frontend : vérifier la prise
en charge de l'API, récupérer la requête du backend, appeler l'API du navigateur et
renvoyer le résultat pour vérification. Le reste du fichier est du code standard
[React](https://www.corbado.com/blog/react-passkeys) pour la gestion de l'état et le rendu de l'interface
utilisateur, que vous pouvez consulter dans le
[dépôt GitHub](https://github.com/corbado/digital-credentials-example).

#### Pourquoi `digital` et `mediation: 'required'` ?

Vous remarquerez peut-être que notre appel à `navigator.credentials.get()` est différent
d'exemples plus simples. C'est parce que nous nous conformons strictement à la
[spécification officielle de l'API W3C Digital Credentials](https://www.w3.org/TR/digital-credentials/#the-digital-credentials-api).

- **Membre `digital` :** La spécification exige que toutes les requêtes d'identifiants
  numériques soient imbriquées dans un objet `digital`. Cela fournit un espace de noms
  clair et standardisé pour cette API, la distinguant des autres types d'identifiants
  (comme `password` ou `federated`) et permettant des extensions futures sans conflits.

- **`mediation: 'required'` :** Cette option est une fonctionnalité cruciale de sécurité
  et d'expérience utilisateur. Elle impose que l'utilisateur interagisse activement avec
  une invite (par exemple, un scan biométrique, la saisie d'un PIN ou un écran de
  consentement) pour approuver la demande d'identifiant. Sans cela, un site web pourrait
  potentiellement tenter d'accéder silencieusement aux identifiants en arrière-plan, ce
  qui représente un risque important pour la vie privée. En exigeant la médiation, nous
  nous assurons que l'utilisateur a toujours le contrôle et donne son consentement
  explicite pour chaque transaction.

### 4.4 Construire les points de terminaison du backend

Avec l'interface utilisateur React en place, nous avons maintenant besoin de deux routes
API qui font le gros du travail sur le serveur :

1. **`/api/verify/start`** – construit une requête OpenID4VP, persiste un challenge à
   usage unique dans MySQL et renvoie le tout au navigateur.
2. **`/api/verify/finish`** – reçoit la réponse du portefeuille, valide le challenge,
   vérifie et décode l'identifiant, et renvoie finalement un résultat JSON concis à
   l'interface utilisateur.

#### 4.4.1 `/api/verify/start`: Générer la requête OpenID4VP

```typescript
// src/app/api/verify/start/route.ts
import { NextResponse } from "next/server";
import { v4 as uuidv4 } from "uuid";
import { createChallenge, cleanupExpiredChallenges } from "@/lib/database";

export async function GET() {
    // 1️⃣ Créer un nonce (challenge) aléatoire et à courte durée de vie
    const challenge = uuidv4();
    const challengeId = uuidv4();
    const expiresAt = new Date(Date.now() + 5 * 60 * 1000);

    await createChallenge(challengeId, challenge, expiresAt);
    cleanupExpiredChallenges().catch(console.error);

    // 2️⃣ Construire une requête DCQL qui décrit *ce que* nous voulons
    const dcqlQuery = {
        credentials: [
            {
                id: "cred1",
                format: "mso_mdoc",
                meta: { doctype_value: "eu.europa.ec.eudi.pid.1" },
                claims: [
                    { path: ["eu.europa.ec.eudi.pid.1", "family_name"] },
                    { path: ["eu.europa.ec.eudi.pid.1", "given_name"] },
                    { path: ["eu.europa.ec.eudi.pid.1", "birth_date"] },
                ],
            },
        ],
    };

    // 3️⃣ Renvoyer un objet que le navigateur peut passer à navigator.credentials.get()
    return NextResponse.json({
        protocol: "openid4vp", // indique au navigateur quel protocole de portefeuille utiliser
        request: {
            dcql_query: dcqlQuery, // CE QU'IL FAUT présenter
            nonce: challenge, // anti-replay
            response_type: "vp_token",
            response_mode: "dc_api", // le portefeuille enverra un POST directement à /finish
        },
        state: {
            credential_type: "mso_mdoc", // conservé pour des vérifications ultérieures
            nonce: challenge,
            challenge_id: challengeId,
        },
    });
}
```

> **Paramètres clés**
>
> • **`nonce`** – challenge cryptographique qui lie la requête et la réponse (empêche le
> rejeu). • **`dcql_query`** – Un objet décrivant les déclarations exactes dont nous avons
> besoin. Pour ce guide, nous utilisons une structure `dcql_query` inspirée des récents
> brouillons du Digital Credential Query Language, bien que ce ne soit pas encore un
> standard finalisé. • **`state`** – JSON arbitraire renvoyé en écho par le portefeuille
> pour que nous puissions retrouver l'enregistrement dans la BDD.

#### 4.4.2 Assistants de base de données

Le fichier `src/lib/database.ts` encapsule les opérations MySQL de base pour les
challenges et les sessions de vérification (insérer, lire, marquer comme utilisé). Garder
cette logique dans un seul module facilite le remplacement du magasin de données plus
tard.

---

### 4.5 `/api/verify/finish`: Valider et décoder la présentation

```typescript
// src/app/api/verify/finish/route.ts
import { NextResponse, NextRequest } from "next/server";
import { v4 as uuidv4 } from "uuid";
import {
    getChallenge,
    markChallengeAsUsed,
    createVerificationSession,
    updateVerificationSession,
} from "@/lib/database";
import { decodeDigitalCredential, decodeAllNamespaces } from "@/lib/crypto";

export async function POST(request: NextRequest) {
    const body = await request.json();

    // 1️⃣ Extraire les éléments de la présentation vérifiable
    const vpTokenMap = body.vp_token ?? body.data?.vp_token;
    const state = body.state;
    const mdocToken = vpTokenMap?.cred1; // nous avons demandé cet ID dans dcqlQuery

    if (!vpTokenMap || !state || !mdocToken) {
        return NextResponse.json(
            { verified: false, message: "Réponse mal formée" },
            { status: 400 },
        );
    }

    // 2️⃣ Validation du challenge à usage unique
    const stored = await getChallenge(state.nonce);
    if (!stored) {
        return NextResponse.json(
            { verified: false, message: "Challenge invalide ou expiré" },
            { status: 400 },
        );
    }

    const sessionId = uuidv4();
    await createVerificationSession(sessionId, stored.id);

    // 3️⃣ (Pseudo) vérifications cryptographiques – à remplacer par une vraie validation mDL en prod
    // Dans une application réelle, vous utiliseriez une bibliothèque dédiée pour effectuer une validation
    // cryptographique complète de la signature mdoc par rapport à la clé publique de l'émetteur.
    const isValid = mdocToken.length > 0;
    if (!isValid) {
        await updateVerificationSession(sessionId, "failed", {
            reason: "la validation mdoc a échoué",
        });
        return NextResponse.json(
            { verified: false, message: "La validation de l'identifiant a échoué" },
            { status: 400 },
        );
    }

    // 4️⃣ Décoder la charge utile du mobile-DL (mdoc) en JSON lisible par l'homme
    const decoded = await decodeDigitalCredential(mdocToken);
    const readable = decodeAllNamespaces(decoded)["eu.europa.ec.eudi.pid.1"];

    await markChallengeAsUsed(state.nonce);
    await updateVerificationSession(sessionId, "verified", { readable });

    return NextResponse.json({
        verified: true,
        message: "Identifiant mdoc vérifié avec succès !",
        credentialData: readable,
        sessionId,
    });
}
```

> **Champs importants dans la réponse du portefeuille**
>
> • **`vp_token`** – une map qui contient _chaque_ identifiant renvoyé par le
> portefeuille. Pour notre démo, nous extrayons `vp_token.cred1`. • **`state`** – l'écho
> du blob que nous avons fourni dans `/start` ; contient le `nonce` pour que nous
> puissions retrouver l'enregistrement dans la BDD. • **`mdocToken`** – une structure CBOR
> encodée en Base64URL qui représente l'ISO mDoc.

### 4.6 Décodage de l'identifiant mdoc

Lorsque le vérificateur reçoit un identifiant mdoc du navigateur, il s'agit d'une chaîne
Base64URL contenant des données binaires encodées en CBOR. Pour extraire les déclarations
réelles, le point de terminaison `finish` effectue un processus de décodage en plusieurs
étapes à l'aide de fonctions d'assistance de `src/lib/crypto.ts`.

#### 4.6.1 Étape 1 : Décodage Base64URL et CBOR

La fonction `decodeDigitalCredential` gère la conversion de la chaîne encodée en un objet
utilisable :

```typescript
// src/lib/crypto.ts
export async function decodeDigitalCredential(encodedCredential: string) {
    // 1. Convertir Base64URL en Base64 standard
    const base64UrlToBase64 = (input: string) => {
        let base64 = input.replace(/-/g, "+").replace(/_/g, "/");
        const pad = base64.length % 4;
        if (pad) base64 += "=".repeat(4 - pad);
        return base64;
    };

    const base64 = base64UrlToBase64(encodedCredential);

    // 2. Décoder Base64 en binaire
    const binaryString = atob(base64);
    const byteArray = Uint8Array.from(binaryString, (char) => char.charCodeAt(0));

    // 3. Décoder CBOR
    const decoded = await cbor.decodeFirst(byteArray);
    return decoded;
}
```

- **Base64URL en Base64 :** Convertit l'identifiant de l'encodage Base64URL à l'encodage
  Base64 standard.
- **Base64 en Binaire :** Décode la chaîne Base64 en un tableau d'octets binaires.
- **Décodage CBOR :** Utilise la bibliothèque `cbor-web` pour décoder les données binaires
  en un objet JavaScript structuré.

#### 4.6.2 Étape 2 : Extraction des déclarations par espace de noms

La fonction `decodeAllNamespaces` traite ensuite l'objet CBOR décodé pour extraire les
déclarations réelles des espaces de noms pertinents :

```typescript
// src/lib/crypto.ts
export function decodeAllNamespaces(jsonObj) {
    const decoded = {};

    try {
        jsonObj.documents.forEach((doc, idx) => {
            // 1) issuerSigned.nameSpaces:
            const issuerNS = doc.issuerSigned?.nameSpaces || {};
            Object.entries(issuerNS).forEach(([nsName, entries]) => {
                if (!decoded[nsName]) decoded[nsName] = {};
                (entries as any[]).forEach((entry) => {
                    const bytes = Uint8Array.from(entry.value);
                    const decodedEntry = cbor.decodeFirstSync(bytes);
                    Object.assign(decoded[nsName], decodedEntry);
                });
            });

            // 2) deviceSigned.nameSpaces (si présent):
            const deviceNS = doc.deviceSigned?.nameSpaces;
            if (deviceNS?.value?.data) {
                const bytes = Uint8Array.from(deviceNS.value);
                decoded[`deviceSigned_ns_${idx}`] = cbor.decodeFirstSync(bytes);
            }
        });
    } catch (e) {
        console.error(e);
    }

    return decoded;
}
```

- **Itère sur tous les documents** dans l'identifiant décodé.
- **Décode chaque espace de noms** (par exemple, `eu.europa.ec.eudi.pid.1`) pour extraire
  les valeurs réelles des déclarations (telles que le nom, la date de naissance, etc.).
- **Gère les espaces de noms signés par l'émetteur et par l'appareil** s'ils sont
  présents.

#### Exemple de sortie

Après avoir suivi ces étapes, le point de terminaison finish obtient un objet lisible par
l'homme contenant les déclarations du mdoc, par exemple :

```json
{
    "family_name": "Doe",
    "given_name": "John",
    "birth_date": "1990-01-01"
}
```

Ce processus garantit que le vérificateur peut extraire de manière sécurisée et fiable les
informations nécessaires de l'identifiant mdoc pour l'affichage et le traitement
ultérieur.

### 4.7 Afficher le résultat dans l'interface utilisateur

Le point de terminaison finish renvoie un objet JSON minimal au frontend :

```json
{
    "verified": true,
    "message": "Identifiant mdoc vérifié avec succès !",
    "credentialData": {
        "family_name": "Doe",
        "given_name": "John",
        "birth_date": "1990-01-01"
    }
}
```

Le frontend reçoit cette réponse dans `startVerification()` et la persiste simplement dans
l'état React pour que nous puissions afficher une belle carte de confirmation ou afficher
des déclarations individuelles – par exemple _« Bienvenue, John Doe (né le 1990-01-01) !
»_.

## 5. Exécuter le vérificateur et prochaines étapes

Vous disposez maintenant d'un vérificateur complet et fonctionnel qui utilise les
capacités natives de gestion des identifiants du navigateur. Voici comment l'exécuter
localement et ce que vous pouvez faire pour le faire passer d'une preuve de concept à une
application prête pour la production.

### 5.1 Comment exécuter l'exemple

1. **Cloner le dépôt :**

    ```bash
    git clone https://github.com/corbado/digital-credentials-example.git
    cd digital-credentials-example
    ```

2. **Installer les dépendances :**

    ```bash
    npm install
    ```

3. **Démarrer la base de données :** Assurez-vous que Docker est en cours d'exécution sur
   votre machine, puis démarrez le conteneur MySQL :

    ```bash
    docker-compose up -d
    ```

4. **Lancer l'application :**

    ```bash
    npm run dev
    ```

    Ouvrez votre navigateur à l'adresse `http://localhost:3000`, et vous devriez voir
    l'interface utilisateur du vérificateur. Vous pouvez maintenant utiliser votre
    CMWallet pour scanner le QR code et compléter le flux de vérification.

### 5.2 Prochaines étapes : de la démo à la production

Ce tutoriel fournit les briques de base pour un vérificateur. Pour le rendre prêt pour la
production, vous devriez implémenter plusieurs fonctionnalités supplémentaires :

- **Validation cryptographique complète :** L'implémentation actuelle utilise une
  vérification de substitution (`mdocToken.length > 0`). Dans un scénario réel, vous devez
  effectuer une validation cryptographique complète de la signature mdoc par rapport à la
  clé publique de l'émetteur (par exemple, en résolvant son DID ou en récupérant son
  certificat de clé publique). Pour les standards de résolution de DID, consultez la
  [spécification W3C DID Resolution](https://www.w3.org/TR/did-resolution/).

- **Vérification de la révocation par l'émetteur :** Les identifiants peuvent être
  révoqués par l'émetteur avant leur date d'expiration. Un vérificateur de production doit
  vérifier le statut de l'identifiant en interrogeant une liste de révocation ou un point
  de terminaison de statut fourni par l'émetteur. La
  [W3C Verifiable Credentials Status List](https://www.w3.org/TR/vc-bitstring-status-list/)
  fournit le standard pour les listes de révocation d'identifiants.

- **Gestion robuste des erreurs et sécurité :** Ajoutez une gestion complète des erreurs,
  une validation des entrées, une limitation du débit sur les points de terminaison de
  l'API, et assurez-vous que toutes les communications se font via HTTPS (TLS) pour
  protéger les données en transit. Les
  [OWASP API Security Guidelines](https://owasp.org/www-project-api-security/) fournissent
  des meilleures pratiques complètes pour la sécurité des API.

- **Prise en charge de plusieurs types d'identifiants :** Étendez la logique pour gérer
  différentes valeurs de `doctype` et formats d'identifiants si vous prévoyez de recevoir
  plus que le simple identifiant PID de l'[identité numérique](https://www.corbado.com/fr/glossary/openid-4-vp)
  européenne (EUDI). Le
  [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) fournit
  des spécifications complètes sur les formats de VC.

### 5.3 Ce qui est hors du champ de ce tutoriel

Cet exemple est volontairement axé sur le flux principal médiatisé par le navigateur pour
le rendre facile à comprendre. Les sujets suivants sont considérés comme hors du champ
d'application :

- **Sécurité prête pour la production :** Le vérificateur est à des fins éducatives et ne
  dispose pas du renforcement requis pour un environnement en direct.
- **Identifiants vérifiables W3C :** Ce tutoriel se concentre exclusivement sur le format
  ISO mDoc pour les permis de conduire mobiles. Il ne couvre pas d'autres formats
  populaires comme les JWT-VC ou les VC avec des preuves de données liées (LD-Proofs).
- **Flux OpenID4VP avancés :** Nous n'implémentons pas de fonctionnalités OpenID4VP plus
  complexes, telles que la communication directe entre le portefeuille et le backend à
  l'aide d'un `redirect_uri` ou l'enregistrement de client dynamique.

En vous basant sur cette fondation et en intégrant ces prochaines étapes, vous pouvez
développer un vérificateur robuste et sécurisé capable de faire confiance et de valider
les [identifiants numériques](https://www.corbado.com/fr/blog/digital-credentials-api) dans vos propres
applications.

## Conclusion

C'est tout ! Avec moins de 250 lignes de TypeScript, nous avons maintenant un vérificateur
de bout en bout qui :

1. Publie une requête pour l'API d'identifiants du navigateur.
2. Permet à tout portefeuille compatible de fournir une présentation vérifiable.
3. Valide la présentation sur le serveur.
4. Met à jour l'interface utilisateur en temps réel.

En production, vous remplaceriez la validation de substitution par des vérifications
complètes [ISO 18013-5](https://www.corbado.com/glossary/iso-18013-5), ajouteriez des consultations de listes de
révocation d'émetteurs, une limitation de débit, des journaux d'audit et, bien sûr, le TLS
de bout en bout, mais les briques de base restent exactement les mêmes.

## Ressources

Voici quelques-unes des principales ressources, spécifications et outils utilisés ou
référencés dans ce tutoriel :

- **Dépôt du projet :**
    - [Code source complet sur GitHub](https://github.com/corbado/digital-credentials-example)

- **Spécifications clés :**
    - [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) : Le
      standard fondamental pour les VCs.
    - [OpenID for Verifiable Presentations (OpenID4VP)](https://openid.net/specs/openid-4-verifiable-presentations-1_0.html)
      : Le protocole de présentation utilisé pour l'échange d'identifiants.
    - [ISO/IEC 18013-5 (mDoc)](https://www.iso.org/standard/69084.html) : Le standard
      international pour les permis de conduire mobiles (mDLs).
    - [W3C Digital Credentials API](https://www.w3.org/TR/digital-credentials/#the-digital-credentials-api)
      : L'API du navigateur utilisée pour demander des identifiants à un portefeuille.

- **Outils :**
    - [CMWallet pour Android](https://github.com/digitalcredentialsdev/CMWallet/actions/runs/16407676816/artifacts/3574255220)
      : Le portefeuille de test utilisé dans ce guide.

- **Bibliothèques :**
    - Next.js : Le framework React pour construire le frontend et le backend.
    - [cbor-web](https://github.com/hildjj/cbor-web) : Pour décoder les identifiants mdoc
      encodés en CBOR.
    - [mysql2](https://github.com/sidorares/node-mysql2) : Le client MySQL pour
      [Node.js](https://www.corbado.com/blog/nodejs-passkeys).
