A Pterodactyl Panel 2.0 extension by Olivier DUTOIT. Users sign in with a hardware security key (YubiKey or any FIDO2 / WebAuthn authenticator, passkeys included):
- At the two-factor checkpoint. An account with a key gets a "Security key" screen after its password, in place of the authenticator code form, and the key prompt opens at once. With an authenticator app too, "Use my authenticator app or a recovery code" switches to the panel's code form, where "Use a security key" brings the key back. An account with a key and no authenticator app also gets this checkpoint (and no code form).
- Without a password (optional, off by default). Admin → Extensions → Security Keys → Passwordless sign-in adds "Sign in with a security key" to the login page. Only passkeys that verify the user (PIN or biometrics) are accepted, and they stand for both factors. Tick "Use for passwordless sign-in" when adding the key: without it the key stores no passkey and only works as a second factor.
- Account → Security Keys to add (password asked), rename and remove (password asked) keys.
- Admin → Users → a user → Security Keys to remove a lost key.
- A key that passes ends the sign-in through the panel's own
CompletesLogins::establish()(session regenerated,DirectLoginandauth:tokenactivity), as the TOTP checkpoint does. wrapAction(CompletesLogins)issues the panel'sLoginCheckpoint(5 minutes) for key-only accounts, under the extension's own session key;pendingCheckpoint()returns it to the core checkpoint and to the extension alike.- Visitor endpoints live under
/extensions/security-keys/{checkpoint,login}in thewebgroup (session + CSRF), behindguestandthrottle:authentication, and failures count towards the same lockout as the panel's login (ThrottlesLogins). - Challenges are kept in the session, single use, 150 seconds. The assertion's origin must be
exactly the one of
APP_URL, the relying party id is its host, and the signature counter is checked. Key management routes refuse API keys (RequireSessionAuthentication). - WebAuthn verification:
lbuchs/webauthn2.2.0 (MIT, no dependencies) bundled invendor/, autoloader suffixOlivierDutoitSecurityKeysExtension. - Sign-in pages are slots (
auth.checkpoint.after,auth.login.form.after): plain extensions cannot override guest views. While the key's screen shows, the checkpoint slot hides the panel's code form (its closest siblings holding a form, up to four levels above the slot) and shows it again on request. The screen is drawn with the SDK's UI kit (Empty,Button,Alert), so the active theme's skins style it.
APP_URL must be the HTTPS address users open the panel at: keys registered on one hostname do
not work on another.
php artisan p:extension:install pterodactyl-security-keys-1.0.1.zip --enable --replaceEnabling runs database/migrations (table security_key_credentials); no php artisan migrate
needed. Requires PHP 8.3 with openssl.
Locked out (key lost, no recovery code): an admin removes the key on the user's Security Keys
tab, or php artisan p:extension:disable security-keys turns the extension off (key-only accounts
then sign in with their password alone).