Webauthn | Client Javascript

WebAuthn (Web Authentication API) est un standard W3C qui permet une authentification sans mot de passe sécurisée grâce à la cryptographie à clé publique. Au lieu des mots de passe, les utilisateurs s'enregistrent et s'authentifient à l'aide d'authentificateurs matériels (comme les lecteurs d'empreintes digitales, Face ID, YubiKeys, etc.) ou d'authentificateurs de plateforme intégrés (comme Touch ID).

 

Voici comment gérer l'enregistrement et l'authentification à l'aide d'un client Javascript.

Inscription WebAuthn

Fonctionnement de l'enregistrement WebAuthn

 

 

 

Le composant TsgcWSAPIServer_WebAuthn dispose d'un fichier HTML pour tester le protocole WebAuthn. Ce fichier HTML contient une interface minimale et du code JavaScript pour interagir avec WebAuthn.

 

Présentation de sgcWebAuthn.html

 

Vue d'ensemble de la structure :

 

 

 

1. Interface HTML pour la saisie

 

<input type="text" id="username" name="username" autocomplete="username webauthn" />
<button id="btnRegBegin"><strong>Register</strong></button>

 

2. JavaScript : Gestionnaire de clic sur le bouton

 

document.querySelector('#btnRegBegin').addEventListener('click', async () => {
  const username = document.getElementById("username").value;
  if (username == "") {
    document.getElementById('Error').innerText = 'Please enter a username to register';
    return;
}

  const resp = await fetch('<#webauthn_registration_options>', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, algorithms: [] })
});

  const options = await resp.json();
const attResp = await startRegistration(options);  // WebAuthn API

 

3. Réponse du serveur (point de terminaison fictif en HTML)

 

fetch('/sgcWebAuthn/Registration/Options', ...)

fetch('/sgcWebAuthn/Registration/Verify', ...)

 

4. Finalisation de l'enregistrement

 

const verificationResp = await fetch('/webauthn/register/verify', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(attResp)
});

const verificationJSON = await verificationResp.json();
if (verificationJSON && verificationJSON.verified) {
  document.getElementById('Success').innerHTML = `Authenticator registered!`;
}

 

 

 

Authentification WebAuthn

Fonctionnement de l'authentification WebAuthn

 

 

1. Configuration de l'interface HTML

 

<div class="container">
<h1>WebAuthn Authentication Sample</h1>

  <section id="userdata">
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" autocomplete="username webauthn" autofocus />
</section>

  <button id="btnAuthBegin"><strong>Authenticate</strong></button>

  <p id="Success" class="success"></p>
<p id="Error" class="error"></p>

  <details open>
    <summary>Console</summary>
    <textarea id="Debug"></textarea>
  </details>
</div>

 

2. Obtenir les options d'authentification

 

Avant d'appeler startAuthentication, vous envoyez le nom d'utilisateur au serveur

 

const resp = await fetch('<#webauthn_authentication_options>', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    username: document.getElementById("username").value,
    user_verification: 'preferred'
  }),
});

 

Le serveur répond avec un objet JSON qui inclut :

 

{
  "challenge": "base64url-encoded-random-string",
  "allowCredentials": [
    {
      "id": "base64url-credential-id",
      "type": "public-key"
    }
  ],
  "userVerification": "preferred",
  "rpId": "yourdomain.com"
}

 

C'est ce qu'on appelle PublicKeyCredentialRequestOptions.

 

 

3. Recevoir la réponse de l'authentificateur

 

La réponse asseResp ressemble à ceci (simplifiée) :

 

{
  "id": "credentialId",
  "rawId": "base64url-encoded-id",
  "response": {
    "authenticatorData": "...",
    "clientDataJSON": "...",
    "signature": "...",
    "userHandle": "..."
  },
  "type": "public-key",
  "clientExtensionResults": {}
}

 

Cette réponse prouve que l'utilisateur :

 

 

 

4. Envoyer la réponse d'authentification signée au serveur

 

Après que l'utilisateur interagit avec son authentificateur (via startAuthentication()), vous obtenez un objet de réponse en JavaScript.

 

const verificationResp = await fetch('/webauthn/authenticate/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(asseResp), // this is the signed response
});

 

 

5. Obtenir la réponse du serveur

 

Le serveur répondra avec un résultat de ce type :

 

{ "verified": true }

 

Ou si quelque chose s'est mal passé :

 

{ "verified": false, "error": "Invalid signature" }

 

Et vous le gérez dans votre code frontend :

 

const result = await verificationResp.json();

if (result.verified) {
  document.getElementById('Success').textContent = 'User authenticated!';
} else {
  document.getElementById('Error').textContent = 'Authentication failed!';
}