Skip to Content

Authentication API

The Authentication API handles all identity verification flows: email/password login, signup, token refresh, magic links, two-factor authentication, and the OAuth2 authorization code flow. Public endpoints do not require an Authorization header; user and admin endpoints do.


Email / Password

POST/api/auth/login

Authenticate a user with email and password. Returns an access token, refresh token, session ID, and token expiry. If the tenant or application requires 2FA and the user has 2FA configured, the response will indicate that a second factor is required before tokens are issued.

Request body

{ "email": "[email protected]", "password": "secret123" }

Success response (no 2FA required)

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "refreshToken": "rt_...", "expiresIn": 900, "sessionId": "sess_abc123", "tokenType": "Bearer" } }

Success response (2FA required)

{ "ok": true, "data": { "requiresTwoFactor": true, "sessionId": "sess_abc123", "availableMethods": ["totp", "sms"] } }

Error codes

CodeHTTPDescription
INVALID_CREDENTIALS401Email or password is incorrect
ACCOUNT_LOCKED403Account is locked due to repeated failures
ACCOUNT_DISABLED403Account has been disabled by an administrator
RATE_LIMITED429Too many login attempts

POST/api/auth/signup

Register a new user account. The tenant must have signup enabled. On success, returns the same token structure as login. If email verification is required by the tenant, an email is sent and the user cannot log in until verified.

Request body

{ "email": "[email protected]", "password": "securepassword", "firstName": "Jane", "lastName": "Doe" }

firstName and lastName are optional. password is required unless the tenant is configured for passwordless-only signup.

Success response

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "refreshToken": "rt_...", "expiresIn": 900, "sessionId": "sess_xyz789", "tokenType": "Bearer" } }

Error codes

CodeHTTPDescription
EMAIL_TAKEN409An account with this email already exists
SIGNUP_DISABLED403The tenant has disabled public signup
WEAK_PASSWORD400Password does not meet strength requirements
VALIDATION_ERROR400Request body failed schema validation

Token Endpoint (OAuth2)

POST/api/auth/token

OAuth2 token endpoint. Supports multiple grant types: Authorization Code (with PKCE), Client Credentials (M2M), and Device Code. The request body shape differs by grant type.

This endpoint is the standard OAuth2 token endpoint referenced in the OIDC Discovery document. It accepts application/json or application/x-www-form-urlencoded request bodies.

Grant: Authorization Code + PKCE

Used to exchange an authorization code (from the hosted login redirect) for tokens. The code_verifier is the original random value from which the code_challenge was derived.

Request body

{ "grant_type": "authorization_code", "code": "auth_code_from_redirect", "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", "redirect_uri": "https://app.yourdomain.com/callback", "client_id": "your-client-id" }

Success response

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "refreshToken": "rt_...", "idToken": "eyJhbGciOiJSUzI1NiJ9...", "expiresIn": 900, "tokenType": "Bearer" } }

Error codes

CodeHTTPDescription
CODE_INVALID400Authorization code does not exist or has expired
CODE_USED400Authorization code has already been exchanged (single-use)
PKCE_MISMATCH400SHA256(code_verifier) does not match the stored challenge
REDIRECT_URI_MISMATCH400redirect_uri does not match the registered URI

Grant: Client Credentials (M2M)

Used for machine-to-machine authentication where no user is involved. The client authenticates using its client_id and client_secret.

Request body

{ "grant_type": "client_credentials", "client_id": "m2m-client-id", "client_secret": "m2m-client-secret", "scope": "read:users manage:roles" }

Success response

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "expiresIn": 3600, "tokenType": "Bearer", "scope": "read:users manage:roles" } }

Grant: Device Code (RFC 8628)

Used for devices that cannot display a browser (CLIs, IoT, smart TVs). First, the device requests a device code; the user then visits the verification URL on a separate device and approves. The device polls until approved.

Request body (polling)

{ "grant_type": "urn:ietf:params:oauth:grant-type:device_code", "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS", "client_id": "your-client-id" }

Pending response (user has not yet approved)

{ "ok": false, "error": { "code": "AUTHORIZATION_PENDING", "message": "The user has not yet approved the request. Continue polling." } }

Token Management

POST/api/auth/refresh

Exchange a refresh token for a new access token and a new refresh token. Refresh tokens are rotated on each use — the old refresh token is immediately invalidated.

Request body

{ "refreshToken": "rt_..." }

Success response

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "refreshToken": "rt_new...", "expiresIn": 900, "tokenType": "Bearer" } }

Error codes

CodeHTTPDescription
REFRESH_TOKEN_INVALID401Token does not exist or has been revoked
REFRESH_TOKEN_EXPIRED401Token has passed its expiry time

POST/api/auth/validateRequires: authenticated user

Validate the current access token and return the authenticated user’s information. This endpoint is also the OIDC UserInfo endpoint.

Request: No body required. The access token is read from the Authorization: Bearer header.

Success response

{ "ok": true, "data": { "valid": true, "userId": "usr_abc123", "email": "[email protected]", "username": "jane.doe", "firstName": "Jane", "lastName": "Doe", "roles": ["viewer", "billing-admin"], "tenant": "acme-corp" } }

