REST API for Wax
A plug that exposes the FIDO2 REST API 7. Transport Binding Profil.
This Plug has been created mainly for use by
WaxFidoTestSuiteServer, but
could be useful for those who want to implement WebAuthn authentication using
javascript to retrieve challenges. Feedback would be appreciated, especially on the
callback module.
def deps do
[
{:wax_api_rest, "~> 0.5.0"}
]
endIn a Phoenix router, forward a route to the WaxAPIREST.Plug:
defmodule MyApp.Router do
use Phoenix.Router
forward "/webauthn", WaxAPIREST.Plug, callback: MyApp.WebAuthnCallbackModule
endIf you're using Plug.Router:
defmodule MyApp.Router do
use Plug.Router
forward "/webauthn", to: WaxAPIREST.Plug, callback: MyApp.WebAuthnCallbackModule
endAn implementation of the WaxAPIREST.Callback module must be provided as an option or
in the configuration file.
This callback is responsible for:
- returning the current user's information (id, display name...)
- returning the current user's registered WebAuthn keys
- saving backend (for instance in the cookie session)
- registering new WebAuthn keys
- setting authentication status once authenticated
Refer to the callback module for more information.
An example implementation can be found in the WaxFidoTestSuiteServer project (but don't use it as-is).
In addition to Wax's options (t:Wax.opt/0), the following options can be used
specifically with this plug:
:callback_module[mandatory]: the callback module:rp_name: a human-palatable identifier for the Relying Party. If not present, defaults to the RP id (Waxoption:rp_id):pub_key_cred_params: the list of allowed credential algorithms. Defaults to[-36, -35, -7]which are ES512, ES384 and ES256 in this order of precedence. These values have been chosen using the following security analysis: Security Concerns Surrounding WebAuthn: Don't Implement ECDAA (Yet):attestation_conveyance_preference: the attestation conveyance preference. Defaults to the value of the request or, if absent, to"none"
For instance, using Phoenix:
defmodule MyApp.Router do
use Phoenix.Router
forward "/webauthn", WaxAPIREST.Plug, [
callback_module: MyApp.WebAuthnCallbackModule,
rp_name: "My site",
pub_key_cred_params: [-36, -35, -7, -259, -258, -257] # allows RSA algs
]
end
See t:WaxAPIREST.Plug.opt/0 for more information, including option precedence rules.
Important: This library does not implement rate limiting. Applications using this library must implement rate limiting to prevent:
- Brute-force authentication attempts
- Challenge generation spam
- Resource exhaustion attacks
Consider using libraries like PlugAttack or similar rate limiting solutions:
defmodule MyApp.Router do
use Phoenix.Router
# Add rate limiting before forwarding to WaxAPIREST.Plug
forward "/webauthn", WaxAPIREST.Plug, callback: MyApp.WebAuthnCallbackModule
endRecommended rate limits:
- Challenge generation endpoints (
/attestation/options,/assertion/options): Limit to reasonable per-user/IP rates (e.g., 10 requests per minute) - Authentication/registration endpoints (
/attestation/result,/assertion/result): Limit to prevent brute-force attacks (e.g., 5 attempts per minute per credential)
While WebAuthn responses are cryptographically signed and validated, applications should still implement CSRF protection if using cookie-based sessions. This provides defense in depth and protects against potential implementation vulnerabilities.
Consider using CSRF token protection for POST endpoints:
defmodule MyApp.Router do
use Phoenix.Router
# Add CSRF protection
plug :protect_from_forgery
forward "/webauthn", WaxAPIREST.Plug, callback: MyApp.WebAuthnCallbackModule
endNote: CSRF protection is especially important if your application uses cookie-based session management for challenge storage or user identification.