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
/api/auth/loginAuthenticate 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
| Code | HTTP | Description |
|---|---|---|
INVALID_CREDENTIALS | 401 | Email or password is incorrect |
ACCOUNT_LOCKED | 403 | Account is locked due to repeated failures |
ACCOUNT_DISABLED | 403 | Account has been disabled by an administrator |
RATE_LIMITED | 429 | Too many login attempts |
/api/auth/signupRegister 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
| Code | HTTP | Description |
|---|---|---|
EMAIL_TAKEN | 409 | An account with this email already exists |
SIGNUP_DISABLED | 403 | The tenant has disabled public signup |
WEAK_PASSWORD | 400 | Password does not meet strength requirements |
VALIDATION_ERROR | 400 | Request body failed schema validation |
Token Endpoint (OAuth2)
/api/auth/tokenOAuth2 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
| Code | HTTP | Description |
|---|---|---|
CODE_INVALID | 400 | Authorization code does not exist or has expired |
CODE_USED | 400 | Authorization code has already been exchanged (single-use) |
PKCE_MISMATCH | 400 | SHA256(code_verifier) does not match the stored challenge |
REDIRECT_URI_MISMATCH | 400 | redirect_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
/api/auth/refreshExchange 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
| Code | HTTP | Description |
|---|---|---|
REFRESH_TOKEN_INVALID | 401 | Token does not exist or has been revoked |
REFRESH_TOKEN_EXPIRED | 401 | Token has passed its expiry time |
/api/auth/validateRequires: authenticated userValidate 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"
}
}/api/auth/logoutRequires: authenticated userInvalidate 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 }
}Magic Links (Passwordless)
/api/auth/magic-linkSend 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.
/api/auth/magic-link/verifyVerify 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
| Code | HTTP | Description |
|---|---|---|
MAGIC_LINK_INVALID | 400 | Token is malformed or does not exist |
MAGIC_LINK_EXPIRED | 400 | Token has expired (default expiry: 15 minutes) |
MAGIC_LINK_USED | 400 | Token has already been consumed (single-use) |
Password Reset
/api/auth/forgot-passwordInitiate 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
/api/auth/verify-2faVerify 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
| Code | HTTP | Description |
|---|---|---|
INVALID_OTP | 400 | The provided code is incorrect |
OTP_EXPIRED | 400 | The code has expired |
SESSION_INVALID | 400 | The session ID is invalid or already consumed |
WEBAUTHN_FAILED | 400 | WebAuthn assertion verification failed |
/api/auth/check-2fa-requiredRequires: authenticated userCheck 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
/api/auth/sso/detectDetect 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
/api/oauth/authorizeStart 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)
| Parameter | Required | Description |
|---|---|---|
response_type | Yes | Must be "code" |
client_id | Yes | Application Client ID |
redirect_uri | Yes | Callback URL (must be registered) |
state | Yes | Random CSRF token |
code_challenge | Yes | BASE64URL(SHA256(code_verifier)) |
code_challenge_method | Yes | Must be "S256" |
scope | No | Space-separated scopes (e.g., openid profile email) |
login_hint | No | Pre-fill the email field |
screen_hint | No | "signup" to show the registration screen first |
locale | No | Force a specific locale (en, it, de, fr, es) |
prompt | No | "login" to force re-authentication |
Redirect on success
https://app.yourdomain.com/callback?code=auth_code_xxx&state=original_stateRedirect on error
https://app.yourdomain.com/callback?error=access_denied&error_description=User+cancelled&state=original_stateError codes (returned as redirect parameters)
| Code | Description |
|---|---|
invalid_request | Missing or invalid parameter |
unauthorized_client | client_id not found or redirect_uri not registered |
access_denied | User cancelled authentication |
invalid_scope | Requested scope is not allowed |
Related
- OAuth 2.0 & OIDC — Protocol fundamentals behind the authentication endpoints
- Tokens Explained — Access tokens, refresh tokens, and ID tokens in detail
- PKCE Flow — How the Authorization Code + PKCE exchange works
- Hosted Login Guide — Integrate hosted login with your application
- Magic Links — Passwordless email authentication
- Social Login — Configure third-party identity providers
- M2M Client Credentials — Server-to-server authentication
- Authentication Settings — Configure MFA, passwordless, and social login in the Console