Elysia Tools

Durchsuche Tools, Beispiele, visuelle Erklärungen und Themenguides an einem klaren Ort.

Beliebte Kategorien

Themen

Sprache
ZHESPTRUFRDEEN

Elysia Tools

Mobile Navigation

Websicherheit

WebAuthn Passwortlose Authentifizierung

Web Authentication API Beispiele mit biometrischer Authentifizierung, Sicherheitsschlüsseln und passwortlosen Anmeldesystemen

Beispiele

Einträge in dieser Sammlung

QuellcodejavascriptEinfach

WebAuthn Hello World

Grundlegende WebAuthn-Implementierung mit einfachem Registrierungs- und Authentifizierungsfluss

Schwierigkeit

4/10

Geschätzte Zeit

20 min

Schlagwörter

webauthn, authentication, security, passwordless

Voraussetzungen

JavaScript basics, Async/await, Cryptography basics

javascript
// WebAuthn Hello World - Basic Passwordless Authentication
// Simple implementation of registration and authentication

class WebAuthnHelloWorld {
  constructor() {
    this.challenges = new Map() // Store challenges for verification
    this.credentials = new Map() // In-memory credential storage (use DB in production)
  }

  // Generate random challenge
  generateChallenge() {
    const array = new Uint8Array(32)
    crypto.getRandomValues(array)
    return this.arrayBufferToBase64URL(array.buffer)
  }

  // Convert ArrayBuffer to Base64URL
  arrayBufferToBase64URL(buffer) {
    return btoa(String.fromCharCode(...new Uint8Array(buffer)))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=/g, '')
  }

  // Convert Base64URL to ArrayBuffer
  base64URLToArrayBuffer(base64url) {
    const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/')
    const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4)
    return Uint8Array.from(atob(padded), c => c.charCodeAt(0)).buffer
  }

  // Register new credential
  async register(username, displayName = username) {
    try {
      // Generate challenge
      const challenge = this.generateChallenge()
      this.challenges.set(username, challenge)

      // Create credential creation options
      const credentialCreationOptions = {
        challenge: this.base64URLToArrayBuffer(challenge),
        rp: {
          name: "WebAuthn Demo",
          id: window.location.hostname
        },
        user: {
          id: this.base64URLToArrayBuffer(btoa(username)),
          name: username,
          displayName: displayName
        },
        pubKeyCredParams: [
          { alg: -7, type: "public-key" },   // ES256
          { alg: -257, type: "public-key" }  // RS256
        ],
        authenticatorSelection: {
          authenticatorAttachment: "platform", // Use device built-in authenticator
          userVerification: "required"
        },
        timeout: 60000,
        attestation: "direct"
      }

      console.log('Creating credential with options:', credentialCreationOptions)

      // Create credential
      const credential = await navigator.credentials.create({
        publicKey: credentialCreationOptions
      })

      if (!credential) {
        throw new Error('Credential creation failed')
      }

      // Store credential (in production, save to database)
      const credentialData = {
        id: this.arrayBufferToBase64URL(credential.rawId),
        type: credential.type,
        response: {
          attestationObject: this.arrayBufferToBase64URL(credential.response.attestationObject),
          clientDataJSON: this.arrayBufferToBase64URL(credential.response.clientDataJSON)
        }
      }

      this.credentials.set(username, credentialData)

      console.log('Credential registered successfully:', {
        username,
        credentialId: credentialData.id
      })

      return {
        success: true,
        credentialId: credentialData.id,
        message: 'Registration successful!'
      }

    } catch (error) {
      console.error('Registration error:', error)
      return {
        success: false,
        error: error.message || 'Registration failed'
      }
    }
  }

  // Authenticate user
  async authenticate(username) {
    try {
      // Get stored credential
      const storedCredential = this.credentials.get(username)
      if (!storedCredential) {
        throw new Error('No credential found for this user')
      }

      // Generate challenge
      const challenge = this.generateChallenge()
      this.challenges.set(username, challenge)

      // Create assertion options
      const assertionOptions = {
        challenge: this.base64URLToArrayBuffer(challenge),
        allowCredentials: [{
          id: this.base64URLToArrayBuffer(storedCredential.id),
          type: storedCredential.type,
          transports: ['internal', 'usb', 'ble', 'nfc']
        }],
        userVerification: "required",
        timeout: 60000
      }

      console.log('Authenticating with options:', assertionOptions)

      // Get assertion
      const assertion = await navigator.credentials.get({
        publicKey: assertionOptions
      })

      if (!assertion) {
        throw new Error('Authentication failed')
      }

      // Verify assertion (simplified - in production, verify cryptographic signature)
      const assertionData = {
        credentialId: this.arrayBufferToBase64URL(assertion.rawId),
        response: {
          authenticatorData: this.arrayBufferToBase64URL(assertion.response.authenticatorData),
          clientDataJSON: this.arrayBufferToBase64URL(assertion.response.clientDataJSON),
          signature: this.arrayBufferToBase64URL(assertion.response.signature),
          userHandle: assertion.response.userHandle ?
            this.arrayBufferToBase64URL(assertion.response.userHandle) : null
        }
      }

      console.log('Authentication successful:', {
        username,
        credentialId: assertionData.credentialId
      })

      return {
        success: true,
        credentialId: assertionData.credentialId,
        message: 'Authentication successful!'
      }

    } catch (error) {
      console.error('Authentication error:', error)
      return {
        success: false,
        error: error.message || 'Authentication failed'
      }
    }
  }

  // Check if WebAuthn is supported
  static isSupported() {
    return !!(navigator.credentials && navigator.credentials.create && navigator.credentials.get)
  }

  // Check if platform authenticator is available
  static async isPlatformAuthenticatorAvailable() {
    if (!this.isSupported()) return false

    try {
      const available = await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()
      return available
    } catch (error) {
      console.warn('Error checking platform authenticator:', error)
      return false
    }
  }
}

