Skip to main content

FIDO2/WebAuthn Authentication

AuthProxy provides FIDO2/WebAuthn support for hardware security key authentication. This is based on the actual FIDO2 implementation found in the codebase.

FIDO2 Configuration

This configuration is used for FIDO2 keys and also in several other processes.

{
"FIDO2": {
"serverDomain": "domain.com",
"serverName": "web.domain.com",
"timestampDriftTolerance": 300000,
"serverIcon": "https://web.itbuild.app/android-chrome-192x192.png",
"origins": [
"https://localhost:7285",
"http://localhost:7285",
"https://localhost:5173",
"http://localhost:3000"
]
}
}

Configuration Options

SettingDescriptionExample Value
serverDomainDomain for FIDO2 operations"yourdomain.com"
serverNameDisplay name for FIDO2"AuthProxy"
timestampDriftToleranceClock drift tolerance in milliseconds300000
serverIconIcon URL for authenticator display"https://domain.com/icon.png"
originsStatic allowed originsArray of URLs

API Integration

FIDO2 keys are managed through the same /auth/v1/keys/ endpoints as Ed25519 software passkeys — there are no FIDO2-specific endpoints. The flow distinguishes a FIDO2 enrolment from a software-key enrolment by the payload supplied to register_key.

Register a key (FIDO2 or software)

POST /auth/v1/keys/register_key
Content-Type: application/json

Body (AuthIn):

  • challengeIdlong from a preceding /auth/v1/login_options or /auth/v1/register_options call.
  • code — verification code returned by the registration flow.
  • credentialNewAuthenticatorAttestationRawResponse from navigator.credentials.create() for FIDO2 keys; the server validates it against the challenge's fido2Options.
  • publicKey — base64url Ed25519 public key for a software passkey (UserKey or PassKey).
  • passKeyFlagtrue to mark a password-derived key (replaces older PasswordKey entries automatically).

A FIDO2 enrolment stores both the public key and the CBOR attestation; a software passkey stores only the Ed25519 public key.

List the current user's keys

GET /auth/v1/keys/user_keys

Returns ApiResponse<List<UserKey>> with id, publicKey (base64url), keyType (PasswordKey | UserKey | FIDO2 | Unknown), utcCreate, current, mcpAccess, cardDavAccess.

Remove a key

POST /auth/v1/keys/remove_key
Content-Type: application/json

{ "keyId": "638412345678901234" }

Soft-deletes the key (KeyFlag.Deleted is OR-ed into flags).

Toggle MCP / CardDAV access

POST /auth/v1/keys/update_key
Content-Type: application/json

{ "keyId": "638412345678901234", "mcpAccess": true, "cardDavAccess": false }

Operator-side bulk listing across users lives in the admin panel (/ProxyAdmin/UserKeys), not on the public API.

Database Storage

FIDO2 keys are stored in the user_key table:

  • timetick — internal key identifier
  • client_id — owning user (apguser.timetick)
  • public_key — EdDSA Ed25519 public key (32 bytes); for FIDO2 keys this holds the credential id
  • fido2_key — FIDO2 public key in CBOR format
  • sign_count — FIDO2 signature counter (reserved; not currently advanced by the platform)
  • flagsKeyFlag bitmask (PasswordKey / UserKey / Fido2Key / McpAccess / CardDav / Deleted)

Implementation Notes

  • AuthProxy uses the Fido2NetLib library for FIDO2 attestation and assertion verification.
  • Software passkeys and FIDO2 keys live in the same table, distinguished by the KeyFlag bits.
  • The maximum number of active keys per user is configurable via ActiveKeysLimit.

For the live request/response shape see the built-in Swagger UI at /docs/swagger/.