POST/api/auth/logoutRequires: authenticated user

Invalidate the current session. The refresh token associated with the session is revoked. The access token continues to be valid until it expires naturally (JWTs are not blocklisted by default — rely on short expiry times).

Request: No body required.

Success response

{ "ok": true, "data": { "loggedOut": true } }

POST/api/auth/magic-link

Send a magic link (passwordless login email) to the specified address. If no account exists and allowSignup is enabled in the tenant’s passwordless configuration, a new account is created automatically when the link is clicked.

Request body

{ "email": "[email protected]", "redirectUrl": "https://app.yourdomain.com/callback" }

redirectUrl is optional; falls back to the tenant’s configured default redirect URL.

Success response

{ "ok": true, "data": { "sent": true } }

The response is always { sent: true } regardless of whether the email exists, to prevent user enumeration.


POST/api/auth/magic-link/verify

Verify a magic link token. Called automatically by the hosted login page when the user clicks the link. Returns tokens on success.

Request body

{ "token": "mlnk_..." }

Success response

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "refreshToken": "rt_...", "expiresIn": 900, "tokenType": "Bearer" } }

Error codes

CodeHTTPDescription
MAGIC_LINK_INVALID400Token is malformed or does not exist
MAGIC_LINK_EXPIRED400Token has expired (default expiry: 15 minutes)
MAGIC_LINK_USED400Token has already been consumed (single-use)

Password Reset

POST/api/auth/forgot-password

Initiate a password reset flow. Sends an email with a reset link to the specified address. The response is always successful to prevent user enumeration.

Request body

{ "email": "[email protected]" }

Success response

{ "ok": true, "data": { "sent": true } }

Two-Factor Authentication

POST/api/auth/verify-2fa

Verify a second factor after initial password authentication. Call this with the session ID returned from login (when requiresTwoFactor: true) and the OTP code or WebAuthn response. On success, returns full access and refresh tokens.

Request body — TOTP

{ "sessionId": "sess_abc123", "code": "123456", "method": "totp" }

Request body — SMS OTP

{ "sessionId": "sess_abc123", "code": "789012", "method": "sms" }

Request body — WebAuthn

{ "sessionId": "sess_abc123", "method": "webauthn", "response": { } }

response is the AuthenticatorAssertionResponse object from the WebAuthn browser API.

Success response

{ "ok": true, "data": { "accessToken": "eyJhbGciOiJSUzI1NiJ9...", "refreshToken": "rt_...", "expiresIn": 900, "tokenType": "Bearer" } }

Error codes

CodeHTTPDescription
INVALID_OTP400The provided code is incorrect
OTP_EXPIRED400The code has expired
SESSION_INVALID400The session ID is invalid or already consumed
WEBAUTHN_FAILED400WebAuthn assertion verification failed

GET/api/auth/check-2fa-requiredRequires: authenticated user

Check whether the current session requires 2FA verification before full access is granted. Useful for guarding pages after initial login to ensure the user has completed the full flow.

Response

{ "ok": true, "data": { "required": false, "verified": true, "availableMethods": ["totp", "sms"] } }

SSO Detection

POST/api/auth/sso/detect

Detect whether a user’s email domain has an Enterprise SSO connection configured. Use this to implement “smart” login forms that automatically redirect enterprise users to their SSO provider instead of showing the password field.

Request body

{ "email": "[email protected]" }

Response — SSO available

{ "ok": true, "data": { "ssoAvailable": true, "provider": "saml", "loginUrl": "https://api.altovar.net/api/auth/sso/login/enterprise-alias" } }

Response — no SSO

{ "ok": true, "data": { "ssoAvailable": false, "provider": null, "loginUrl": null } }

OAuth2 Authorization Endpoint

POST/api/oauth/authorize

Start an OAuth2 Authorization Code + PKCE flow. This endpoint creates a session and redirects the user to the Auris hosted login page. On successful authentication, Auris redirects to the registered redirect_uri with an authorization code.

This is typically triggered as a browser redirect (GET or form POST) rather than a fetch call. The SDK method loginWithRedirect() handles all of this automatically.

Parameters (query string or request body)

ParameterRequiredDescription
response_typeYesMust be "code"
client_idYesApplication Client ID
redirect_uriYesCallback URL (must be registered)
stateYesRandom CSRF token
code_challengeYesBASE64URL(SHA256(code_verifier))
code_challenge_methodYesMust be "S256"
scopeNoSpace-separated scopes (e.g., openid profile email)
login_hintNoPre-fill the email field
screen_hintNo"signup" to show the registration screen first
localeNoForce a specific locale (en, it, de, fr, es)
promptNo"login" to force re-authentication

Redirect on success

https://app.yourdomain.com/callback?code=auth_code_xxx&state=original_state

Redirect on error

https://app.yourdomain.com/callback?error=access_denied&error_description=User+cancelled&state=original_state

Error codes (returned as redirect parameters)

CodeDescription
invalid_requestMissing or invalid parameter
unauthorized_clientclient_id not found or redirect_uri not registered
access_deniedUser cancelled authentication
invalid_scopeRequested scope is not allowed