// HTML UI Example
// <!DOCTYPE html>
// <html>
// <head>
//   <title>WebAuthn Hello World</title>
//   <style>
//     body {
//       font-family: system-ui, -apple-system, sans-serif;
//       max-width: 500px;
//       margin: 50px auto;
//       padding: 20px;
//       background: #f5f5f5;
//     }
//     .container {
//       background: white;
//       padding: 30px;
//       border-radius: 10px;
//       box-shadow: 0 2px 10px rgba(0,0,0,0.1);
//     }
//     h1 {
//       text-align: center;
//       color: #333;
//       margin-bottom: 30px;
//     }
//     .form-group {
//       margin-bottom: 20px;
//     }
//     label {
//       display: block;
//       margin-bottom: 5px;
//       font-weight: 500;
//       color: #555;
//     }
//     input {
//       width: 100%;
//       padding: 12px;
//       border: 1px solid #ddd;
//       border-radius: 5px;
//       font-size: 16px;
//       box-sizing: border-box;
//     }
//     button {
//       width: 100%;
//       padding: 12px;
//       background: #007AFF;
//       color: white;
//       border: none;
//       border-radius: 5px;
//       font-size: 16px;
//       cursor: pointer;
//       margin-bottom: 10px;
//     }
//     button:hover {
//       background: #0056b3;
//     }
//     button:disabled {
//       background: #ccc;
//       cursor: not-allowed;
//     }
//     .status {
//       padding: 15px;
//       border-radius: 5px;
//       margin-top: 20px;
//       text-align: center;
//     }
//     .success {
//       background: #d4edda;
//       color: #155724;
//       border: 1px solid #c3e6cb;
//     }
//     .error {
//       background: #f8d7da;
//       color: #721c24;
//       border: 1px solid #f5c6cb;
//     }
//     .info {
//       background: #d1ecf1;
//       color: #0c5460;
//       border: 1px solid #bee5eb;
//     }
//   </style>
// </head>
// <body>
//   <div class="container">
//     <h1>🔐 WebAuthn Hello World</h1>

//     <div class="form-group">
//       <label for="username">Username:</label>
//       <input type="text" id="username" placeholder="Enter your username" value="alice">
//     </div>

//     <button id="registerBtn" onclick="register()">Register New Credential</button>
//     <button id="authenticateBtn" onclick="authenticate()">Sign In</button>

//     <div id="status" class="status info">
//       Click "Register" to create a new credential, then "Sign In" to authenticate
//     </div>
//   </div>

//   <script src="webauthn-hello-world.js"></script>
//   <script>
//     const webauthn = new WebAuthnHelloWorld()

//     // Check browser support
//     if (!WebAuthnHelloWorld.isSupported()) {
//       updateStatus('WebAuthn is not supported in this browser', 'error')
//       document.getElementById('registerBtn').disabled = true
//       document.getElementById('authenticateBtn').disabled = true
//     }

//     async function register() {
//       const username = document.getElementById('username').value.trim()
//       if (!username) {
//         updateStatus('Please enter a username', 'error')
//         return
//       }

//       updateStatus('Creating credential...', 'info')
//       disableButtons(true)

//       try {
//         const result = await webauthn.register(username)
//         if (result.success) {
//           updateStatus(`✅ ${result.message} (ID: ${result.credentialId})`, 'success')
//         } else {
//           updateStatus(`❌ Registration failed: ${result.error}`, 'error')
//         }
//       } catch (error) {
//         updateStatus(`❌ Registration error: ${error.message}`, 'error')
//       } finally {
//         disableButtons(false)
//       }
//     }

//     async function authenticate() {
//       const username = document.getElementById('username').value.trim()
//       if (!username) {
//         updateStatus('Please enter a username', 'error')
//         return
//       }

//       updateStatus('Authenticating...', 'info')
//       disableButtons(true)

//       try {
//         const result = await webauthn.authenticate(username)
//         if (result.success) {
//           updateStatus(`✅ ${result.message} (ID: ${result.credentialId})`, 'success')
//           // Redirect to dashboard on success
//           setTimeout(() => {
//             updateStatus('🎉 Authentication successful! Redirecting...', 'success')
//           }, 2000)
//         } else {
//           updateStatus(`❌ Authentication failed: ${result.error}`, 'error')
//         }
//       } catch (error) {
//         updateStatus(`❌ Authentication error: ${error.message}`, 'error')
//       } finally {
//         disableButtons(false)
//       }
//     }

//     function updateStatus(message, type) {
//       const statusEl = document.getElementById('status')
//       statusEl.textContent = message
//       statusEl.className = `status ${type}`
//     }

//     function disableButtons(disabled) {
//       document.getElementById('registerBtn').disabled = disabled
//       document.getElementById('authenticateBtn').disabled = disabled
//     }

//     // Check platform authenticator availability
//     (async () => {
//       const isAvailable = await WebAuthnHelloWorld.isPlatformAuthenticatorAvailable()
//       if (isAvailable) {
//         console.log('✅ Platform authenticator (biometric) is available')
//       } else {
//         console.log('ℹ️ Platform authenticator not available, but you can use security keys')
//       }
//     })()
//   </script>
// </body>
// </html>

