WebAuthn / Passkeys in OpenACS – Background and Terminology
This post provides some background on passkeys, the related standards, and the terminology used in the current OpenACS implementation. It is intended as a short technical introduction for OpenACS developers and site administrators.
What are passkeys?
Passkeys are a passwordless authentication mechanism based on public-key cryptography using eliptic curves (EC).
Instead of authenticating with a shared secret (password), the user authenticates by proving possession of a private key that never leaves their device.
From a user’s perspective, passkeys typically involve:
- Face ID / Touch ID
- Fingerprint sensors
- Device PIN / unlock mechanism
- External security keys (USB / NFC / Bluetooth)
No password is typed, transmitted, reused, or stored on the server.
The standards stack
Passkeys are not a proprietary feature. They are the user-facing expression of a well-defined standards stack:
WebAuthn (W3C)
Web Authentication (WebAuthn) is the web standard that defines how browsers interact with servers to:
- register a credential
- authenticate using that credential
The relevant browser APIs are:
navigator.credentials.create()
navigator.credentials.get()
OpenACS integrates at this layer.
FIDO2 (FIDO Alliance)
FIDO2 is the broader ecosystem specification that includes:
- WebAuthn (browser ↔ server)
- CTAP (client ↔ authenticator, e.g. phone, security key)
In practice, “FIDO2 login” usually means WebAuthn-based authentication.
Public-key cryptography (core concept)
Each passkey consists of:
- a private key, securely stored on the user’s device
- a public key, stored by the server
Authentication is done via a cryptographic challenge/response, not by sharing secrets.
Important properties:
- The private key cannot be extracted
- The public key is not sensitive
- Credentials are bound to a Relying Party ID (rpID) (typically a domain)
CBOR / COSE (binary formats)
WebAuthn uses compact binary encodings internally:
- CBOR (RFC 8949): a binary alternative to JSON
- COSE (RFC 9052): cryptographic key and signature structures encoded in CBOR
The OpenACS implementation relies on recent NaviServer support for CBOR decoding and COSE key handling.
What exactly is a “passkey”?
A passkey is:
- a WebAuthn credential
- backed by a public/private key pair
- typically discoverable (resident) on the device
- often synchronized by the platform vendor
Examples:
- Apple iCloud Keychain (Safari, Chrome on iOS/macOS)
- Google Password Manager (Chrome, Android)
- Windows Hello
- Hardware security keys (e.g. YubiKey)
From OpenACS’ point of view, all of these are simply WebAuthn credentials.
Who is using passkeys today?
Passkeys are widely deployed in production:
- Apple (Apple ID)
- Google (Google Accounts)
- Microsoft (Microsoft Accounts, Windows Hello)
- GitHub (developer authentication)
- PayPal, Amazon, Shopify, and others
All major browsers support WebAuthn:
- Safari
- Chrome
- Firefox
- Edge
Why this matters for OpenACS
For OpenACS sites, passkeys provide:
- Strong phishing resistance
- No shared secrets on the server
- Better user experience on modern devices
- A standards-based, future-proof authentication mechanism
For users:
- Faster login
- Biometric authentication where supported
- Multiple devices per account
For site administrators:
- Reduced password-related support
- Improved security posture
- Compatibility with current browser and OS platforms
Current status in OpenACS
The current WebAuthn support in OpenACS provides:
- Passkey registration
- Passkey-based login
- Credential management per user
- Integration with OpenACS authentication and session handling
This is intentionally introduced as a preview / foundation, allowing us to gain operational experience before finalizing UX details and policies.
Testing on openacs.org
The new WebAuthn / passkey support is installed for testing on openacs.org.
- To register and manage passkeys, visit the /pvt/home page
- The login page will offer a “Sign in with passkey” action when appropriate
- Note: in the current preview, passkey logins are configured to log the user out when the session expires, to keep behavior explicit during testing
Feedback from real-world testing is very welcome.