campbell-moore.com / projects
OPNsense plugin

os-webauthn

Passkeys and password-manager-friendly one-time codes for the OPNsense firewall, without an identity provider on the firewall itself.

Updated · version 0.2

Download 0.2 Donate

Install it

You need OPNsense 26.7 or later. The library package is built for PHP 8.5, which OPNsense 26.7 uses.

  1. Open a shell on the firewall as root. Log in with SSH, or select option 8 (Shell) at the console.
  2. Run these four commands:
    fetch -o /tmp/php85-webauthn.pkg "https://campbell-moore.com/downloads/os-webauthn/latest?role=dependency"
    fetch -o /tmp/os-webauthn.pkg    "https://campbell-moore.com/downloads/os-webauthn/latest"
    pkg add /tmp/php85-webauthn.pkg /tmp/os-webauthn.pkg
    configctl webgui restart
  3. Reload the web interface in your browser.

The plugin adds two items under System → Access:

  • 2FA is where each user sets up their own passkey or one-time code.
  • 2FA Settings is for administrators. It holds the settings for everyone and the list of enrolled passkeys.

The links always point to the current release, so the commands do not go out of date.

Why there are two files

The plugin and its library change at different times. Two packages let you update one without reinstalling the other.

  • php85-webauthn is the WebAuthn protocol library. It does the cryptography. It is a general-purpose PHP library that I did not write; I packaged it for the firewall. Without it, the plugin still installs, but it does not offer passkeys.
  • os-webauthn-devel is the plugin: the settings page, the enrolment flow and the sign-in screen.

The pkg add command above installs both files.

Set up a passkey

  1. Open the web interface by its hostname. Browsers do not allow passkeys on an IP address.
  2. Open System → Access → 2FA Settings, then the Passkeys tab.
  3. Select Enable passkey sign-in, then select Save.
  4. Open System → Access → 2FA, then the Passkey tab.
  5. Type a name for the key, then select Register key.
  6. Select Use the key now. The plugin saves the key only after this test sign-in works.

The login page now shows a passkey button next to the password form.

Set up one-time codes

  1. Open System → Access → 2FA Settings. On the One-time codes tab, select Create it.
  2. Open System → Access → 2FA. On the One-time code tab, select Generate.
  3. Scan the QR code with your authenticator app or password manager.
  4. Type the current code, then select Verify and save.
  5. Make sure that every user who signs in has done steps 2 to 4.
  6. Go back to 2FA Settings and select Require codes now.
  7. Keep this session open. Sign in from a second browser to test.

The code has its own box on the login page, so a password manager can fill it. For sudo, SSH with a password and the console, type the code straight after the password, with no space. The Other ways in section of 2FA Settings sets which of these ask for a code. A passkey works only in the browser.

If something goes wrong

The 2FA items are not in the menu.

  1. Make sure your account has the 2FA privileges. Administrators have them. For other users, add them in System → Access → Groups.
  2. Run rm -f /var/lib/php/tmp/opnsense_menu_cache.xml /var/lib/php/tmp/opnsense_acl_cache.json, then reload the page.
  3. If the items are still missing, run pkg info os-webauthn-devel. The output shows if the package is installed.

The passkey tab says passkeys are not available. You opened the web interface by IP address, or php85-webauthn is not installed.

You think you are locked out. The plugin never turns off password sign-in. Passkeys are added next to the password.

Caution: Require codes now makes a one-time code necessary. Do not select it until your code works in a second browser.

If a user loses their authenticator after codes are required, remove their second factor as root:

  1. Open a shell on the firewall as root.
  2. Run /usr/local/opnsense/scripts/webauthn/reset2fa.php remove username.

This removes the user's code and passkeys. Their password does not change. The audit log records each removal.

Remove it

  1. Run pkg delete os-webauthn-devel.
  2. Run configctl webgui restart.

Password sign-in works during and after the removal. The plugin keeps its replay counters in /var/db/webauthn, so a reinstall cannot replay an old code. To remove them too, run rm -rf /var/db/webauthn.

What it actually does

Signs you in with a passkey instead of a password typed into the firewall's login form. A passkey is a credential held in a security key, a phone or a password manager.

It also adds one-time codes that a password manager can fill. The stock implementation does not allow that.

The bit worth knowing

Auditing the existing one-time-password path while building this surfaced a timing weakness in OPNsense's own TOTP comparison. It was reported, and the hardening fix now ships in OPNsense core. So the audit improved the thing it was auditing, whether or not you ever install this.

Requirements and licence

OPNsense 26.7 or later.

The plugin is PolyForm Noncommercial 1.0.0. It is free for personal and non-commercial use. For commercial use, ask for a separate licence. The bundled WebAuthn library keeps its own terms.

Releases

0.2
2026-09-16

Passkey registration and sign-in, one-time codes a password manager can fill, and the packaging fixed so the plugin survives an OPNsense major upgrade. Install php85-webauthn first - or give pkg add both files at once, as the instructions above do.