// Usage example:
// const webauthn = new WebAuthnHelloWorld()
//
// // Register a new user
// webauthn.register('alice', 'Alice Smith')
//   .then(result => console.log(result))
//
// // Authenticate existing user
// webauthn.authenticate('alice')
//   .then(result => console.log(result))

export default WebAuthnHelloWorld
QuellcodetypescriptMittel

Passkeys-Manager-System

Vollständiges Passkeys-Management-System mit Multi-Geräte-Unterstützung, Backup-Optionen und benutzerfreundlicher Oberfläche

Schwierigkeit

7/10

Geschätzte Zeit

35 min

Schlagwörter

webauthn, passkeys, authentication, security, passwordless

Voraussetzungen

TypeScript, IndexedDB, Async programming, Cryptography

typescript
// WebAuthn Passkeys Manager - Complete Passwordless Authentication System
// Multiple device support, backup options, and enterprise features

interface PasskeyCredential {
  id: string
  name: string
  createdAt: Date
  lastUsedAt?: Date
  deviceType: 'platform' | 'cross-platform'
  userHandle: string
  publicKey: string
  counter: number
  transports: string[]
  backupEligible: boolean
  backupState: boolean
}

interface UserAccount {
  id: string
  username: string
  email: string
  displayName: string
  passkeys: PasskeyCredential[]
  createdAt: Date
  lastLoginAt?: Date
  mfaEnabled: boolean
}

class PasskeysManager {
  private db: IDBDatabase | null = null
  private readonly DB_NAME = 'PasskeysManagerDB'
  private readonly DB_VERSION = 1
  private readonly STORE_NAME = 'users'

  constructor() {
    this.initDB()
  }

  // Initialize IndexedDB for credential storage
  private async initDB(): Promise<void> {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.DB_NAME, this.DB_VERSION)

      request.onerror = () => reject(request.error)
      request.onsuccess = () => {
        this.db = request.result
        resolve()
      }

