Skip to main content
Version: 2.0

REST API

Nauthilus exposes REST endpoints for authentication, administration, and the native Identity Provider (OIDC/SAML2). All paths listed here are current and available without versioned docs.

Conventions and Common Headers

  • Admin APIs under /api/v1 are usually protected by Basic Auth or JWT (depending on your backchannel configuration).
  • IdP endpoints (/login, /oidc/*, /saml/*) are public and used by browsers and protocol clients.
  • Rate limiting and brute force protection apply to all endpoints.

Tracking Headers

All authentication-related endpoints return these headers:

HeaderDescription
X-Nauthilus-SessionRequest GUID for correlation
X-Nauthilus-Memory-CacheHit or Miss (cache status)
Auth-StatusOK, FAIL, or a temporary error string

Attribute Headers

Attribute mappings are exposed as X-Nauthilus-<AttributeName> headers (for header/basic/nginx services). Example: X-Nauthilus-Mail.

Configurable Request Headers

Header names for the header/nginx/basic auth services are configurable via server::default_http_request_header::*. The examples below use the default header names (Auth-User, Auth-Pass, Auth-Protocol, Auth-Method, Auth-Login-Attempt, Auth-Password-Encoded). The OIDC client ID header name is configured with server::default_http_request_header::oidc_cid.


Authentication Services

These endpoints are designed for backchannel integrations (mail servers, reverse proxies, or custom applications). All endpoints accept JSON or form data as noted. Authentication failures return Auth-Status: FAIL and set the X-Nauthilus-Session header for correlation.

JSON Authentication Service

POST /api/v1/auth/json

Content-Type: application/json (also supports application/x-www-form-urlencoded)

Request Body (example):

{
"username": "testuser",
"password": "testpassword",
"protocol": "imap",
"method": "plain",
"client_ip": "203.0.113.9",
"client_port": "56544",
"client_hostname": "mail.example",
"client_id": "imap01",
"user_agent": "Dovecot/2.3",
"oidc_cid": "demo-client",
"auth_login_attempt": 1,
"ssl": "on",
"ssl_protocol": "TLSv1.3",
"ssl_cipher": "TLS_AES_256_GCM_SHA384",
"ssl_verify": "SUCCESS",
"ssl_subject_dn": "CN=client",
"ssl_issuer_dn": "CN=issuer",
"ssl_serial": "01:02",
"ssl_fingerprint": "AB:CD:EF",
"ssl_client_notbefore": "2025-01-01T00:00:00Z",
"ssl_client_notafter": "2026-01-01T00:00:00Z"
}

Response (success - 200 OK):

{
"ok": true,
"account_field": "account",
"totp_secret_field": "nauthilusTotpSecret",
"backend": 1,
"attributes": {
"mail": "user@example.com",
"display_name": "John Doe",
"uid": "1001"
}
}

Response (failure - 403 Forbidden):

null

Response (temporary failure - 500 Internal Server Error):

{
"error": "Temporary server problem"
}
Status CodeDescription
200 OKAuthentication successful
400 Bad RequestInvalid JSON or unsupported media type
403 ForbiddenAuthentication failed or blocked
404 Not FoundEndpoint disabled
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorTemporary processing error

Header Authentication Service

POST /api/v1/auth/header

Request Headers (example):

Auth-User: testuser
Auth-Pass: testpassword
Auth-Protocol: imap
Auth-Method: plain
Auth-Login-Attempt: 1
Auth-Password-Encoded: 0
<oidc_cid_header>: demo-client

When Auth-Password-Encoded: 1 is set, the password value is expected to be Base64 URL-encoded. The <oidc_cid_header> placeholder must match your configured server::default_http_request_header::oidc_cid value.

Response Headers (success):

Auth-Status: OK
X-Nauthilus-Session: 8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f
X-Nauthilus-DisplayName: John Doe
X-Nauthilus-Mail: user@example.com

Response Body (failure):

null
Status CodeDescription
200 OKAuthentication successful
400 Bad RequestMissing or invalid headers
403 ForbiddenAuthentication failed or blocked
404 Not FoundEndpoint disabled
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorTemporary processing error

Basic Authentication Service

GET /api/v1/auth/basic

Build Tag Requirement

This endpoint exists only if Nauthilus was built with the Go build tag auth_basic_endpoint (for example: go build -tags auth_basic_endpoint ...). Without this build tag, the route is not available.

Request Headers (example):

Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3N3b3Jk
Auth-Protocol: imap
Auth-Method: plain
Auth-Login-Attempt: 1
<oidc_cid_header>: demo-client

Response Headers (success):

Auth-Status: OK
X-Nauthilus-Session: 8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f
X-Nauthilus-DisplayName: John Doe
Status CodeDescription
200 OKAuthentication successful
400 Bad RequestMissing Authorization or protocol header
403 ForbiddenAuthentication failed or blocked
404 Not FoundEndpoint disabled
429 Too Many RequestsRate limit exceeded
500 Internal Server ErrorTemporary processing error

Nginx Authentication Service

GET /api/v1/auth/nginx / POST /api/v1/auth/nginx

Request Headers (example):

Auth-User: testuser
Auth-Pass: testpassword
Auth-Protocol: imap
X-Real-IP: 203.0.113.9
X-Forwarded-For: 203.0.113.9

Response Headers (success):

Auth-Status: OK
X-Nauthilus-Session: 8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f
X-Nauthilus-Mail: user@example.com

Response Headers (failure):

Auth-Status: FAIL
Auth-Wait: 2
Status CodeDescription
200 OKSuccess, failure, or temporary failure (see Auth-Status)
404 Not FoundEndpoint disabled
429 Too Many RequestsRate limit exceeded

Identity Provider (IdP)

Nauthilus ships a native OIDC and SAML2 Identity Provider. All IdP endpoints are at the root path (no /idp prefix). Many browser-facing endpoints also support an optional /:languageTag suffix.

For flow diagrams, see OIDC and SAML2.

IdP Endpoint Inventory (Complete)

The following list reflects all currently registered IdP routes.

OIDC + Login/Consent

  • GET /.well-known/openid-configuration
  • GET /oidc/authorize and GET /oidc/authorize/:languageTag
  • POST /oidc/token, GET /oidc/token
  • GET /oidc/userinfo
  • POST /oidc/introspect
  • GET /oidc/jwks
  • POST /oidc/device
  • GET /oidc/device/verify and GET /oidc/device/verify/:languageTag
  • GET /oidc/device/verify/failed and GET /oidc/device/verify/failed/:languageTag
  • POST /oidc/device/verify and POST /oidc/device/verify/:languageTag
  • GET /oidc/device/consent and GET /oidc/device/consent/:languageTag
  • POST /oidc/device/consent and POST /oidc/device/consent/:languageTag
  • GET /oidc/logout, GET /logout
  • GET /oidc/consent and GET /oidc/consent/:languageTag
  • POST /oidc/consent and POST /oidc/consent/:languageTag

IdP Browser Login/MFA

  • GET /login and GET /login/:languageTag
  • POST /login and POST /login/:languageTag
  • GET /login/totp and GET /login/totp/:languageTag
  • POST /login/totp and POST /login/totp/:languageTag
  • GET /login/webauthn and GET /login/webauthn/:languageTag
  • GET /login/webauthn/begin and GET /login/webauthn/begin/:languageTag
  • POST /login/webauthn/finish and POST /login/webauthn/finish/:languageTag
  • GET /login/mfa and GET /login/mfa/:languageTag
  • GET /login/recovery and GET /login/recovery/:languageTag
  • POST /login/recovery and POST /login/recovery/:languageTag
  • GET /logged_out and GET /logged_out/:languageTag

SAML2

  • GET /saml/metadata
  • GET /saml/sso
  • GET /saml/slo
  • POST /saml/slo

IdP MFA Self-Service (session required, /mfa/*)

  • GET /mfa/register/home and GET /mfa/register/home/:languageTag
  • GET /mfa/totp/register and GET /mfa/totp/register/:languageTag
  • POST /mfa/totp/register and POST /mfa/totp/register/:languageTag
  • DELETE /mfa/totp
  • GET /mfa/webauthn/register and GET /mfa/webauthn/register/:languageTag
  • GET /mfa/webauthn/register/begin and GET /mfa/webauthn/register/begin/:languageTag
  • POST /mfa/webauthn/register/finish and POST /mfa/webauthn/register/finish/:languageTag
  • DELETE /mfa/webauthn
  • GET /mfa/webauthn/devices and GET /mfa/webauthn/devices/:languageTag
  • DELETE /mfa/webauthn/device/:id
  • POST /mfa/webauthn/device/:id/name
  • GET /mfa/recovery/register and GET /mfa/recovery/register/:languageTag
  • POST /mfa/recovery/register and POST /mfa/recovery/register/:languageTag
  • POST /mfa/recovery/register/save and POST /mfa/recovery/register/save/:languageTag
  • POST /mfa/recovery/generate and POST /mfa/recovery/generate/:languageTag
  • GET /mfa/register/continue and GET /mfa/register/continue/:languageTag
  • GET /mfa/register/cancel and GET /mfa/register/cancel/:languageTag

IdP Backchannel APIs

  • GET /api/v1/mfa/totp/setup
  • POST /api/v1/mfa/totp/register
  • DELETE /api/v1/mfa/totp
  • POST /api/v1/mfa/recovery-codes/generate
  • GET /api/v1/mfa/webauthn/register/begin
  • POST /api/v1/mfa/webauthn/register/finish
  • DELETE /api/v1/mfa/webauthn/:credentialID
  • GET /api/v1/oidc/sessions/{user_id}
  • DELETE /api/v1/oidc/sessions/{user_id}
  • DELETE /api/v1/oidc/sessions/{user_id}/{token}
  • POST /api/v1/mfa-backchannel/totp
  • DELETE /api/v1/mfa-backchannel/totp
  • POST /api/v1/mfa-backchannel/totp/recovery-codes
  • DELETE /api/v1/mfa-backchannel/totp/recovery-codes
  • GET /api/v1/mfa-backchannel/webauthn/credential
  • POST /api/v1/mfa-backchannel/webauthn/credential
  • PUT /api/v1/mfa-backchannel/webauthn/credential
  • DELETE /api/v1/mfa-backchannel/webauthn/credential

OpenID Connect Discovery

GET /.well-known/openid-configuration

Response (example):

{
"issuer": "https://idp.example.com",
"authorization_endpoint": "https://idp.example.com/oidc/authorize",
"token_endpoint": "https://idp.example.com/oidc/token",
"introspection_endpoint": "https://idp.example.com/oidc/introspect",
"userinfo_endpoint": "https://idp.example.com/oidc/userinfo",
"jwks_uri": "https://idp.example.com/oidc/jwks",
"end_session_endpoint": "https://idp.example.com/oidc/logout",
"device_authorization_endpoint": "https://idp.example.com/oidc/device",
"response_types_supported": ["code"],
"scopes_supported": ["openid", "profile", "email"],
"claims_supported": ["sub", "name", "email"],
"token_endpoint_auth_methods_supported": ["client_secret_basic", "client_secret_post"]
}
Status CodeDescription
200 OKDiscovery document returned
500 Internal Server ErrorDiscovery generation failed

OIDC Authorization Endpoint

GET /oidc/authorize (alias: GET /oidc/authorize/:languageTag)

Request (example):

GET /oidc/authorize?response_type=code&client_id=demo&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&scope=openid%20profile%20email&state=abc123&code_challenge=xyz&code_challenge_method=S256&nonce=n-0S6_WzA2Mj

Response (success - 302 Found):

Location: https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=abc123
Status CodeDescription
302 FoundRedirect to login/consent or client redirect URI
400 Bad RequestInvalid or missing parameters
500 Internal Server ErrorAuthorization processing failed

OIDC Token Endpoint

POST /oidc/token (alias: GET /oidc/token)

Content-Type: application/x-www-form-urlencoded

Request Body (example):

grant_type=authorization_code&code=SplxlOBeZQQYbYS6WxSbIA&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&client_id=demo&client_secret=secret

Client Credentials example:

grant_type=client_credentials&scope=nauthilus:authenticate%20nauthilus:admin

For private_key_jwt client authentication, send client_assertion_type and client_assertion in the form body (instead of client_secret).

Response (success - 200 OK):

{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "def50200...",
"id_token": "eyJhbGciOi..."
}
Status CodeDescription
200 OKToken issued
400 Bad RequestInvalid grant or request
401 UnauthorizedClient authentication failed
500 Internal Server ErrorToken generation failed

Supported grant_type values:

  • authorization_code
  • refresh_token
  • client_credentials
  • urn:ietf:params:oauth:grant-type:device_code

OIDC UserInfo Endpoint

GET /oidc/userinfo

Request Headers (example):

Authorization: Bearer eyJhbGciOi...

Response (success - 200 OK):

{
"sub": "1001",
"name": "John Doe",
"email": "user@example.com"
}
Status CodeDescription
200 OKClaims returned
401 UnauthorizedInvalid or missing access token
500 Internal Server ErrorUserInfo processing failed

OIDC Introspection Endpoint

POST /oidc/introspect

Content-Type: application/x-www-form-urlencoded

Request Body (example):

token=eyJhbGciOi...&token_type_hint=access_token

Response (success - 200 OK):

{
"active": true,
"client_id": "demo",
"username": "testuser",
"scope": "openid profile",
"exp": 1736000000
}
Status CodeDescription
200 OKToken introspected
400 Bad RequestInvalid request
401 UnauthorizedClient authentication failed
500 Internal Server ErrorIntrospection failed

OIDC JWKS Endpoint

GET /oidc/jwks

Response (example):

{
"keys": [
{
"kty": "RSA",
"kid": "key-1",
"use": "sig",
"n": "...",
"e": "AQAB"
}
]
}
Status CodeDescription
200 OKJWKS returned
500 Internal Server ErrorJWKS generation failed

OIDC Logout Endpoint

GET /oidc/logout (alias: GET /logout)

Request (example):

GET /oidc/logout?id_token_hint=eyJhbGciOi...&post_logout_redirect_uri=https%3A%2F%2Fapp.example.com%2Flogged_out&state=abc123

Response (success - 302 Found):

Location: https://app.example.com/logged_out?state=abc123
Status CodeDescription
200 OKLogout page rendered
302 FoundRedirected to post_logout_redirect_uri
400 Bad RequestInvalid logout request
500 Internal Server ErrorLogout processing failed

OIDC Device Authorization Endpoints

POST /oidc/device

Content-Type: application/x-www-form-urlencoded

Request Body (example):

client_id=demo-device&scope=openid%20profile

Response (success - 200 OK):

{
"device_code": "dvc_abc123",
"user_code": "ABCD-EFGH",
"verification_uri": "https://idp.example.com/oidc/device/verify",
"verification_uri_complete": "https://idp.example.com/oidc/device/verify?user_code=ABCD-EFGH",
"expires_in": 600,
"interval": 5
}
Status CodeDescription
200 OKDevice code issued
400 Bad RequestInvalid client/scope request
401 UnauthorizedClient authentication failed
500 Internal Server ErrorDevice authorization failed

GET /oidc/device/verify / POST /oidc/device/verify

Language variants are available with /:languageTag.

Status CodeDescription
200 OKVerification page rendered / code accepted
302 FoundRedirect to login/consent/success page
400 Bad RequestInvalid device verification request
500 Internal Server ErrorDevice verification failed

GET /oidc/device/verify/failed

Language variant available: GET /oidc/device/verify/failed/:languageTag.

GET /oidc/device/consent / POST /oidc/device/consent

Language variants are available with /:languageTag.

Status CodeDescription
200 OKConsent page rendered
302 FoundConsent accepted and completion page shown
400 Bad RequestInvalid device consent request
403 ForbiddenConsent denied
500 Internal Server ErrorDevice consent processing failed

GET /oidc/consent (alias: GET /oidc/consent/:languageTag)

Request (example):

GET /oidc/consent?consent_challenge=abcd&state=xyz

Response (success - 200 OK):

<HTML consent page>

POST /oidc/consent (alias: POST /oidc/consent/:languageTag)

Content-Type: application/x-www-form-urlencoded

Request Body (example):

consent_challenge=abcd&state=xyz&submit=allow

Response (success - 302 Found):

Location: https://app.example.com/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz
Status CodeDescription
200 OKConsent page rendered
302 FoundConsent accepted and redirected
403 ForbiddenConsent denied
400 Bad RequestInvalid consent request
500 Internal Server ErrorConsent processing failed

IdP Login Endpoints

important

These login endpoints are designed exclusively for IdP flows (OIDC and SAML2). They cannot be accessed directly without a valid flow state stored in cookies. The flow state is automatically set when a user initiates an OIDC authorization or SAML2 SSO request. Flow state is managed securely via HTTP-only cookies to prevent Open Redirect vulnerabilities.

GET /login (alias: GET /login/:languageTag)

Displays the login page. Requires a valid IdP flow state cookie.

Request (example):

GET /login

Response (success - 200 OK):

<HTML login page>

Response (no valid flow - 400 Bad Request):

<HTML error page: "This login page can only be accessed through a valid OIDC or SAML2 authentication flow.">

POST /login (alias: POST /login/:languageTag)

Content-Type: application/x-www-form-urlencoded

Request Body (example):

username=testuser&password=testpassword&csrf_token=<token>&remember_me=on

Required Form Fields:

  • username: The user's username or email
  • password: The user's password
  • csrf_token: CSRF protection token (from template variable .CSRFToken)
  • remember_me (optional): Set to on to remember the session

Response (success - 302 Found):

Location: /oidc/authorize?response_type=code&client_id=demo&...
Status CodeDescription
200 OKLogin form rendered or re-rendered with error
302 FoundLogin succeeded and redirected to IdP endpoint
400 Bad RequestInvalid login request, missing flow state, or CSRF token validation failed
500 Internal Server ErrorLogin processing failed

IdP MFA Login Endpoints

All MFA endpoints require a valid IdP flow state cookie and CSRF token.

GET /login/mfa (alias: GET /login/mfa/:languageTag)

Displays the MFA method selection page when the user has multiple MFA methods available.

Response (success - 200 OK):

<HTML MFA selection page>

GET /login/totp (alias: GET /login/totp/:languageTag)

Displays the TOTP verification form.

Request (example):

GET /login/totp

Response (success - 200 OK):

<HTML TOTP form>

POST /login/totp (alias: POST /login/totp/:languageTag)

Content-Type: application/x-www-form-urlencoded

Request Body (example):

code=123456&csrf_token=<token>

Required Form Fields:

  • code: 6-digit TOTP code from authenticator app
  • csrf_token: CSRF protection token

Response (success - 302 Found):

Location: /oidc/authorize?response_type=code&client_id=demo&...

GET /login/recovery (alias: GET /login/recovery/:languageTag)

Displays the recovery code verification form.

Request (example):

GET /login/recovery

Response (success - 200 OK):

<HTML recovery code form>

POST /login/recovery (alias: POST /login/recovery/:languageTag)

Content-Type: application/x-www-form-urlencoded

Request Body (example):

code=R2D2-1C3P&csrf_token=<token>

Required Form Fields:

  • code: Recovery code (format: XXXX-XXXX)
  • csrf_token: CSRF protection token

Response (success - 302 Found):

Location: /oidc/authorize?response_type=code&client_id=demo&...

GET /login/webauthn (alias: GET /login/webauthn/:languageTag)

Displays the WebAuthn (passkey/security key) verification page.

Request (example):

GET /login/webauthn

Response (success - 200 OK):

<HTML WebAuthn verification page with JavaScript>
Status CodeDescription
200 OKMFA form rendered or re-rendered with error
302 FoundMFA validation succeeded
400 Bad RequestInvalid MFA request, missing flow state, or CSRF token validation failed
500 Internal Server ErrorMFA processing failed

Logged-Out Page

GET /logged_out (alias: GET /logged_out/:languageTag)

Response (success - 200 OK):

<HTML logged out page>
Status CodeDescription
200 OKPage rendered
500 Internal Server ErrorRendering failed

WebAuthn Endpoints (Names Only)

WebAuthn is intentionally documented by endpoint names only. The UI handles payload details.

  • Login flow: GET /login/webauthn/begin, POST /login/webauthn/finish (both also with /:languageTag)
  • Browser self-service registration flow: GET /mfa/webauthn/register/begin, POST /mfa/webauthn/register/finish (both also with /:languageTag)
  • Backchannel registration flow: GET /api/v1/mfa/webauthn/register/begin, POST /api/v1/mfa/webauthn/register/finish

SAML2 Endpoints

GET /saml/metadata

Response (success - 200 OK):

<EntityDescriptor entityID="https://idp.example.com/saml">
<!-- Metadata XML -->
</EntityDescriptor>
Status CodeDescription
200 OKMetadata returned
500 Internal Server ErrorMetadata generation failed

GET /saml/sso

Request (example):

SAMLRequest=<base64>&RelayState=xyz

Response (success - 200 OK or 302 Found):

<HTML auto-submit form or redirect>
Status CodeDescription
200 OKSAML response rendered
302 FoundRedirect to IdP login or SP
400 Bad RequestInvalid SAML request
500 Internal Server ErrorSSO processing failed

GET /saml/slo / POST /saml/slo

Request (example):

SAMLRequest=<base64>&RelayState=xyz

Response (success - 200 OK or 302 Found):

<HTML auto-submit form or redirect>
Status CodeDescription
200 OKLogout response rendered
302 FoundRedirect to SP or IdP
400 Bad RequestInvalid SAML request
500 Internal Server ErrorSLO processing failed

Multi-Factor Authentication (MFA) API

Session Required

These endpoints require an active frontend session (cookie). They are typically used by the internal /mfa/* self-service pages.

TOTP (Time-based One-Time Password)

GET /api/v1/mfa/totp/setup

Response (success - 200 OK):

{
"secret": "JBSWY3DPEHPK3PXP",
"qr_code_url": "otpauth://totp/Nauthilus:testuser?secret=JBSWY3DPEHPK3PXP&issuer=Nauthilus"
}
Status CodeDescription
200 OKTOTP secret generated
401 UnauthorizedFrontend session missing
500 Internal Server ErrorTOTP generation failed

POST /api/v1/mfa/totp/register

Content-Type: application/json

Request Body (example):

{
"code": "123456"
}

Response (success - 200 OK):

{
"status": "success",
"message": "TOTP registered successfully"
}
Status CodeDescription
200 OKTOTP registered
400 Bad RequestInvalid code or request
401 UnauthorizedFrontend session missing
500 Internal Server ErrorTOTP registration failed

DELETE /api/v1/mfa/totp

Response (success - 200 OK):

{
"status": "success",
"message": "TOTP deleted successfully"
}
Status CodeDescription
200 OKTOTP deleted
401 UnauthorizedFrontend session missing
500 Internal Server ErrorTOTP deletion failed

Recovery Codes

POST /api/v1/mfa/recovery-codes/generate

Response (success - 200 OK):

{
"codes": [
"R2D2-1C3P",
"A9TQ-0Z9L",
"K2M8-0P1F"
]
}
Status CodeDescription
200 OKRecovery codes generated
400 Bad RequestNo MFA method enabled
401 UnauthorizedFrontend session missing
500 Internal Server ErrorGeneration failed

WebAuthn (Names Only)

Per requirement, WebAuthn is listed by endpoint name only:

  • GET /api/v1/mfa/webauthn/register/begin
  • POST /api/v1/mfa/webauthn/register/finish
  • DELETE /api/v1/mfa/webauthn/:credentialID

Management & Operations

These endpoints are typically protected by Basic Auth or JWT and used for monitoring or administrative tasks.

OIDC Session Management API

GET /api/v1/oidc/sessions/{user_id}

Response (success - 200 OK):

{
"at_123": {
"client_id": "demo",
"user_id": "1001",
"username": "testuser",
"display_name": "John Doe",
"scopes": ["openid", "profile"],
"redirect_uri": "https://app.example.com/callback",
"auth_time": 1736000000,
"nonce": "n-0S6_WzA2Mj",
"claims": {
"email": "user@example.com"
}
}
}
Status CodeDescription
200 OKSessions returned
400 Bad RequestMissing user_id
401 UnauthorizedMissing/invalid credentials
403 ForbiddenInsufficient role
500 Internal Server ErrorSession lookup failed

DELETE /api/v1/oidc/sessions/{user_id}

Response (success - 204 No Content):

(empty body)
Status CodeDescription
204 No ContentAll sessions deleted
400 Bad RequestMissing user_id
401 UnauthorizedMissing/invalid credentials
403 ForbiddenInsufficient role
500 Internal Server ErrorDeletion failed

DELETE /api/v1/oidc/sessions/{user_id}/{token}

Response (success - 204 No Content):

(empty body)
Status CodeDescription
204 No ContentSession deleted
400 Bad RequestMissing token
401 UnauthorizedMissing/invalid credentials
403 ForbiddenInsufficient role
500 Internal Server ErrorDeletion failed

IdP MFA Backchannel API (/api/v1/mfa-backchannel/*)

These endpoints are used by backend integrations (for example Lua proxy backend) to manage MFA artifacts in LDAP/Lua backends.

Common request fields:

  • username (required for all operations)
  • backend (optional: empty/lua/ldap)
  • backend_name (optional backend instance name)

TOTP + Recovery

  • POST /api/v1/mfa-backchannel/totp
    Body fields: username, totp_secret
  • DELETE /api/v1/mfa-backchannel/totp
    Body fields: username
  • POST /api/v1/mfa-backchannel/totp/recovery-codes
    Body fields: username, codes (array)
  • DELETE /api/v1/mfa-backchannel/totp/recovery-codes
    Body fields: username

WebAuthn Credential Storage

  • GET /api/v1/mfa-backchannel/webauthn/credential
    Query: username (required), optional backend, backend_name
  • POST /api/v1/mfa-backchannel/webauthn/credential
    Body fields: username, credential (JSON-encoded credential string)
  • PUT /api/v1/mfa-backchannel/webauthn/credential
    Body fields: username, credential, old_credential (both JSON-encoded credential strings)
  • DELETE /api/v1/mfa-backchannel/webauthn/credential
    Body fields: username, credential (JSON-encoded credential string)

Typical status codes:

  • 200 OK success
  • 400 Bad Request invalid input
  • 401 Unauthorized or 403 Forbidden backchannel authentication/authorization failure
  • 500 Internal Server Error backend operation failed

Brute Force Protection

GET /api/v1/bruteforce/list / POST /api/v1/bruteforce/list

Request Body (optional, POST example):

{
"accounts": ["testuser"],
"ip_addresses": ["203.0.113.9"]
}

Response (success - 200 OK):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "bruteforce",
"operation": "list",
"result": [
{
"ip_addresses": {
"203.0.113.9": "default"
},
"error": null
},
{
"accounts": {
"testuser": ["default"]
},
"error": null
}
]
}
Status CodeDescription
200 OKList returned
400 Bad RequestInvalid filter request
401 UnauthorizedMissing/invalid credentials
403 ForbiddenMissing required role
500 Internal Server ErrorList retrieval failed

DELETE /api/v1/bruteforce/flush

Request Body (example):

{
"ip_address": "203.0.113.9",
"rule_name": "default",
"protocol": "imap",
"oidc_cid": "demo-client"
}

Response (success - 200 OK):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "bruteforce",
"operation": "flush",
"result": {
"ip_address": "203.0.113.9",
"rule_name": "default",
"protocol": "imap",
"oidc_cid": "demo-client",
"removed_keys": ["bf:203.0.113.9:default"],
"status": "1 keys flushed"
}
}
Status CodeDescription
200 OKBrute force entries flushed
400 Bad RequestInvalid request payload
401 UnauthorizedMissing/invalid credentials
403 ForbiddenMissing required role
500 Internal Server ErrorFlush failed

DELETE /api/v1/bruteforce/flush/async

Request Body (example):

{
"ip_address": "203.0.113.9",
"rule_name": "default",
"protocol": "imap"
}

Response (success - 202 Accepted):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "bruteforce",
"operation": "flush_async",
"result": {
"jobId": "1736000000-acde",
"status": "QUEUED"
}
}
Status CodeDescription
202 AcceptedFlush job enqueued
400 Bad RequestInvalid request payload
401 UnauthorizedMissing/invalid credentials
403 ForbiddenMissing required role
500 Internal Server ErrorEnqueue failed

Cache Management

DELETE /api/v1/cache/flush

Request Body (example):

{
"user": "testuser"
}

Response (success - 200 OK):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "cache",
"operation": "flush",
"result": {
"user": "testuser",
"removed_keys": ["cache:user:testuser"],
"status": "1 keys flushed"
}
}
Status CodeDescription
200 OKCache flushed
400 Bad RequestInvalid request payload
401 UnauthorizedMissing/invalid credentials
403 ForbiddenMissing required role
500 Internal Server ErrorCache flush failed

DELETE /api/v1/cache/flush/async

Request Body (example):

{
"user": "testuser"
}

Response (success - 202 Accepted):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "cache",
"operation": "flush_async",
"result": {
"jobId": "1736000000-acde",
"status": "QUEUED"
}
}
Status CodeDescription
202 AcceptedCache flush job enqueued
400 Bad RequestInvalid request payload
401 UnauthorizedMissing/invalid credentials
403 ForbiddenMissing required role
500 Internal Server ErrorEnqueue failed

Async Jobs

GET /api/v1/async/jobs/{jobId}

Response (success - 200 OK):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "async",
"operation": "status",
"result": {
"jobId": "1736000000-acde",
"status": "DONE",
"type": "CACHE_FLUSH",
"createdAt": "2025-02-05T10:00:00Z",
"startedAt": "2025-02-05T10:00:01Z",
"finishedAt": "2025-02-05T10:00:02Z",
"resultCount": "1250",
"error": ""
}
}
Status CodeDescription
200 OKJob status returned
404 Not FoundJob ID not found
500 Internal Server ErrorStatus lookup failed

Configuration

GET /api/v1/config/load

Response (success - 200 OK):

{
"session": "8a7c4c5b-6cf9-4af7-bfde-0a94cfd79f4f",
"object": "config",
"operation": "load",
"result": "{\"server\":{\"log\":{\"log_level\":\"info\"}}}"
}
Status CodeDescription
200 OKConfiguration returned
401 UnauthorizedMissing/invalid credentials
403 ForbiddenMissing required role
404 Not FoundEndpoint disabled
500 Internal Server ErrorConfig retrieval failed

Developer & Miscellaneous

JWT Generation

POST /api/v1/jwt/token

Request Body (example):

{
"username": "admin",
"password": "secret"
}

Response (success - 200 OK):

{
"token": "eyJhbGciOi...",
"expires_at": 1736000000,
"refresh_token": "def50200..."
}
Status CodeDescription
200 OKToken issued
400 Bad RequestInvalid request payload
401 UnauthorizedInvalid credentials
403 ForbiddenMissing required role
500 Internal Server ErrorToken creation failed

POST /api/v1/jwt/refresh

Request Headers (example):

X-Refresh-Token: def50200...

Response (success - 200 OK):

{
"token": "eyJhbGciOi...",
"expires_at": 1736000000,
"refresh_token": "def50200..."
}
Status CodeDescription
200 OKToken refreshed
400 Bad RequestMissing refresh token
401 UnauthorizedInvalid refresh token
500 Internal Server ErrorRefresh failed

Custom Hooks

ANY /api/v1/custom/{hookName}

Request Body (example):

{
"username": "testuser",
"action": "provision"
}

Response (example):

{
"status": "ok",
"message": "Hook executed"
}
Status CodeDescription
200 OKHook executed
403 ForbiddenHook disabled or insufficient permissions
500 Internal Server ErrorHook execution failed

UI Developer Mode

GET /api/v1/dev/ui

Response (success - 200 OK):

<HTML developer UI>

GET /api/v1/dev/ui/version

Response (success - 200 OK):

{
"version": "1.12.0"
}

GET /api/v1/dev/ui/render/{template}

Response (success - 200 OK):

<Rendered HTML fragment>

Optional language variant: GET /api/v1/dev/ui/render/{template}/{languageTag}.

Status CodeDescription
200 OKDeveloper UI rendered
403 ForbiddenDeveloper mode disabled
404 Not FoundTemplate not found
500 Internal Server ErrorRendering failed

Metrics Endpoint

GET /metrics

Response (success - 200 OK):

# HELP nauthilus_logins_total Total authentication attempts
# TYPE nauthilus_logins_total counter
nauthilus_logins_total{result="success"} 42
Status CodeDescription
200 OKPrometheus metrics returned
404 Not FoundMetrics route not enabled

Global Response Headers

Authentication endpoints include these tracking headers:

HeaderDescription
X-Nauthilus-SessionA unique request GUID for log correlation
X-Nauthilus-Memory-CacheHit if the result came from local cache, otherwise Miss
Auth-StatusOK or FAIL (authentication endpoints only)