Authenticator Lifecycle

This document describes the complete lifecycle of a FIDO2 authenticator credential, from registration through authentication and management.

Note: This lifecycle applies to both client-direct and backend-proxied deployment approaches. The endpoints shown are FIDO2 server endpoints. In client-direct deployments, clients call these endpoints directly. In backend-proxied deployments, clients call backend endpoints that proxy requests to the FIDO2 server. The authenticator interaction steps are identical in both approaches.

Lifecycle Overview

spinner

Phase 1: Registration (Attestation)

Registration creates a new credential on the authenticator and stores the public key on the server.

Step 1: Begin Registration

FIDO2 Server Endpoint: POST /fidoapi/certify/attestation/options

The client initiates registration by sending user information:

{
  "username": "[email protected]",
  "displayName": "John Doe",
  "userVerification": "preferred",
  "attestation": "none",
  "attachment": "cross-platform"
}

Server Actions:

  1. Validate the request

  2. Look up existing credentials for the user

  3. Generate a random challenge

  4. Create registration options with:

    • Relying party information

    • User entity

    • Supported algorithms

    • Exclude list (existing credentials)

  5. Store state in session

  6. Return PublicKeyCredentialCreationOptions

Step 2: Authenticator Interaction

The client application:

  1. Receives the server options

  2. Calls navigator.credentials.create() (WebAuthn) or SDK equivalent

  3. Prompts user for authenticator interaction

  4. User taps/inserts authenticator

  5. User completes verification (PIN/biometric if required)

  6. Authenticator generates new key pair

  7. Returns attestation response

Step 3: Complete Registration

FIDO2 Server Endpoint: POST /fidoapi/certify/attestation/result

The client sends the authenticator response:

Server Actions:

  1. Retrieve session state

  2. Validate the response format

  3. Verify clientDataJSON:

    • Type is "webauthn.create"

    • Challenge matches

    • Origin is allowed

  4. Parse attestation object

  5. Verify attestation statement (if direct/indirect)

  6. Check AAGUID against MDS (if enabled)

  7. Extract and store:

    • Credential ID

    • Public key

    • AAGUID

    • User ID

    • Device metadata (keypair)

  8. Return success

Registration Validation

The server validates:

Check
Error Code
Description

Type field

E0002R-E0004R

Must be "public-key" string

ID field

E0005R-E0006R

Must be valid base64url

clientDataJSON

E0008R

Must be valid base64url

tokenBinding

E0009R

Not supported (deprecated)

Keypair format

E0023R

Invalid JSON structure

Session

E0024R

Session expired

Relying party

E0025R

Unknown relying party

Header format

E0026R

Invalid header value

Phase 2: Authentication (Assertion)

Authentication verifies the user owns a registered credential.

Step 1: Begin Authentication

FIDO2 Server Endpoint: POST /fidoapi/certify/assertion/options

The client initiates authentication:

Server Actions:

  1. Look up user's registered credentials

  2. Verify user exists (return 403 if not found)

  3. Generate a random challenge

  4. Create assertion options with:

    • Challenge

    • Relying party ID

    • Allowed credentials list

    • User verification requirement

  5. Store state in session

  6. Return PublicKeyCredentialRequestOptions

Step 2: Authenticator Interaction

The client application:

  1. Receives the server options

  2. Calls navigator.credentials.get() (WebAuthn) or SDK equivalent

  3. Prompts user for authenticator interaction

  4. User taps/inserts authenticator

  5. User completes verification (if required)

  6. Authenticator signs the challenge

  7. Returns assertion response

Step 3: Complete Authentication

FIDO2 Server Endpoint: POST /fidoapi/certify/assertion/result

The client sends the signed assertion:

Server Actions:

  1. Retrieve session state

  2. Validate the response format

  3. Find credential by ID

  4. Verify clientDataJSON:

    • Type is "webauthn.get"

    • Challenge matches

    • Origin is allowed

  5. Verify signature using stored public key

  6. Verify authenticator data:

    • RP ID hash matches

    • Flags are set correctly

    • Counter has increased

  7. Update counter in database

  8. Return success (optionally with JWT token)

Authentication Validation

The server validates:

Check
Error Code
Description

Type field

E0011R-E0013R

Must be "public-key" string

ID field

E0014R-E0015R

Must be valid base64url

Response object

E0016R

Must be a dictionary

authenticatorData