      request.onupgradeneeded = (event) => {
        const db = (event.target as IDBOpenDBRequest).result

        if (!db.objectStoreNames.contains(this.STORE_NAME)) {
          const store = db.createObjectStore(this.STORE_NAME, { keyPath: 'id' })
          store.createIndex('username', 'username', { unique: true })
          store.createIndex('email', 'email', { unique: true })
        }
      }
    })
  }

  // Generate secure random challenge
  private generateChallenge(): string {
    const array = new Uint8Array(32)
    crypto.getRandomValues(array)
    return Array.from(array, byte => byte.toString(16).padStart(2, '0')).join('')
  }

  // Convert ArrayBuffer to Base64URL
  private arrayBufferToBase64URL(buffer: ArrayBuffer): string {
    return btoa(String.fromCharCode(...new Uint8Array(buffer)))
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=/g, '')
  }

  // Convert Base64URL to ArrayBuffer
  private base64URLToArrayBuffer(base64url: string): ArrayBuffer {
    return Uint8Array.from(atob(base64url.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0)).buffer
  }

  // Generate unique user ID
  private generateUserId(): string {
    return this.arrayBufferToBase64URL(crypto.getRandomValues(new Uint8Array(16)))
  }

  // Create new user account
  async createUser(username: string, email: string, displayName: string): Promise<UserAccount> {
    if (!this.db) throw new Error('Database not initialized')

    // Check if user already exists
    const existingUser = await this.getUserByUsername(username)
    if (existingUser) {
      throw new Error('User already exists')
    }

    const user: UserAccount = {
      id: this.generateUserId(),
      username,
      email,
      displayName,
      passkeys: [],
      createdAt: new Date(),
      mfaEnabled: false
    }

    await this.saveUser(user)
    return user
  }

  // Register new passkey for user
  async registerPasskey(
    userId: string,
    passkeyName: string,
    authenticatorAttachment: 'platform' | 'cross-platform' = 'platform'
  ): Promise<PasskeyCredential> {
    if (!this.db) throw new Error('Database not initialized')

    const user = await this.getUserById(userId)
    if (!user) {
      throw new Error('User not found')
    }

    try {
      // Generate challenge
      const challenge = this.generateChallenge()

      // Create credential creation options
      const credentialCreationOptions: CredentialCreationOptions = {
        challenge: this.base64URLToArrayBuffer(challenge),
        rp: {
          name: "Passkeys Manager",
          id: window.location.hostname
        },
        user: {
          id: this.base64URLToArrayBuffer(user.id),
          name: user.username,
          displayName: user.displayName
        },
        pubKeyCredParams: [
          { alg: -7, type: "public-key" },   // ES256
          { alg: -257, type: "public-key" },  // RS256
          { alg: -8, type: "public-key" },    // Ed25519
        ],
        authenticatorSelection: {
          authenticatorAttachment,
          residentKey: 'required',
          userVerification: 'required'
        },
        extensions: {
          credProps: true,
          largeBlob: true
        },
        timeout: 60000,
        attestation: 'direct'
      }

      // Create credential
      const credential = await navigator.credentials.create({
        publicKey: credentialCreationOptions
      }) as PublicKeyCredential

      if (!credential) {
        throw new Error('Credential creation failed')
      }

      // Parse client data
      const clientDataJSON = JSON.parse(
        new TextDecoder().decode(credential.response.clientDataJSON)
      )

      // Extract authenticator info
      const authData = new Uint8Array(credential.response.authenticatorData)
      const flags = authData[32]
      const backupEligible = !!(flags & 0x08)
      const backupState = !!(flags & 0x10)

      // Create passkey record
      const passkey: PasskeyCredential = {
        id: this.arrayBufferToBase64URL(credential.rawId),
        name: passkeyName,
        createdAt: new Date(),
        deviceType: authenticatorAttachment,
        userHandle: user.id,
        publicKey: this.arrayBufferToBase64URL(credential.response.publicKey || new ArrayBuffer(0)),
        counter: 0,
        transports: clientDataJSON.transports || [],
        backupEligible,
        backupState
      }

      // Add passkey to user
      user.passkeys.push(passkey)
      await this.saveUser(user)

      console.log('Passkey registered successfully:', {
        name: passkeyName,
        id: passkey.id,
        deviceType: passkey.deviceType,
        backupEligible: passkey.backupEligible
      })

      return passkey

    } catch (error) {
      console.error('Passkey registration error:', error)
      throw new Error(`Passkey registration failed: ${error.message}`)
    }
  }

  // Authenticate user with passkey
  async authenticate(userHint?: string): Promise<{ user: UserAccount; credentialId: string }> {
    if (!this.db) throw new Error('Database not initialized')

    try {
      // Generate challenge
      const challenge = this.generateChallenge()

      // Get all available passkeys if no specific user hint
      let allowCredentials: PublicKeyCredentialDescriptor[] = []

      if (userHint) {
        const user = await this.getUserByUsername(userHint)
        if (user && user.passkeys.length > 0) {
          allowCredentials = user.passkeys.map(passkey => ({
            id: this.base64URLToArrayBuffer(passkey.id),
            type: 'public-key',
            transports: passkey.transports as AuthenticatorTransport[]
          }))
        }
      }

      // Create assertion options
      const assertionOptions: AssertionOptions = {
        challenge: this.base64URLToArrayBuffer(challenge),
        allowCredentials,
        userVerification: 'required',
        extensions: {
          largeBlob: true
        },
        timeout: 60000
      }

      // Get assertion
      const assertion = await navigator.credentials.get({
        publicKey: assertionOptions
      }) as PublicKeyCredential

      if (!assertion) {
        throw new Error('Authentication failed')
      }

      // Find user by credential ID
      const credentialId = this.arrayBufferToBase64URL(assertion.rawId)
      let authenticatedUser: UserAccount | null = null
      let matchedPasskey: PasskeyCredential | null = null

      // Search all users for matching credential
      for (const user of await this.getAllUsers()) {
        const passkey = user.passkeys.find(pk => pk.id === credentialId)
        if (passkey) {
          authenticatedUser = user
          matchedPasskey = passkey
          break
        }
      }

      if (!authenticatedUser || !matchedPasskey) {
        throw new Error('Invalid credential')
      }

      // Update last used timestamp
      matchedPasskey.lastUsedAt = new Date()
      authenticatedUser.lastLoginAt = new Date()
      await this.saveUser(authenticatedUser)

      console.log('Authentication successful:', {
        user: authenticatedUser.username,
        credentialId,
        passkeyName: matchedPasskey.name
      })

      return { user: authenticatedUser, credentialId }

    } catch (error) {
      console.error('Authentication error:', error)
      throw new Error(`Authentication failed: ${error.message}`)
    }
  }

  // List user's passkeys
  async listPasskeys(userId: string): Promise<PasskeyCredential[]> {
    const user = await this.getUserById(userId)
    return user ? user.passkeys : []
  }

  // Delete passkey
  async deletePasskey(userId: string, passkeyId: string): Promise<void> {
    const user = await this.getUserById(userId)
    if (!user) {
      throw new Error('User not found')
    }

    const passkeyIndex = user.passkeys.findIndex(pk => pk.id === passkeyId)
    if (passkeyIndex === -1) {
      throw new Error('Passkey not found')
    }

    // Remove passkey
    user.passkeys.splice(passkeyIndex, 1)
    await this.saveUser(user)
  }

  // Update passkey name
  async updatePasskeyName(userId: string, passkeyId: string, newName: string): Promise<void> {
    const user = await this.getUserById(userId)
    if (!user) {
      throw new Error('User not found')
    }

    const passkey = user.passkeys.find(pk => pk.id === passkeyId)
    if (!passkey) {
      throw new Error('Passkey not found')
    }

    passkey.name = newName
    await this.saveUser(user)
  }

  // Database operations
  private async saveUser(user: UserAccount): Promise<void> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.STORE_NAME], 'readwrite')
      const store = transaction.objectStore(this.STORE_NAME)
      const request = store.put(user)

      request.onsuccess = () => resolve()
      request.onerror = () => reject(request.error)
    })
  }

  private async getUserById(userId: string): Promise<UserAccount | null> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.STORE_NAME], 'readonly')
      const store = transaction.objectStore(this.STORE_NAME)
      const request = store.get(userId)

      request.onsuccess = () => resolve(request.result || null)
      request.onerror = () => reject(request.error)
    })
  }

  private async getUserByUsername(username: string): Promise<UserAccount | null> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.STORE_NAME], 'readonly')
      const store = transaction.objectStore(this.STORE_NAME)
      const index = store.index('username')
      const request = index.get(username)

      request.onsuccess = () => resolve(request.result || null)
      request.onerror = () => reject(request.error)
    })
  }

  private async getAllUsers(): Promise<UserAccount[]> {
    if (!this.db) throw new Error('Database not initialized')

    return new Promise((resolve, reject) => {
      const transaction = this.db!.transaction([this.STORE_NAME], 'readonly')
      const store = transaction.objectStore(this.STORE_NAME)
      const request = store.getAll()

      request.onsuccess = () => resolve(request.result || [])
      request.onerror = () => reject(request.error)
    })
  }

  // Export passkeys for backup
  async exportPasskeys(userId: string): Promise<string> {
    const user = await this.getUserById(userId)
    if (!user) {
      throw new Error('User not found')
    }

    // Create export data (excluding sensitive fields)
    const exportData = {
      user: {
        id: user.id,
        username: user.username,
        email: user.email,
        displayName: user.displayName
      },
      passkeys: user.passkeys.map(pk => ({
        id: pk.id,
        name: pk.name,
        createdAt: pk.createdAt,
        deviceType: pk.deviceType,
        transports: pk.transports,
        backupEligible: pk.backupEligible
      })),
      exportedAt: new Date().toISOString()
    }

    return JSON.stringify(exportData, null, 2)
  }

  // Check browser compatibility
  static checkCompatibility(): {
    supported: boolean
    platformAuthenticator: boolean
    conditionalUI: boolean
    largeBlob: boolean
  } {
    return {
      supported: !!(navigator.credentials && navigator.credentials.create && navigator.credentials.get),
      platformAuthenticator: !!(PublicKeyCredential as any).isUserVerifyingPlatformAuthenticatorAvailable,
      conditionalUI: !!(PublicKeyCredential as any).isConditionalMediationAvailable,
      largeBlob: 'publicKey' in PublicKeyCredential.prototype
    }
  }
}

