Skip to content

WebAuthn パスワードレスログイン

Doggy は web-auth/webauthn-symfony-bundle に基づいて WebAuthn 標準認証を実装し、指紋、顔認証、セキュリティキーによるログインをサポートします。

概要

WebAuthn 認証情報は src/Entity/Security/WebauthnCredential.php(テーブル webauthn_credentials)に保存され、App\Entity\Organization\Employee(ユーザーエンティティ)に関連付けられます。

認証情報リポジトリは PublicKeyCredentialSourceRepositoryInterface を実装し、WebAuthn 認証情報の保存とクエリをサポートします。

設定

yaml
# config/packages/webauthn.yaml
webauthn:
  credential_repository: 'App\Repository\Security\WebauthnCredentialRepository'
  user_repository: 'App\Repository\Organization\EmployeeRepository'
  creation_profiles:
    default:
      rp:
        name: '%env(RELYING_PARTY_NAME)%'
        id: '%env(RELYING_PARTY_ID)%'
      public_key_credential_parameters:
        - -7    # ES256
        - -257  # RS256
      authenticator_selection_criteria:
        resident_key: required
        user_verification: required
  request_profiles:
    default:
      rp_id: '%env(RELYING_PARTY_ID)%'
      user_verification: required
  allowed_origins: ['http://localhost:8000']

セキュリティファイアウォール設定

yaml
# config/packages/security.yaml
security:
  firewalls:
    main:
      custom_authenticator: App\Security\AppCustomAuthenticator
      webauthn:
        success_handler: App\Security\WebauthnSuccessHandler
        authentication:
          enabled: true
          routes:
            options_path: '/login/webauthn/options'
            result_path: '/login/webauthn/result'

認証情報管理

php
// src/Entity/Security/WebauthnCredential.php
class WebauthnCredential
{
    private string $publicKeyCredentialId;
    private string $type;          // 'public-key'
    private array $transports;     // ['usb', 'nfc', 'internal']
    private string $attestationType;
    private string $credentialPublicKey;
    private string $userHandle;    // Employee ID
    private int $counter;
    private ?string $deviceName;   // 如 "Chrome on Mac"

    #[ORM\ManyToOne(targetEntity: Employee::class, inversedBy: 'passkeys')]
    private ?Employee $employee = null;
}

ログインフロー

Passkey の登録

  1. ユーザーはログイン後にセキュリティ設定へ入る(/user/webauthn/register/options
  2. ブラウザが WebAuthn API を呼び出して認証情報を作成
  3. 結果を /user/webauthn/register/result に送信
  4. 公開鍵認証情報を webauthn_credentials テーブルに保存

パスワードレスログイン

  1. ユーザー名を入力し、「Passkey ログイン」をクリック
  2. POST を /login/webauthn/options に送信してチャレンジを取得
  3. ブラウザが WebAuthn API を呼び出して署名
  4. 結果を /login/webauthn/result に送信
  5. WebauthnSuccessHandler がログイン成功を処理(デバイス記録、最終使用時間の更新)

サクセスハンドラー

App\Security\WebauthnSuccessHandler はログイン成功後に:

  1. 認証情報の最終使用時間を更新
  2. デバイス名を自動認識(User-Agent 解析)
  3. 初回ログインかをチェックし、パスワード変更をガイド
  4. パスワードリセットフローをサポート

WebAuthn 認証情報リポジトリ

App\Repository\Security\WebauthnCredentialRepository の実装:

  • findOneByCredentialId(): 認証情報を検索
  • findAllForUserEntity(): ユーザーの全認証情報を取得
  • saveCredentialSource(): 認証情報の作成/更新
  • parseUserAgent(): デバイス名の識別

MIT ライセンスでオープンソース | Copyright © 2026 Doggy