MageOS Passkey Authentication

March 17, 2026 · View on GitHub

Latest Stable Version License Total Downloads

Passwordless login for Magento 2 customer accounts using the WebAuthn/FIDO2 standard. Customers register passkeys (biometric, security key, or device PIN) and sign in with a single tap — no passwords to remember, phish, or leak.

Built on web-auth/webauthn-lib v5.

Key Features

Passwordless Authentication

  • One-tap login: Customers authenticate with fingerprint, Face ID, Windows Hello, or a hardware security key
  • Token-based sessions: Successful passkey authentication issues a standard Magento customer token
  • Anti-enumeration: Authentication options return a valid response even for non-existent emails, preventing account discovery

Credential Management

  • My Account page: Customers add, rename, and delete passkeys from their account dashboard
  • Clone detection: Sign-count tracking detects copied authenticators

Store Admin Controls

  • Enrollment prompts: Optional banners on account pages after password login or account creation to encourage passkey adoption
  • Rate limiting: Built-in cache-based limits on options requests and verification failures

Requirements

ComponentVersion
PHP8.2+
Magento Open Source / Mage-OS2.4.x
HTTPSRequired (WebAuthn does not work over plain HTTP)

Installation

composer require mage-os/module-passkey-auth
bin/magento setup:upgrade

Configuration

Navigate to Stores > Configuration > Customers > Customer Configuration > Passkey Authentication.

SettingDescriptionDefault
Enable Passkey AuthenticationMaster on/off switchYes
Prompt After Password LoginShow enrollment banner on account pages after password sign-inYes
Prompt After Account CreationShow enrollment banner on account pages after registrationNo

The Relying Party (RP) ID and allowed origins are derived automatically from the store's base URL — no manual configuration required.

WebAuthn parameters (user verification, attestation conveyance, ceremony timeout, authenticator attachment, and max credentials per customer) use sane defaults internally and are not exposed as admin settings.

Architecture

Service Contracts

All business logic is exposed through Api interfaces:

InterfaceImplementationPurpose
RegistrationOptionsInterfaceRegistration\OptionsGeneratorGenerate WebAuthn creation options
RegistrationVerifierInterfaceRegistration\VerifierVerify attestation and store credential
AuthenticationOptionsInterfaceAuthentication\OptionsGeneratorGenerate WebAuthn request options
AuthenticationVerifierInterfaceAuthentication\VerifierVerify assertion and issue token
CredentialRepositoryInterfaceCredentialRepositoryCredential CRUD
CredentialManagementInterfaceCredentialManagementList, rename, delete credentials
Data\CredentialInterfaceData\CredentialCredential data transfer object
Data\AuthenticationResultInterfaceData\AuthenticationResultAuthentication result DTO

REST API

MethodEndpointAuthPurpose
POST/V1/passkey/registration/optionsCustomer (self)Get creation options for navigator.credentials.create()
POST/V1/passkey/registration/verifyCustomer (self)Submit attestation response, receive stored credential
POST/V1/passkey/authentication/optionsAnonymousGet request options for navigator.credentials.get()
POST/V1/passkey/authentication/verifyAnonymousSubmit assertion response, receive customer token
GET/V1/passkey/credentialsCustomer (self)List customer's registered passkeys
PUT/V1/passkey/credentials/:entityIdCustomer (self)Rename a passkey
DELETE/V1/passkey/credentials/:entityIdCustomer (self)Delete a passkey

Events

EventPayloadFired When
passkey_credential_register_aftercustomer_id, credentialNew passkey registered
passkey_authentication_successcustomer_id, credentialSuccessful passkey login
passkey_authentication_failurecredential_id, reasonFailed passkey login
passkey_credential_remove_aftercustomer_id, credential_idPasskey deleted

Database

passkey_credential — Stores registered WebAuthn credentials. One customer can have multiple credentials (up to 10). Foreign key to customer_entity with CASCADE delete.

passkey_challenge — Temporary single-use challenges with a 5-minute TTL. Cleaned up by the passkey_challenge_cleanup cron job.

Extensibility

Observing Passkey Events

Create an observer in your module's etc/events.xml:

<event name="passkey_authentication_success">
    <observer name="my_module_passkey_login" instance="Vendor\Module\Observer\PasskeyLogin"/>
</event>

Overriding Services

All service contracts can be replaced via DI preferences in etc/di.xml:

<preference for="MageOS\PasskeyAuth\Api\AuthenticationVerifierInterface"
            type="Vendor\Module\Model\CustomVerifier"/>

Frontend Customization

The module provides three jQuery UI widgets that can be extended via RequireJS mixins:

  • passkeyLogin — Login page authentication flow
  • passkeyManage — My Account credential management (add/rename/delete)
  • enrollmentPrompt — Enrollment banner after password login

Templates are in view/frontend/templates/ and can be overridden via theme fallback. Styles use Luma/blank theme variables and patterns (.message.info, .data.table, .action.primary) for native theme consistency.

Security

  • HTTPS required: WebAuthn ceremonies are rejected by browsers on non-secure origins. The module detects non-secure contexts and displays a specific error message.
  • Single-use challenges: Each challenge token is consumed on verification and cannot be reused.
  • Rate limiting: Options generation (10 requests/60s) and verification failures (5 failures/900s) are rate-limited per customer.
  • Sign-count validation: Detects cloned authenticators by tracking the signature counter.
  • Anti-enumeration: Authentication options return a valid (but unusable) response for non-existent email addresses.
  • Ownership enforcement: All credential operations validate that the credential belongs to the requesting customer.

Contributing

Issues and pull requests welcome on GitHub.

License

This module is licensed under the Open Software License 3.0.

Support