// React Component Example
// import React, { useState, useEffect } from 'react'

// const PasskeysManager: React.FC = () => {
//   const [passkeysManager] = useState(() => new PasskeysManager())
//   const [currentUser, setCurrentUser] = useState<UserAccount | null>(null)
//   const [passkeys, setPasskeys] = useState<PasskeyCredential[]>([])
//   const [loading, setLoading] = useState(false)
//   const [error, setError] = useState<string | null>(null)

//   useEffect(() => {
//     const compatibility = PasskeysManager.checkCompatibility()
//     console.log('WebAuthn compatibility:', compatibility)
//   }, [])

//   const handleRegisterPasskey = async (name: string, deviceType: 'platform' | 'cross-platform') => {
//     if (!currentUser) return

//     setLoading(true)
//     setError(null)

//     try {
//       const passkey = await passkeysManager.registerPasskey(currentUser.id, name, deviceType)
//       setPasskeys(prev => [...prev, passkey])
//     } catch (err) {
//       setError(err.message)
//     } finally {
//       setLoading(false)
//     }
//   }

//   const handleAuthenticate = async (userHint?: string) => {
//     setLoading(true)
//     setError(null)

//     try {
//       const { user } = await passkeysManager.authenticate(userHint)
//       setCurrentUser(user)
//       const userPasskeys = await passkeysManager.listPasskeys(user.id)
//       setPasskeys(userPasskeys)
//     } catch (err) {
//       setError(err.message)
//     } finally {
//       setLoading(false)
//     }
//   }

//   return (
//     <div className="passkeys-manager">
//       {/* UI implementation here */}
//     </div>
//   )
// }

export default PasskeysManager
QuellcodetypescriptKomplex

MFA-Integration

Integration von WebAuthn mit bestehenden MFA-Systemen, Backup-Codes und Wiederherstellungsoptionen

Schwierigkeit

9/10

Geschätzte Zeit

45 min

Schlagwörter

webauthn, mfa, authentication, security, enterprise

Voraussetzungen

Advanced TypeScript, Security concepts, Cryptography, Enterprise auth

typescript
// WebAuthn MFA Integration - Enhanced Security with Multiple Factors
// Backup codes, recovery options, and enterprise features

interface MFAConfig {
  passkeysRequired: boolean
  backupCodesEnabled: boolean
  smsEnabled: boolean
  emailEnabled: boolean
  timeBasedOTPEnabled: boolean
  rememberDevice: boolean
  sessionTimeout: number
}

interface BackupCode {
  id: string
  code: string
  usedAt?: Date
  createdAt: Date
  expiresAt: Date
}

interface AuthSession {
  id: string
  userId: string
  deviceFingerprint: string
  createdAt: Date
  expiresAt: Date
  isTrusted: boolean
  lastUsedAt: Date
}

interface SecurityEvent {
  id: string
  userId: string
  type: 'login' | 'passkey_added' | 'passkey_removed' | 'mfa_enabled' | 'suspicious_activity'
  timestamp: Date
  ipAddress: string
  userAgent: string
  success: boolean
  details?: any
}

class WebAuthnMFAIntegration {
  private passkeysManager: PasskeysManager
  private config: MFAConfig
  private mfaSessions = new Map<string, AuthSession>()
  private securityEvents: SecurityEvent[] = []

  constructor(config: MFAConfig) {
    this.passkeysManager = new PasskeysManager()
    this.config = config
  }

  // Enhanced authentication with MFA
  async authenticateWithMFA(userHint?: string): Promise<{
    user: UserAccount
    requiresMFA: boolean
    mfaMethods: string[]
    sessionToken?: string
  }> {
    try {
      // First attempt WebAuthn authentication
      const { user, credentialId } = await this.passkeysManager.authenticate(userHint)

      // Check if additional MFA is required
      const requiresMFA = this.shouldRequireMFA(user)

      if (!requiresMFA) {
        // Create trusted session
        const sessionToken = await this.createTrustedSession(user)

        await this.logSecurityEvent(user.id, 'login', true, {
          method: 'passkey_only',
          credentialId
        })

        return {
          user,
          requiresMFA: false,
          mfaMethods: [],
          sessionToken
        }
      }

      // MFA required - return available methods
      const mfaMethods = this.getAvailableMFAMethods(user)

      await this.logSecurityEvent(user.id, 'login', false, {
        method: 'passkey',
        requiresMFA: true,
        credentialId
      })

      return {
        user,
        requiresMFA: true,
        mfaMethods,
        sessionToken: this.createTemporaryMFASession(user)
      }

    } catch (error) {
      // Log failed authentication attempt
      await this.logSecurityEvent('', 'login', false, {
        error: error.message,
        userHint
      })

      throw error
    }
  }

