Soyons honnêtes : nous avons tous souhaité pouvoir nous connecter à des sites Web en utilisant nos empreintes digitales ou Face ID, tout comme sur les applications mobiles, n'est-ce pas ? Eh bien, grâce à la biométrie Web, ce rêve n’est plus si farfelu. Imaginez abandonner ces mots de passe longs et compliqués et utiliser simplement notre empreinte digitale ou notre visage pour vous connecter à nos sites Web préférés. Ça a l’air cool, n’est-ce pas ?
La biométrie Web, optimisée par WebAuthn, rend cela possible. C'est un nom sophistiqué pour quelque chose d'assez simple : nous authentifier avec le même type de sécurité que le capteur d'empreintes digitales ou la reconnaissance faciale de notre téléphone, mais directement dans notre navigateur Web. Ne vous inquiétez plus de la fuite ou du vol de vos mots de passe : il suffit d'une analyse rapide et nous y sommes.
Dans ce didacticiel, nous allons nous familiariser avec l'intégration de la connexion par empreinte digitale et Face ID dans nos applications Angular. Nous aborderons l'essentiel, comme le fonctionnement de l'API WebAuthn et ce que nous devons faire sur le backend pour que tout reste sécurisé et fluide. C’est plus facile que vous ne le pensez, et à la fin, notre application sera prête pour l’avenir de l’authentification. Alors, plongeons-nous et faisons de la connexion un jeu d'enfant !
Très bien, avant de passer au code, voyons brièvement ce qu'est WebAuthn. Considérez WebAuthn comme le pont qui connecte nos applications aux fonctionnalités biométriques intéressantes que nous aimons sur nos téléphones, comme les empreintes digitales et Face ID, directement dans nos navigateurs. Il utilise la cryptographie à clé publique pour authentifier les utilisateurs, ce qui signifie qu'il n'est plus nécessaire de stocker d'anciens mots de passe que les pirates peuvent facilement récupérer. Au lieu de cela, nous parlons de clés générées de manière sécurisée qui rendent nos connexions à la fois sûres et transparentes.
Pour faire avancer les choses, nous devons comprendre quelques acteurs clés du jeu WebAuthn : PublicKeyCredentialCreationOptions et PublicKeyCredentialRequestOptions. Ne vous laissez pas effrayer par les noms longs : ce ne sont que des moyens sophistiqués d'indiquer au navigateur comment nous souhaitons enregistrer et authentifier les utilisateurs.
Il s'agit de notre objet de prédilection lors de la configuration de nouveaux identifiants utilisateur. Il comprend :
Quand vient le temps de vérifier nos utilisateurs, cet objet prend le devant de la scène. Il comprend :
Avec ces objets en main, notre application Angular pourra guider les utilisateurs dans l'enregistrement de leurs données biométriques et dans leur authentification rapide et sécurisée. Ensuite, nous entrerons dans le code et verrons comment réaliser cette magie dans notre application !
Dans cette section, nous vous guiderons dans la configuration d'une application Angular avec authentification biométrique à l'aide de WebAuthn. Nous allons nous concentrer sur l’utilisation des empreintes digitales et de Face ID, alors mettons la main à la pâte !
Pour commencer, créons un nouveau projet Angular. Ouvrez votre terminal et tapez les commandes suivantes :
ng new web-biometrics-demo cd web-biometrics-demo ng serve
Cela configure une application angulaire de base et l'exécution de ng serve démarrera votre application sur http://localhost:4200/. Vous devriez voir la page de bienvenue angulaire par défaut. Nous sommes désormais prêts à intégrer WebAuthn pour l'authentification biométrique.
Nous avons besoin d'un service en Angular pour gérer toutes nos fonctionnalités WebAuthn, y compris l'enregistrement et l'authentification à l'aide de la biométrie. Créons ce service en exécutant :
ng generate service services/webauthn
Now, open webauthn.service.ts and add the following code:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class WebAuthnService { constructor() { } // Generates a random buffer to use as a challenge, which is a unique value needed for security private generateRandomBuffer(length: number): Uint8Array { const randomBuffer = new Uint8Array(length); window.crypto.getRandomValues(randomBuffer); // Fills the buffer with cryptographically secure random values return randomBuffer; } // Registers a new credential (like a fingerprint or Face ID) for the user async register() { // Generate a unique challenge for the registration process const challenge = this.generateRandomBuffer(32); // PublicKeyCredentialCreationOptions is the core object needed for registration const publicKey: PublicKeyCredentialCreationOptions = { challenge: challenge, // A random value generated by the server to ensure the request is fresh and unique rp: { // Relying Party (your app) information name: "OurAwesomeApp" // Display name of your app }, user: { // User information id: this.generateRandomBuffer(16), // A unique identifier for the user name: "user@example.com", // User's email or username displayName: "User Example" // A friendly name for the user }, pubKeyCredParams: [{ // Array of acceptable public key algorithms type: "public-key", alg: -7 // Represents the ES256 algorithm (Elliptic Curve Digital Signature Algorithm) }], authenticatorSelection: { // Criteria for selecting the appropriate authenticator authenticatorAttachment: "platform", // Ensures we use the device's built-in biometric authenticator like Touch ID or Face ID userVerification: "required" // Requires user verification (e.g., fingerprint or face scan) }, timeout: 60000, // Timeout for the registration operation in milliseconds attestation: "direct" // Attestation provides proof of the authenticator's properties and is sent back to the server }; try { // This will prompt the user to register their biometric credential const credential = await navigator.credentials.create({ publicKey }) as PublicKeyCredential; this.storeCredential(credential, challenge); // Store the credential details locally for demo purposes console.log("Registration successful!", credential); return credential; // Return the credential object containing the user's public key and other details } catch (err) { console.error("Registration failed:", err); throw err; // Handle any errors that occur during registration } } // Authenticates the user with stored credentials (like a fingerprint or Face ID) async authenticate() { const storedCredential = this.getStoredCredential(); // Retrieve stored credential information if (!storedCredential) { throw new Error("No stored credential found. Please register first."); // Error if no credentials are found } // PublicKeyCredentialRequestOptions is used to prompt the user to authenticate const publicKey: PublicKeyCredentialRequestOptions = { challenge: new Uint8Array(storedCredential.challenge), // A new challenge to ensure the request is fresh and unique allowCredentials: [{ // Specifies which credentials can be used for authentication id: new Uint8Array(storedCredential.rawId), // The ID of the credential to use type: "public-key" }], userVerification: "required", // Requires user verification (e.g., fingerprint or face scan) timeout: 60000 // Timeout for the authentication operation in milliseconds }; try { // This will prompt the user to authenticate using their registered biometric credential const credential = await navigator.credentials.get({ publicKey }) as PublicKeyCredential; console.log("Authentication successful!", credential); return credential; // Return the credential object with authentication details } catch (err) { console.error("Authentication failed:", err); throw err; // Handle any errors that occur during authentication } } // Stores credential data in localStorage (for demo purposes only; this should be handled securely in production) private storeCredential(credential: PublicKeyCredential, challenge: Uint8Array) { const credentialData = { rawId: Array.from(new Uint8Array(credential.rawId)), // Converts the raw ID to an array for storage challenge: Array.from(challenge) // Converts the challenge to an array for storage }; localStorage.setItem('webauthn_credential', JSON.stringify(credentialData)); // Store the data as a JSON string } // Retrieves stored credential data from localStorage private getStoredCredential(): any { const storedCredential = localStorage.getItem('webauthn_credential'); return storedCredential ? JSON.parse(storedCredential) : null; // Parse the stored JSON back into an object } }
generateRandomBuffer: Creates a random buffer that serves as a challenge to ensure each authentication or registration request is unique.
register: This method sets up the biometric registration process. It uses PublicKeyCredentialCreationOptions to define parameters like the challenge, relying party (your app), user information, and acceptable public key algorithms. When navigator.credentials.create() is called, the browser prompts the user to register their biometric data.
authenticate: This method handles user authentication with biometrics. It uses PublicKeyCredentialRequestOptions to define the authentication challenge and credentials that can be used. The method prompts the user to authenticate with their registered biometrics.
storeCredential and getStoredCredential: These methods handle storing and retrieving credentials in localStorage for demonstration purposes.
In a real-world app, you’d securely store this information on your backend.
Now, let’s create a basic UI with buttons to trigger the registration and login functions. This UI will provide feedback based on whether the registration or login was successful.
Open app.component.ts and replace the content with the following:
import { Component } from '@angular/core'; import { WebAuthnService } from './services/webauthn.service'; @Component({ selector: 'app-root', template: ` <div class="auth-container"> <h1>Web Biometrics in Angular</h1> <button (click)="register()">Register with Fingerprint</button> <button (click)="login()">Login with Face ID</button> <p *ngIf="message" [ngClass]="{'success': isSuccess, 'error': !isSuccess}">{{ message }}</p> </div> `, styles: [` .auth-container { text-align: center; padding: 50px; } .success { color: green; } .error { color: red; } button { margin: 10px; padding: 10px 20px; font-size: 16px; } p { margin: 10px; font-size: 16px; } `] }) export class AppComponent { message: string | null = null; // Message to display feedback to the user isSuccess: boolean = false; // Indicates if the last action was successful constructor(private webAuthnService: WebAuthnService) { } // Trigger registration process and update the UI based on the outcome async register() { try { await this.webAuthnService.register(); this.message = "Registration successful!"; // Success message if registration works this.isSuccess = true; } catch (err) { this.message = "Registration failed. Please try again."; // Error message if something goes wrong this.isSuccess = false; } } // Trigger authentication process and update the UI based on the outcome async login() { try { await this.webAuthnService.authenticate(); this.message = "Authentication successful!"; // Success message if authentication works this.isSuccess = true; } catch (err) { this.message = "Authentication failed. Please try again."; // Error message if something goes wrong this.isSuccess = false; } } }
register and login methods: These methods call the respective register and authenticate methods from the WebAuthnService. If successful, a success message is displayed; otherwise, an error message is shown.
Template and Styling: The template includes buttons to trigger registration and login, and it displays messages to the user based on the operation's outcome. The buttons are styled for simplicity.
That’s it! We’ve built a basic Angular app with WebAuthn-based biometric authentication, supporting fingerprints and Face ID. This setup captures the core concepts and lays a foundation that can be expanded with additional features and security measures for a production environment.
When implementing biometric authentication like fingerprints or Face ID in web applications using WebAuthn, the backend plays a crucial role in managing the security and flow of data. Here’s a breakdown of how the backend processes work in theory, focusing on registration and login functionalities.
User Data Capture: During registration, the user provides basic credentials, such as an email and password. If biometric data is also being registered, this is captured as part of the WebAuthn response.
Password Hashing: For security, passwords are never stored in plain text. Instead, they are hashed using a library like bcrypt before being stored in the database.
Storing WebAuthn Credentials:
The backend uses libraries like cbor to decode binary data formats from the WebAuthn response, extracting necessary elements like the public key and authenticator data.
It ensures that the challenge from the initial registration request matches what is returned in the WebAuthn response to verify the authenticity of the registration.
If the WebAuthn response passes all checks, the credentials are saved in the database, linked to the user account.
Challenge Generation: Similar to registration, the server generates a challenge that must be responded to by the client’s authenticator during login.
Validating the WebAuthn Response:
Berechtigungsüberprüfung:
Nichtübereinstimmung oder ungültige Antwort: Wenn die Challenge-Antwort nicht mit den erwarteten Werten übereinstimmt oder wenn die WebAuthn-Anmeldeinformationen nicht korrekt überprüft werden, antwortet das Backend mit einem Fehler und verhindert so unbefugten Zugriff.
Fallback auf Passwort: Wenn WebAuthn fehlschlägt oder nicht verfügbar ist, kann das System zur herkömmlichen Passwortüberprüfung zurückkehren und sicherstellen, dass Benutzer weiterhin auf ihre Konten zugreifen können.
Datenintegrität: Die Integrität der WebAuthn-Anmeldeinformationen ist von entscheidender Bedeutung. Jede Änderung bei der Speicherung oder Übertragung würde dazu führen, dass die Überprüfung fehlschlägt, wodurch der Authentifizierungsprozess gesichert wird.
Challenge Nonces: Die Verwendung einzigartiger, zeitlich begrenzter Challenges stellt sicher, dass Antworten nicht wiederverwendet werden können, und schützt so vor Replay-Angriffen.
Öffentliche Schlüsselspeicherung: Die ausschließliche Speicherung öffentlicher Schlüssel (die nicht dazu verwendet werden können, sich als Benutzer auszugeben) erhöht die Sicherheit, da private Schlüssel auf dem Clientgerät verbleiben.
Durch die Befolgung dieser Prinzipien verwaltet das Backend die biometrische Authentifizierung effektiv und sorgt so für ein sicheres, nahtloses Erlebnis für Benutzer, die Funktionen wie Fingerabdruck oder Face ID in ihren Angular-Apps verwenden möchten.
In diesem Tutorial haben wir uns mit der Integration der biometrischen Authentifizierung in Angular mithilfe von WebAuthn befasst. Wir haben das Wesentliche behandelt, vom Verständnis wichtiger WebAuthn-Objekte wie PublicKeyCredentialCreationOptions und PublicKeyCredentialRequestOptions bis hin zum Einrichten von Angular-Diensten und UI-Komponenten für einen reibungslosen Registrierungs- und Anmeldeprozess. Wir haben auch die Backend-Überlegungen besprochen, die für die sichere Handhabung der biometrischen Authentifizierung erforderlich sind.
Für diejenigen, die WebAuthn unbedingt in Aktion sehen möchten, habe ich eine Demo und ein Repository mit einer vollständigen Implementierung bereitgestellt. Sie können sich die Demo hier ansehen und den Quellcode auf GitHub in diesem Repository erkunden.
Die Einführung der biometrischen Authentifizierung erhöht nicht nur die Sicherheit, sondern vereinfacht auch das Benutzererlebnis und ebnet den Weg für eine Zukunft, in der die Anmeldung so einfach ist wie ein Fingerabdruck-Scan oder eine schnelle Gesichtserkennung. Wenn Sie diese Funktionen in Ihre Angular-Apps integrieren, tragen Sie zu einem sichereren und benutzerfreundlicheren Web bei. Viel Spaß beim Codieren!
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!