Web Authenticator API
Configuration and usage guidance for Web Authenticator API in Fortified ID Access.
Introduction
Section titled “Introduction”The Web Authenticator API is the interface between authenticator implementations (server) and their views (user agent/browser) and is based on HTTP and JSON.
The API is public and documented, which makes it possible to replace the view of an authenticator with an implementation of your own. See Custom frontend.
Design
Section titled “Design”Understanding why the boundary sits where it does makes the rest of this page, and the individual authenticator pages, easier to follow.
The authenticator decides, the view presents
Section titled “The authenticator decides, the view presents”An authenticator owns the protocol, the session, the authentication state, and the audit trail. A view owns presentation and nothing else. It reports what the user did and follows the instructions it gets back; it never determines whether an authentication succeeded.
This is why a result such as AUTHORIZED is computed on the server and returned to the view, and why a complete response carries a location for the view to follow rather than leaving the view to decide where to go next. A view that reasons about success on its own is not a different design, it is a security flaw.
State lives in the session
Section titled “State lives in the session”Authentication state is held in the session on the server, not in the page. That is what the state message exists for: it reports where the flow currently stands so the view can render the right thing.
Without it, a flow would break the moment anything interrupts the page. Browser reloads, the return from an app switch, and the back button are all normal parts of an authentication, and each one starts a new page against a session that is already in progress. A view that only ever sends start works until the first reload.
Authenticators that hold no intermediate state say so explicitly. The Passkey validator answers NONE to every state request, and a reloaded view there must begin again.
Views are static files
Section titled “Views are static files”A view is plain static content served from a directory. No part of it runs on the server, so replacing it is a configuration change rather than a fork, and nothing in it can be trusted with a decision that matters.
The same boundary supports three levels of change: an overlay replaces individual files such as a logo or a stylesheet, webroot_dir replaces a whole view, and ExternalFlow moves the step to a separate service entirely.
One envelope, many protocols
Section titled “One envelope, many protocols”The message envelope on this page is shared by every authenticator. Which message types exist, what they carry, and which statuses they report is specific to each authenticator and documented in the API section on its own page.
That split keeps this page short and each authenticator page self-contained. The message types an authenticator registers are its public interface; when they change, the corresponding page changes with them.
HTTP requirements
Section titled “HTTP requirements”All API request MUST use HTTP method PUT.
User agent MUST support/allow cookies.
Message format
Section titled “Message format”WAAPI uses a standardised format for API messages. It's an enveloped JSON format with common headers and custom data.
| Name | Description |
|---|---|
success | Message status flag indicating success (true) or failure (false). Only used in response messages. |
reason | Error reason. Only supplied for non successful (failed) messages/responses. |
type | Message type. Used for routing, authenticators registers handlers for each message type they support. |
reply_to | Reply address |
data | Custom message data object. May contain arbitrary data of JSON format. |
data.message | Response message object. If a message is supplied it should be translated and displayed to the end user. If both message and location is supplied, message is first displayed and when confirmed redirection is performed. Commonly used in messages of type "failure", but MAY be supplied in any response. When supplied in a failure context it should be considered an error message, in regular messages as information. |
data.message.text | Message text or a translation key. |
data.location | Redirect location. If a location is supplied, the view MUST redirect to this location. Always supplied in responses of type "complete", MAY be supplied in any response. |
{ "type": "<message-type>", "data": {
}}{ "success": true, "type": "<message-type>", "data": {
}}{ "success": false, "reason": "Error reason message", "data": {
}}Protocol
Section titled “Protocol”Each authenticator defines its own protocol when it comes to which messages it supports and what those messages contain. That protocol is documented in the API section on the page for each authenticator.
Structure of an authenticator API section
Section titled “Structure of an authenticator API section”Every authenticator that has a user interface documents its protocol using the same structure, so that a replacement frontend can be written from the page alone. See Custom frontend for what such a frontend must do.
| Heading | Content |
|---|---|
General requirements | Transport requirements, normally a reference back to this page. |
Messages | Every message type the authenticator accepts, with a one-line purpose. cancel is always available. |
| One heading per message | Request and response for that message type, as tabs. Request bodies show the fields in data; response bodies show the fields the view needs. |
Response from server | The expected HTTP status and the general shape of the response body. |
Possible status messages | Every value each status field can take. Authenticators that expose both a general and a vendor-specific status document them separately. |
Message status
Section titled “Message status”The status of a message represent the result of the operation returning the message.
If the operation succeeded without errors, "success": true is returned.
If the operation failed, "success": false is returned.
Each authenticators define what is considered to be a failure and not. If an error is a part of the normal operation (for example invalid user input) it is perfectly valid to return a failure message (i.e. a message with "type": "failure") with status "success": true containing an error message. In this case the message object in data should be used, not the reason header which is only allowed in combination with "success": false.
Common messages
Section titled “Common messages”Cancel
Section titled “Cancel”Use this message to cancel the operation(s) of the current authenticator. If successful, authenticator replies with a redirect location to where the view MUST redirect.
{ "type": "cancel", "data": { }}{ "success": "true", "type": "cancel", "data": { "location": "/path/to/cancel/location" }}Complete
Section titled “Complete”This response message means that the authentication process for the current authenticator is completed and can be . This message always contain a redirect location to where the view MUST redirect.
Requests of type "complete" are not allowed.
{ "success": "true", "type": "complete", "data": { "location": "/path/to/next/step" }}Failure
Section titled “Failure”When a failure occurs a failure response is returned. This message SHOULD contain a message which MUST be displayed to the user. Message MAY contain a location for redirect, which the user agent MUST follow. If both message and location is supplied, message MUST first be displayed and when confirmed, redirect is performed.
Requests of type "failure" are not allowed.
{ "success": "true", "type": "failure", "data": { "message": { "text": "Process cancelled" }, "location": "/path/to/next/step" }}