  // Complete MFA verification
  async completeMFA(
    tempSessionToken: string,
    mfaMethod: string,
    mfaData: any
  ): Promise<{ user: UserAccount; sessionToken: string }> {
    const tempSession = this.mfaSessions.get(tempSessionToken)
    if (!tempSession || tempSession.expiresAt < new Date()) {
      throw new Error('Invalid or expired MFA session')
    }

    const user = await this.passkeysManager['getUserById'](tempSession.userId)
    if (!user) {
      throw new Error('User not found')
    }

    let mfaVerified = false

    switch (mfaMethod) {
      case 'backup_code':
        mfaVerified = await this.verifyBackupCode(user.id, mfaData.code)
        break
      case 'totp':
        mfaVerified = await this.verifyTOTP(user.id, mfaData.token)
        break
      case 'sms':
        mfaVerified = await this.verifySMS(user.id, mfaData.code)
        break
      case 'email':
        mfaVerified = await this.verifyEmail(user.id, mfaData.code)
        break
      default:
        throw new Error('Unsupported MFA method')
    }

    if (!mfaVerified) {
      await this.logSecurityEvent(user.id, 'login', false, {
        mfaMethod,
        mfaData
      })
      throw new Error('MFA verification failed')
    }

    // Create trusted session
    const sessionToken = await this.createTrustedSession(user)

    // Clean up temporary session
    this.mfaSessions.delete(tempSessionToken)

    await this.logSecurityEvent(user.id, 'login', true, {
      mfaMethod,
      deviceTrusted: true
    })

    return { user, sessionToken }
  }

  // Generate backup codes
  async generateBackupCodes(userId: string, count: number = 10): Promise<BackupCode[]> {
    const user = await this.passkeysManager['getUserById'](userId)
    if (!user) {
      throw new Error('User not found')
    }

    const backupCodes: BackupCode[] = []
    const expiresAt = new Date()
    expiresAt.setFullYear(expiresAt.getFullYear() + 1) // Valid for 1 year

    for (let i = 0; i < count; i++) {
      const code = this.generateBackupCode()
      backupCodes.push({
        id: this.generateId(),
        code,
        createdAt: new Date(),
        expiresAt
      })
    }

    // Store backup codes (in production, encrypt these)
    await this.storeBackupCodes(userId, backupCodes)

    await this.logSecurityEvent(user.id, 'mfa_enabled', true, {
      type: 'backup_codes_generated',
      count
    })

    return backupCodes
  }

  // Setup TOTP (Time-based One-Time Password)
  async setupTOTP(userId: string): Promise<{
    secret: string
    qrCodeUrl: string
    backupCodes: BackupCode[]
  }> {
    const user = await this.passkeysManager['getUserById'](userId)
    if (!user) {
      throw new Error('User not found')
    }

    // Generate TOTP secret
    const secret = this.generateTOTPSecret()
    const issuer = encodeURIComponent('Passkeys Manager')
    const accountName = encodeURIComponent(user.email)
    const qrCodeUrl = `otpauth://totp/${issuer}:${accountName}?secret=${secret}&issuer=${issuer}`

    // Generate backup codes
    const backupCodes = await this.generateBackupCodes(userId)

    // Store TOTP secret (in production, encrypt this)
    await this.storeTOTPSecret(userId, secret)

    await this.logSecurityEvent(user.id, 'mfa_enabled', true, {
      type: 'totp_setup'
    })

    return { secret, qrCodeUrl, backupCodes }
  }

  // Verify TOTP token
  async verifyTOTP(userId: string, token: string): Promise<boolean> {
    const secret = await this.getTOTPSecret(userId)
    if (!secret) {
      return false
    }

    // Verify token (simplified - use proper TOTP library in production)
    const expectedToken = this.generateTOTPToken(secret)
    const isValid = token === expectedToken

    if (isValid) {
      await this.logSecurityEvent(userId, 'login', true, {
        mfaMethod: 'totp',
        tokenVerified: true
      })
    }

    return isValid
  }

  // Check if MFA is required
  private shouldRequireMFA(user: UserAccount): boolean {
    if (!this.config.passkeysRequired) return false

    // Always require MFA if user has it enabled
    if (user.mfaEnabled) return true

    // Require MFA for new devices or suspicious locations
    // This would include IP geolocation, device fingerprinting, etc.
    return this.isNewDevice() || this.isSuspiciousLocation()
  }

  // Get available MFA methods for user
  private getAvailableMFAMethods(user: UserAccount): string[] {
    const methods = []

    if (this.config.backupCodesEnabled) {
      methods.push('backup_code')
    }

    if (this.config.timeBasedOTPEnabled) {
      // Check if user has TOTP setup
      if (this.hasTOTPSetup(user.id)) {
        methods.push('totp')
      }
    }

    if (this.config.smsEnabled && user.email) {
      methods.push('sms')
    }

    if (this.config.emailEnabled && user.email) {
      methods.push('email')
    }

    return methods
  }

  // Create trusted session
  private async createTrustedSession(user: UserAccount): Promise<string> {
    const session: AuthSession = {
      id: this.generateId(),
      userId: user.id,
      deviceFingerprint: this.generateDeviceFingerprint(),
      createdAt: new Date(),
      expiresAt: new Date(Date.now() + this.config.sessionTimeout),
      isTrusted: true,
      lastUsedAt: new Date()
    }

    // Store session (in production, use secure session storage)
    await this.storeSession(session)

    return session.id
  }

