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/v1are 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:
| Header | Description |
|---|---|
X-Nauthilus-Session | Request GUID for correlation |
X-Nauthilus-Memory-Cache | Hit or Miss (cache status) |
Auth-Status | OK, 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.
All request-header values for these services may be URL-partially encoded and are decoded by Nauthilus before processing.
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 Code | Description |
|---|---|
200 OK | Authentication successful |
400 Bad Request | Invalid JSON or unsupported media type |
403 Forbidden | Authentication failed or blocked |
404 Not Found | Endpoint disabled |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Temporary 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 Code | Description |
|---|---|
200 OK | Authentication successful |
400 Bad Request | Missing or invalid headers |
403 Forbidden | Authentication failed or blocked |
404 Not Found | Endpoint disabled |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Temporary processing error |
Basic Authentication Service
GET /api/v1/auth/basic
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 Code | Description |
|---|---|
200 OK | Authentication successful |
400 Bad Request | Missing Authorization or protocol header |
403 Forbidden | Authentication failed or blocked |
404 Not Found | Endpoint disabled |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | Temporary processing error |
Nginx Authentication Service
GET /api/v1/auth/nginx / POST /api/v1/auth/nginx
All incoming Nginx request-header values may be URL-partially encoded and are understood by Nauthilus.
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 Code | Description |
|---|---|
200 OK | Success, failure, or temporary failure (see Auth-Status) |
404 Not Found | Endpoint disabled |
429 Too Many Requests | Rate 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-configurationGET /oidc/authorizeandGET /oidc/authorize/:languageTagPOST /oidc/token,GET /oidc/tokenGET /oidc/userinfoPOST /oidc/introspectGET /oidc/jwksPOST /oidc/deviceGET /oidc/device/verifyandGET /oidc/device/verify/:languageTagGET /oidc/device/verify/failedandGET /oidc/device/verify/failed/:languageTagPOST /oidc/device/verifyandPOST /oidc/device/verify/:languageTagGET /oidc/device/consentandGET /oidc/device/consent/:languageTagPOST /oidc/device/consentandPOST /oidc/device/consent/:languageTagGET /oidc/logout,GET /logoutGET /oidc/consentandGET /oidc/consent/:languageTagPOST /oidc/consentandPOST /oidc/consent/:languageTag
IdP Browser Login/MFA
GET /loginandGET /login/:languageTagPOST /loginandPOST /login/:languageTagGET /login/totpandGET /login/totp/:languageTagPOST /login/totpandPOST /login/totp/:languageTagGET /login/webauthnandGET /login/webauthn/:languageTagGET /login/webauthn/beginandGET /login/webauthn/begin/:languageTagPOST /login/webauthn/finishandPOST /login/webauthn/finish/:languageTagGET /login/mfaandGET /login/mfa/:languageTagGET /login/recoveryandGET /login/recovery/:languageTagPOST /login/recoveryandPOST /login/recovery/:languageTagGET /logged_outandGET /logged_out/:languageTag
SAML2
GET /saml/metadataGET /saml/ssoGET /saml/sloPOST /saml/slo
IdP MFA Self-Service (session required, /mfa/*)
GET /mfa/register/homeandGET /mfa/register/home/:languageTagGET /mfa/totp/registerandGET /mfa/totp/register/:languageTagPOST /mfa/totp/registerandPOST /mfa/totp/register/:languageTagDELETE /mfa/totpGET /mfa/webauthn/registerandGET /mfa/webauthn/register/:languageTagGET /mfa/webauthn/register/beginandGET /mfa/webauthn/register/begin/:languageTagPOST /mfa/webauthn/register/finishandPOST /mfa/webauthn/register/finish/:languageTagDELETE /mfa/webauthnGET /mfa/webauthn/devicesandGET /mfa/webauthn/devices/:languageTagDELETE /mfa/webauthn/device/:idPOST /mfa/webauthn/device/:id/nameGET /mfa/recovery/registerandGET /mfa/recovery/register/:languageTagPOST /mfa/recovery/registerandPOST /mfa/recovery/register/:languageTagPOST /mfa/recovery/register/saveandPOST /mfa/recovery/register/save/:languageTagPOST /mfa/recovery/generateandPOST /mfa/recovery/generate/:languageTagGET /mfa/register/continueandGET /mfa/register/continue/:languageTagGET /mfa/register/cancelandGET /mfa/register/cancel/:languageTag
IdP Backchannel APIs
GET /api/v1/mfa/totp/setupPOST /api/v1/mfa/totp/registerDELETE /api/v1/mfa/totpPOST /api/v1/mfa/recovery-codes/generateGET /api/v1/mfa/webauthn/register/beginPOST /api/v1/mfa/webauthn/register/finishDELETE /api/v1/mfa/webauthn/:credentialIDGET /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/totpDELETE /api/v1/mfa-backchannel/totpPOST /api/v1/mfa-backchannel/totp/recovery-codesDELETE /api/v1/mfa-backchannel/totp/recovery-codesGET /api/v1/mfa-backchannel/webauthn/credentialPOST /api/v1/mfa-backchannel/webauthn/credentialPUT /api/v1/mfa-backchannel/webauthn/credentialDELETE /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 Code | Description |
|---|---|
200 OK | Discovery document returned |
500 Internal Server Error | Discovery 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 Code | Description |
|---|---|
302 Found | Redirect to login/consent or client redirect URI |
400 Bad Request | Invalid or missing parameters |
500 Internal Server Error | Authorization 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 Code | Description |
|---|---|
200 OK | Token issued |
400 Bad Request | Invalid grant or request |
401 Unauthorized | Client authentication failed |
500 Internal Server Error | Token generation failed |
Supported grant_type values:
authorization_coderefresh_tokenclient_credentialsurn: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 Code | Description |
|---|---|
200 OK | Claims returned |
401 Unauthorized | Invalid or missing access token |
500 Internal Server Error | UserInfo 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 Code | Description |
|---|---|
200 OK | Token introspected |
400 Bad Request | Invalid request |
401 Unauthorized | Client authentication failed |
500 Internal Server Error | Introspection failed |
OIDC JWKS Endpoint
GET /oidc/jwks
Response (example):
{
"keys": [
{
"kty": "RSA",
"kid": "key-1",
"use": "sig",
"n": "...",
"e": "AQAB"
}
]
}
| Status Code | Description |
|---|---|
200 OK | JWKS returned |
500 Internal Server Error | JWKS 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 Code | Description |
|---|---|
200 OK | Logout page rendered |
302 Found | Redirected to post_logout_redirect_uri |
400 Bad Request | Invalid logout request |
500 Internal Server Error | Logout 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 Code | Description |
|---|---|
200 OK | Device code issued |
400 Bad Request | Invalid client/scope request |
401 Unauthorized | Client authentication failed |
500 Internal Server Error | Device authorization failed |
GET /oidc/device/verify / POST /oidc/device/verify
Language variants are available with /:languageTag.
| Status Code | Description |
|---|---|
200 OK | Verification page rendered / code accepted |
302 Found | Redirect to login/consent/success page |
400 Bad Request | Invalid device verification request |
500 Internal Server Error | Device 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 Code | Description |
|---|---|
200 OK | Consent page rendered |
302 Found | Consent accepted and completion page shown |
400 Bad Request | Invalid device consent request |
403 Forbidden | Consent denied |
500 Internal Server Error | Device consent processing failed |
OIDC Consent Endpoints
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 Code | Description |
|---|---|
200 OK | Consent page rendered |
302 Found | Consent accepted and redirected |
403 Forbidden | Consent denied |
400 Bad Request | Invalid consent request |
500 Internal Server Error | Consent processing failed |
IdP Login Endpoints
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 emailpassword: The user's passwordcsrf_token: CSRF protection token (from template variable.CSRFToken)remember_me(optional): Set toonto remember the session
Response (success - 302 Found):
Location: /oidc/authorize?response_type=code&client_id=demo&...
| Status Code | Description |
|---|---|
200 OK | Login form rendered or re-rendered with error |
302 Found | Login succeeded and redirected to IdP endpoint |
400 Bad Request | Invalid login request, missing flow state, or CSRF token validation failed |
500 Internal Server Error | Login 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 appcsrf_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 Code | Description |
|---|---|
200 OK | MFA form rendered or re-rendered with error |
302 Found | MFA validation succeeded |
400 Bad Request | Invalid MFA request, missing flow state, or CSRF token validation failed |
500 Internal Server Error | MFA processing failed |
Logged-Out Page
GET /logged_out (alias: GET /logged_out/:languageTag)
Response (success - 200 OK):
<HTML logged out page>
| Status Code | Description |
|---|---|
200 OK | Page rendered |
500 Internal Server Error | Rendering 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 Code | Description |
|---|---|
200 OK | Metadata returned |
500 Internal Server Error | Metadata 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 Code | Description |
|---|---|
200 OK | SAML response rendered |
302 Found | Redirect to IdP login or SP |
400 Bad Request | Invalid SAML request |
500 Internal Server Error | SSO 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 Code | Description |
|---|---|
200 OK | Logout response rendered |
302 Found | Redirect to SP or IdP |
400 Bad Request | Invalid SAML request |
500 Internal Server Error | SLO processing failed |
Multi-Factor Authentication (MFA) API
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 Code | Description |
|---|---|
200 OK | TOTP secret generated |
401 Unauthorized | Frontend session missing |
500 Internal Server Error | TOTP 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 Code | Description |
|---|---|
200 OK | TOTP registered |
400 Bad Request | Invalid code or request |
401 Unauthorized | Frontend session missing |
500 Internal Server Error | TOTP registration failed |
DELETE /api/v1/mfa/totp
Response (success - 200 OK):
{
"status": "success",
"message": "TOTP deleted successfully"
}
| Status Code | Description |
|---|---|
200 OK | TOTP deleted |
401 Unauthorized | Frontend session missing |
500 Internal Server Error | TOTP deletion failed |
Recovery Codes
POST /api/v1/mfa/recovery-codes/generate
Response (success - 200 OK):
{
"codes": [
"R2D2-1C3P",
"A9TQ-0Z9L",
"K2M8-0P1F"
]
}
| Status Code | Description |
|---|---|
200 OK | Recovery codes generated |
400 Bad Request | No MFA method enabled |
401 Unauthorized | Frontend session missing |
500 Internal Server Error | Generation failed |
WebAuthn (Names Only)
Per requirement, WebAuthn is listed by endpoint name only:
GET /api/v1/mfa/webauthn/register/beginPOST /api/v1/mfa/webauthn/register/finishDELETE /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 Code | Description |
|---|---|
200 OK | Sessions returned |
400 Bad Request | Missing user_id |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Insufficient role |
500 Internal Server Error | Session lookup failed |
DELETE /api/v1/oidc/sessions/{user_id}
Response (success - 204 No Content):
(empty body)
| Status Code | Description |
|---|---|
204 No Content | All sessions deleted |
400 Bad Request | Missing user_id |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Insufficient role |
500 Internal Server Error | Deletion failed |
DELETE /api/v1/oidc/sessions/{user_id}/{token}
Response (success - 204 No Content):
(empty body)
| Status Code | Description |
|---|---|
204 No Content | Session deleted |
400 Bad Request | Missing token |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Insufficient role |
500 Internal Server Error | Deletion 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_secretDELETE /api/v1/mfa-backchannel/totp
Body fields:usernamePOST /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), optionalbackend,backend_namePOST /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 OKsuccess400 Bad Requestinvalid input401 Unauthorizedor403 Forbiddenbackchannel authentication/authorization failure500 Internal Server Errorbackend 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 Code | Description |
|---|---|
200 OK | List returned |
400 Bad Request | Invalid filter request |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Missing required role |
500 Internal Server Error | List 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 Code | Description |
|---|---|
200 OK | Brute force entries flushed |
400 Bad Request | Invalid request payload |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Missing required role |
500 Internal Server Error | Flush 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 Code | Description |
|---|---|
202 Accepted | Flush job enqueued |
400 Bad Request | Invalid request payload |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Missing required role |
500 Internal Server Error | Enqueue 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 Code | Description |
|---|---|
200 OK | Cache flushed |
400 Bad Request | Invalid request payload |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Missing required role |
500 Internal Server Error | Cache flush failed |
If lua.config.cache_flush_script_path is configured, Nauthilus executes nauthilus_cache_flush(request) during cache flush.
The script can return additional Redis keys to delete and an optional account name.
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 Code | Description |
|---|---|
202 Accepted | Cache flush job enqueued |
400 Bad Request | Invalid request payload |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Missing required role |
500 Internal Server Error | Enqueue 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 Code | Description |
|---|---|
200 OK | Job status returned |
404 Not Found | Job ID not found |
500 Internal Server Error | Status 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 Code | Description |
|---|---|
200 OK | Configuration returned |
401 Unauthorized | Missing/invalid credentials |
403 Forbidden | Missing required role |
404 Not Found | Endpoint disabled |
500 Internal Server Error | Config 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 Code | Description |
|---|---|
200 OK | Token issued |
400 Bad Request | Invalid request payload |
401 Unauthorized | Invalid credentials |
403 Forbidden | Missing required role |
500 Internal Server Error | Token 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 Code | Description |
|---|---|
200 OK | Token refreshed |
400 Bad Request | Missing refresh token |
401 Unauthorized | Invalid refresh token |
500 Internal Server Error | Refresh failed |
Custom Hooks
ANY /api/v1/custom/{hookName}
Request Body (example):
{
"username": "testuser",
"action": "provision"
}
Response (example):
{
"status": "ok",
"message": "Hook executed"
}
| Status Code | Description |
|---|---|
200 OK | Hook executed |
403 Forbidden | Hook disabled or insufficient permissions |
500 Internal Server Error | Hook 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 Code | Description |
|---|---|
200 OK | Developer UI rendered |
403 Forbidden | Developer mode disabled |
404 Not Found | Template not found |
500 Internal Server Error | Rendering 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 Code | Description |
|---|---|
200 OK | Prometheus metrics returned |
404 Not Found | Metrics route not enabled |
Global Response Headers
Authentication endpoints include these tracking headers:
| Header | Description |
|---|---|
X-Nauthilus-Session | A unique request GUID for log correlation |
X-Nauthilus-Memory-Cache | Hit if the result came from local cache, otherwise Miss |
Auth-Status | OK or FAIL (authentication endpoints only) |