OpenACS WebAuthn / Passkeys


This package adds WebAuthn (passkey) authentication support to OpenACS running on NaviServer.

  • Login flows for passkeys (passkey-first, identifier-first, and auto mode)

  • JSON endpoints for WebAuthn registration/authentication ceremonies

  • Optional diagnostics endpoint for troubleshooting browser/device capabilities

Endpoints

  • GET /webauthn/auth/options: Returns WebAuthn assertion options for navigator.credentials.get().

Additional endpoints are provided for registration/authentication flows as part of the package”™s API surface.

Development Notes

  • JSON endpoints validate inputs using webauthn::json_contract (similar in spirit to ad_page_contract, but returning JSON errors instead of HTML complaints).

  • WebAuthn request options are per-request and must not be cached.

Configuration

The WebAuthn relying party identifier (RP ID) can be configured via the NaviServer configuration file. The RP ID must match the effective host name used to access the site (for example, localhost versus 127.0.0.1), otherwise browsers will reject WebAuthn operations.

To set the RP ID explicitly, add the following stanza:

ns_section ns/server/$server/acs/webauthn {
    ns_param RpID "YOUR-RPID"
}

If RpID is not specified, the package first tries to use the configured server name ([ns_info server]). This value is typically correct in Docker-based configurations and in standard installations derived from the sample openacs-config.tcl. When the server name is not appropriate for use as an RP ID, the package falls back to localhost.

Common Pitfalls

A frequent source of WebAuthn failures during development is a mismatch between the configured RP ID and the host name used to access the site. Browsers enforce strict origin and RP ID checks and will reject requests that do not match.

  • Accessing the site via https://127.0.0.1 while the RP ID is localhost (or vice versa). In this case, browsers typically fail with a SecurityError such as “The operation is insecure.”

  • Using an IP address as RP ID while accessing the site via a host name, or changing the effective host name without updating the RP ID.

For local development, it is recommended to consistently use https://localhost and either rely on the default RP ID resolution or explicitly configure RpID to localhost.

Requirements

This package requires recent versions of both NaviServer and OpenACS.

NaviServer

A recent NaviServer version with the following features enabled is required:

  • CBOR support (RFC 8949): Used for decoding WebAuthn attestation objects and authenticator data.

  • Extended cryptographic support for EC keys, including:

    • Importing and creating elliptic-curve keys from affine coordinates

    • COSE / WebAuthn-compatible key handling

    • ECDSA verification suitable for ES256 credentials

  • OpenSSL with modern EC support: NaviServer must be built against a recent OpenSSL version providing contemporary elliptic-curve primitives required by WebAuthn.

In practice, this means a current NaviServer 5.x build with ns_cbor and enhanced ns_crypto functionality enabled.

OpenACS

OpenACS HEAD: Use the newest available version from the HEAD branch. The recent version of acs-subsite is needed for inclusion of the WebAuthn UI elements. Otherwise, branch acs-5-10 should be sufficient.

Older OpenACS releases are not supported, as this package relies on recent authentication infrastructure, filter behavior, and JSON-based endpoint patterns.

License

SPDX-License-Identifier: MPL-2.0

Copyright (c) 2026 Gustaf Neumann

This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.