  // Create temporary MFA session
  private createTemporaryMFASession(user: UserAccount): string {
    const session: AuthSession = {
      id: this.generateId(),
      userId: user.id,
      deviceFingerprint: this.generateDeviceFingerprint(),
      createdAt: new Date(),
      expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes
      isTrusted: false,
      lastUsedAt: new Date()
    }

    this.mfaSessions.set(session.id, session)

    return session.id
  }

  // Utility methods
  private generateBackupCode(): string {
    const characters = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789' // Remove confusing characters
    let code = ''
    for (let i = 0; i < 8; i++) {
      if (i > 0 && i % 4 === 0) code += '-'
      code += characters[Math.floor(Math.random() * characters.length)]
    }
    return code
  }

  private generateTOTPSecret(): string {
    const base32Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'
    let secret = ''
    for (let i = 0; i < 32; i++) {
      secret += base32Chars[Math.floor(Math.random() * base32Chars.length)]
    }
    return secret
  }

  private generateTOTPToken(secret: string): string {
    // Simplified TOTP generation - use proper library in production
    const timestamp = Math.floor(Date.now() / 30000) // 30-second intervals
    return (timestamp + secret.length).toString().slice(-6)
  }

  private generateDeviceFingerprint(): string {
    const canvas = document.createElement('canvas')
    const ctx = canvas.getContext('2d')
    if (ctx) {
      ctx.textBaseline = 'top'
      ctx.font = '14px Arial'
      ctx.fillText('Device fingerprint', 2, 2)
      return canvas.toDataURL().slice(-20)
    }
    return Math.random().toString(36).substring(2)
  }

  private generateId(): string {
    return Math.random().toString(36).substring(2) + Date.now().toString(36)
  }

  private isNewDevice(): boolean {
    // Implement device fingerprinting logic
    return Math.random() > 0.7 // 30% chance of new device for demo
  }

  private isSuspiciousLocation(): boolean {
    // Implement geolocation checking
    return Math.random() > 0.9 // 10% chance of suspicious location for demo
  }

  // Security logging
  private async logSecurityEvent(
    userId: string,
    type: SecurityEvent['type'],
    success: boolean,
    details?: any
  ): Promise<void> {
    const event: SecurityEvent = {
      id: this.generateId(),
      userId,
      type,
      timestamp: new Date(),
      ipAddress: '192.168.1.1', // Get from request in production
      userAgent: navigator.userAgent,
      success,
      details
    }

    this.securityEvents.push(event)

    // In production, store in secure logging system
    console.log('Security event:', event)

    // Alert on suspicious activity
    if (!success || type === 'suspicious_activity') {
      await this.alertSuspiciousActivity(event)
    }
  }

  private async alertSuspiciousActivity(event: SecurityEvent): Promise<void> {
    // Implement alert system (email, SMS, admin notification)
    console.warn('🚨 Suspicious activity detected:', event)
  }

  // Storage methods (implement with your preferred storage)
  private async storeBackupCodes(userId: string, codes: BackupCode[]): Promise<void> {
    // Implement secure storage
  }

  private async storeTOTPSecret(userId: string, secret: string): Promise<void> {
    // Implement secure storage
  }

  private async getTOTPSecret(userId: string): Promise<string | null> {
    // Implement secure retrieval
    return null
  }

  private async hasTOTPSetup(userId: string): Promise<boolean> {
    // Check if TOTP is configured for user
    return false
  }

  private async storeSession(session: AuthSession): Promise<void> {
    // Implement secure session storage
  }

  // Enterprise features
  async getSecurityReport(userId: string): Promise<{
    user: UserAccount
    recentEvents: SecurityEvent[]
    trustedDevices: AuthSession[]
    securityScore: number
    recommendations: string[]
  }> {
    const user = await this.passkeysManager['getUserById'](userId)
    if (!user) {
      throw new Error('User not found')
    }

    const recentEvents = this.securityEvents
      .filter(event => event.userId === userId)
      .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime())
      .slice(0, 50)

    const trustedDevices = Array.from(this.mfaSessions.values())
      .filter(session => session.userId === userId && session.isTrusted)

    const securityScore = this.calculateSecurityScore(user, recentEvents)
    const recommendations = this.generateSecurityRecommendations(user, securityScore)

    return {
      user,
      recentEvents,
      trustedDevices,
      securityScore,
      recommendations
    }
  }

  private calculateSecurityScore(user: UserAccount, events: SecurityEvent[]): number {
    let score = 50 // Base score

    // Add points for passkeys
    score += Math.min(user.passkeys.length * 10, 30)

    // Add points for MFA enabled
    if (user.mfaEnabled) score += 20

    // Subtract points for failed login attempts
    const failedLogins = events.filter(e => e.type === 'login' && !e.success).length
    score -= Math.min(failedLogins * 5, 20)

    return Math.max(0, Math.min(100, score))
  }

  private generateSecurityRecommendations(user: UserAccount, score: number): string[] {
    const recommendations = []

    if (user.passkeys.length === 0) {
      recommendations.push('Add at least one passkey for passwordless authentication')
    }

    if (user.passkeys.length === 1) {
      recommendations.push('Add a backup passkey for account recovery')
    }

    if (!user.mfaEnabled) {
      recommendations.push('Enable multi-factor authentication for enhanced security')
    }

    if (score < 70) {
      recommendations.push('Review recent security events for suspicious activity')
    }

    return recommendations
  }
}