E0017R-E0018R

Required, must be base64url

Signature

E0019R

Must be valid base64url

clientDataJSON

E0020R-E0021R

Required, must be base64url

tokenBinding

E0022R

Not supported (deprecated)

Phase 3: Credential Management

Multiple Devices

The Arculus FIDO2 Server supports multiple credentials per user:

  • Each authenticator creates a separate credential

  • All credentials for a user are valid for authentication

  • excludeCredentials prevents re-registering the same authenticator

Listing Credentials

Credentials can be managed through the user API:

Endpoint: GET /users or GET /userapi/manageusers

Returns user credentials including:

  • Credential ID

  • AAGUID (authenticator model)

  • Registration date

  • Device metadata

  • Enabled/disabled status

Disabling Credentials

Credentials can be disabled without deletion:

  • Set disabled flag to prevent authentication

  • Credential remains in database

  • Can be re-enabled later

Phase 4: Credential Removal

User-Initiated Removal

Users can remove their own credentials through the application.

Administrative Removal

Administrators can remove credentials via:

Endpoint: POST /userapi/deletelistusers

Bulk deletion of user credentials.

Tenant Cleanup

When a tenant is removed, all associated credentials are deleted.

Session Management

Session State

The server maintains session state between begin and complete calls:

Field
Description

challenge

Random bytes for verification

userid

Username for the operation

keypair

Device metadata (registration only)

rp_id

Relying party identifier

Session Timeout

  • Default session timeout: 60 seconds (configurable via --session flag)

  • Session expired error: E0024R (408 Request Timeout)

  • Session must be maintained via cookies (credentials: 'include')

Important: Session cookies are critical for FIDO2 operations. The FIDO2 authentication flow is a two-step process (begin + complete), and the server uses session cookies to link these steps together.

Why Session Cookies Are Required

Without proper cookie handling:

  • The "complete" call cannot find the challenge from the "begin" call

  • You will receive "Session expired" (E0024R) errors

  • The authentication or registration flow will fail

Your HTTP client must:

  1. Store cookies from the "begin" response (check Set-Cookie header or enable automatic cookie handling)

  2. Send cookies with the "complete" request (include Cookie header or use credentials: 'include' in fetch)

Technical Details

The FIDO2 server uses Flask sessions with:

  • HttpOnly flag for security

  • SameSite=None for cross-origin requests

  • Secure flag when using HTTPS

Note: In backend-proxied deployments, the backend may maintain its own session management and proxy session cookies to the FIDO2 server. The session requirements remain the same at the FIDO2 server level.

Multi-Tenant Considerations

Tenant Isolation

  • Each tenant has separate credential storage

  • Credentials are scoped to tenant + relying party

  • Cross-tenant authentication is not possible

Relying Party Determination

Order of precedence for determining relying party:

  1. X-ArculusFido-RelyingParty header

  2. --domain server argument

  3. Origin header (in multi-tenant mode)

Tenant Lookup

If tenant not found, returns E0025R error with available domains.

Counter Management

Purpose

The signature counter helps detect cloned authenticators:

  • Counter increments with each authentication

  • Server stores the last seen counter

  • If counter decreases, authenticator may be cloned

Counter Validation

Error Handling

Registration Errors

Error Code
HTTP Status
Description

E0002R-E0009R

401

Validation failures

E0023R

400

Invalid keypair JSON

E0024R

408

Session expired

E0025R

400

Unknown relying party

E0026R

400

Invalid header format

Authentication Errors

Error Code
HTTP Status
Description

E0010R-E0022R

401

Validation failures

E0024R

408

Session expired

403

403

No account for user

Attestation Errors

Error Code
Description

E1000R

Invalid AAGUID length

E1001R-E1002R

Wrong data length

E1003R

Invalid AAGUID for fido-u2f format

E1004R-E1009R

Attestation statement validation

Security Considerations

Origin Binding

  • Client origin must match relying party ID

  • Prevents phishing attacks

Challenge Freshness

  • Challenges are randomly generated

  • Single-use (stored in session)

  • Time-limited by session timeout

Attestation Verification

  • Direct attestation verifies authenticator authenticity

  • MDS lookup validates authenticator security status

  • Revoked authenticators can be blocked

User Verification

  • Server can enforce userVerification: required

  • Overrides client preference via --verify flag

  • Ensures PIN/biometric was used

Last updated