// Usage Example
// const mfaConfig: MFAConfig = {
//   passkeysRequired: true,
//   backupCodesEnabled: true,
//   smsEnabled: true,
//   emailEnabled: true,
//   timeBasedOTPEnabled: true,
//   rememberDevice: true,
//   sessionTimeout: 24 * 60 * 60 * 1000 // 24 hours
// }
//
// const mfaIntegration = new WebAuthnMFAIntegration(mfaConfig)
//
// // Authenticate with MFA
// const authResult = await mfaIntegration.authenticateWithMFA('[email protected]')
// if (authResult.requiresMFA) {
//   // Show MFA options UI
//   console.log('Available MFA methods:', authResult.mfaMethods)
//
//   // Complete MFA (user enters backup code)
//   const finalResult = await mfaIntegration.completeMFA(
//     authResult.sessionToken!,
//     'backup_code',
//     { code: 'ABCD-1234-EFGH' }
//   )
//   console.log('Authentication complete:', finalResult)
// }

export default WebAuthnMFAIntegration

Werkzeuge

Tools, die oft mit diesem Beispiel genutzt werden

Verwandt

Verwandte Beispielsammlungen

Leitfaden zur Tool-Nutzung

Kontext zum Verständnis dieser Beispielsammlung

Titel

WebAuthn Passwortlose Authentifizierung

Beschreibung

Web Authentication API Beispiele mit biometrischer Authentifizierung, Sicherheitsschlüsseln und passwortlosen Anmeldesystemen

Überblick

Web Authentication API Beispiele mit biometrischer Authentifizierung, Sicherheitsschlüsseln und passwortlosen Anmeldesystemen

Wann verwenden

  • Use this sample set when you want reference inputs for WebAuthn Passwortlose Authentifizierung.
  • Use it to preview output formats and compare related sample variants.

So funktioniert es

  1. 1Open a sample entry to inspect the prepared example payload or asset.
  2. 2Compare it with related tools to understand how the workflow connects.

Anwendungsfälle

  • WebAuthn Hello World
  • Passkeys-Manager-System
  • MFA-Integration

FAQ

What is included in WebAuthn Passwortlose Authentifizierung?

This page includes curated sample entries, related tools, and neighboring sample collections for WebAuthn Passwortlose Authentifizierung.

Start
Werkzeuge3197
Beispiele593
Visualisierungen461
Dateibetrachter103
Themen229
Schlagwörter333
Bilder, Audio & Video655

Werkzeuge für Bild-, Audio- und Videobearbeitung, Konvertierung und Optimierung

Mathe, Datum & Finanzen644

Rechner, Zahlenwerkzeuge, Datumslogik, Statistik und Finanztools

Design & Farbe296

Werkzeuge für Farben, Layouts, Grafiken, visuelle Gestaltung und Designhilfen

Text & Schreiben209

Werkzeuge für Schreiben, Bereinigung, Formatierung, Extraktion und Textanalyse

Entwicklung & Web193

Entwicklerwerkzeuge, Netzwerk-Utilities, Web-Debugging und Automatisierungshelfer

Konvertierung & Kodierung175

Werkzeuge für Format-, Datei-, Archiv-, Einheiten- und Kodierungskonvertierung

UI-Screenshot strukturieren, prüfen und an die Entwicklung übergeben
Klavierskizze erstellen, MIDI prüfen und Hördemo übergeben
Retro-Spieltexturen prüfen und Ressourcen übergeben
Screenshot-Anleitungen prüfen und Schulungsunterlagen übergeben
Responsive Seitenänderungen prüfen und Bildnachweise übergeben

© 2026 Elysia Tools. Alle Rechte vorbehalten.

DokumentationTarifeÜber unsNutzungsbedingungenDatenschutzerklärungCookiesKontakt

Cryptography

WebAuthn-Passkey-Assertion-Decoder und Challenge-Debugger

Dekodiert clientDataJSON, authenticatorData, Flags, rpIdHash und signCount; prüft ES256, RS256 oder Ed25519 bei bereitgestelltem Public Key.

Development

HTTP-Header-Analysator

Analysiert HTTP-Header, Sicherheitskonfigurationen und Antwortinformationen

Security

JWT-Decoder

JWT-Tokens dekodieren

Security

JWT-Decoder und Sicherheits-Auditor

Dekodiert JWT-Header und -Payload, prueft HS256- oder RS256-Signaturen und markiert Risiken bei Algorithmus, Ablauf und sensiblen Claims

Security

JWT-Generator

JWT-Tokens mit benutzerdefinierten Claims und Algorithmen generieren

Security

Passwort-Stärkemesser

Schätzt die echte Passwortstärke mit Shannon-Entropie, zxcvbn-Mustererkennung (l33t, Wörterbuch, Sequenzen, Wiederholungen) und Brute-Force-Knackzeit für verschiedene Angriffsszenarien. Das Passwort wird lokal ausgewertet und nirgendwo hingesendet.

Security

Passwort-Validator

Überprüft die Passwortstärke und gängige Sicherheitsanforderungen

Security

XSS-Payload-Detektor

Erkennt XSS-Angriffsvektoren (Cross-Site Scripting) in Eingabezeichenfolgen

Sicherheit

JWT-Beispiele

Umfassende JWT-Beispiele von der grundlegenden Token-Struktur bis zu fortgeschrittenen Sicherheitsimplementierungen

Sicherheit

Zero Trust Architektur-Beispiele

Umfassende Zero Trust Architekturbeispiele mit Authentifizierung, Netzsegmentierung und Zugriffskontrolle

Validierung

Starke Passwort-Beispiele

Sammlung von Passwörtern mit verschiedenen Stärkestufen für Validierungstests