Authentication API
All authentication endpoints are public (no Bearer token required) unless noted otherwise. They are subject to rate limiting. Include X-Tenant-ID when the tenant cannot be inferred from the request.
Base path: https://api.ithbat.io/api/v1/auth/
POST /api/v1/auth/login
Authenticate a user with email and password. Returns JWT tokens. If MFA is enabled, the response will include mfaRequired: true and an mfaToken to use for the MFA verification step. In that case, accessToken and refreshToken are absent.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
password | string | Yes | User's password |
rememberMe | boolean | No | Extend session duration |
curl -X POST "https://api.ithbat.io/api/v1/auth/login" \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a" \
-d '{
"email": "[email protected]",
"password": "correct-horse-battery-staple"
}'
Response 200 — Success
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"email": "[email protected]",
"firstName": "Alice",
"fatherName": "",
"grandfatherName": "",
"familyName": "Smith",
"displayName": "Alice Smith",
"roles": ["admin"],
"permissions": ["admin"]
}
}
}
Response 200 — MFA Required
{
"mfaRequired": true,
"mfaToken": "mfa_eyJhbGciOiJIUzI1NiJ9..."
}
When mfaRequired is true, accessToken and refreshToken are absent. Call POST /api/v1/auth/mfa/verify with the mfaToken and the user's TOTP code.
Error Codes
| Code | HTTP | Description |
|---|---|---|
INVALID_CREDENTIALS | 401 | Email or password is incorrect |
ACCOUNT_SUSPENDED | 403 | Account has been suspended |
ACCOUNT_NOT_VERIFIED | 403 | Email address has not been verified |
TENANT_NOT_FOUND | 404 | Tenant not found |
TENANT_SUSPENDED | 403 | Tenant account is suspended |
POST /api/v1/auth/register
Register a new user account in the current tenant. Sends a verification email upon successful registration.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
firstName | string | Yes | First name |
fatherName | string | No | Father's name (Arabic naming convention) |
grandfatherName | string | No | Grandfather's name (Arabic naming convention) |
familyName | string | Yes | Family/last name |
password | string | Yes | Password (must meet tenant's password policy) |
curl -X POST "https://api.ithbat.io/api/v1/auth/register" \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a" \
-d '{
"email": "[email protected]",
"firstName": "Bob",
"familyName": "Jones",
"password": "SecurePass@2024"
}'
Response 201
{
"success": true,
"data": {
"userId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"email": "[email protected]",
"displayName": "Bob Jones",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"message": "Registration successful. Please verify your email address."
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
DUPLICATE_EMAIL | 409 | A user with this email already exists |
VALIDATION_ERROR | 400 | Password does not meet policy requirements |
REGISTRATION_DISABLED | 403 | Self-registration is disabled for this tenant |
POST /api/v1/auth/refresh
Exchange a valid refresh token for a new access token and refresh token pair. The old refresh token is revoked.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
refreshToken | string | Yes | A valid refresh token |
curl -X POST "https://api.ithbat.io/api/v1/auth/refresh" \
-H "Content-Type: application/json" \
-d '{"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}'
Response 200
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
TOKEN_INVALID | 401 | Refresh token is malformed or has been revoked |
TOKEN_EXPIRED | 401 | Refresh token has expired |
POST /api/v1/auth/logout
Authentication required.
Revoke the current session. Optionally revokes the refresh token to prevent further use.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
refreshToken | string | No | Refresh token to revoke alongside the session |
curl -X POST "https://api.ithbat.io/api/v1/auth/logout" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."}'
Response 200
{
"success": true,
"message": "Logged out successfully"
}
POST /api/v1/auth/change-password
Authentication required.
Change the authenticated user's password. Optionally revoke all other active sessions after the change.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
current_password | string | Yes | Current password |
new_password | string | Yes | New password (minimum 8 characters) |
revoke_other_sessions | boolean | No | Revoke all sessions except the current one (default: false) |
curl -X POST "https://api.ithbat.io/api/v1/auth/change-password" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{
"current_password": "OldPass@2023",
"new_password": "NewPass@2024",
"revoke_other_sessions": true
}'
Response 200
{
"success": true,
"data": {
"message": "Password changed successfully"
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
INVALID_CREDENTIALS | 401 | Current password is incorrect |
VALIDATION_ERROR | 400 | New password does not meet policy requirements |
POST /api/v1/auth/password-reset/initiate
Request a password reset email for the given address. Always returns 200 to prevent email enumeration, regardless of whether the address exists.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address associated with the account |
curl -X POST "https://api.ithbat.io/api/v1/auth/password-reset/initiate" \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a" \
-d '{"email": "[email protected]"}'
Response 200
{
"success": true,
"data": {
"message": "If an account exists for this email, a password reset link has been sent."
}
}
POST /api/v1/auth/password-reset/validate
Validate a password reset token before presenting the reset form. This avoids showing the form only to fail after submission.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Token from the reset email link |
curl -X POST "https://api.ithbat.io/api/v1/auth/password-reset/validate" \
-H "Content-Type: application/json" \
-d '{"token": "prst_abc123xyz..."}'
Response 200
{
"success": true,
"data": {
"valid": true
}
}
Response 200 — Invalid token
{
"success": true,
"data": {
"valid": false,
"message": "Token is invalid or has expired"
}
}
POST /api/v1/auth/password-reset/complete
Complete the password reset using the token from the reset email.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Token from the reset email link |
newPassword | string | Yes | New password (must meet tenant's password policy) |
curl -X POST "https://api.ithbat.io/api/v1/auth/password-reset/complete" \
-H "Content-Type: application/json" \
-d '{
"token": "prst_abc123xyz...",
"newPassword": "NewSecurePass@2024"
}'
Response 200
{
"success": true,
"data": {
"message": "Password has been reset successfully. You can now log in with your new password."
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
TOKEN_INVALID | 400 | Reset token is invalid or has already been used |
TOKEN_EXPIRED | 400 | Reset token has expired |
VALIDATION_ERROR | 400 | New password does not meet policy requirements |
POST /api/v1/auth/verify-email
Verify a user's email address using the token from the verification email.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Token from the verification email |
curl -X POST "https://api.ithbat.io/api/v1/auth/verify-email" \
-H "Content-Type: application/json" \
-d '{"token": "vfy_abc123xyz..."}'
Response 200
{
"success": true,
"data": {
"message": "Email address verified successfully"
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
TOKEN_INVALID | 400 | Verification token is invalid or has already been used |
TOKEN_EXPIRED | 400 | Verification token has expired |
POST /api/v1/auth/resend-verification
Resend the email verification email to the given address.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address that needs verification |
curl -X POST "https://api.ithbat.io/api/v1/auth/resend-verification" \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a" \
-d '{"email": "[email protected]"}'
Response 200
{
"success": true,
"message": "Verification email sent"
}
POST /api/v1/auth/passwordless/start
Send a magic link to the specified email address. The link is valid for 15 minutes.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address to send the magic link to |
tenant_id | string | No | Tenant ID (required if not in X-Tenant-ID header) |
curl -X POST "https://api.ithbat.io/api/v1/auth/passwordless/start" \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a" \
-d '{"email": "[email protected]"}'
Response 200
{
"success": true,
"data": {
"message": "Magic link sent. Check your email to continue."
}
}
POST /api/v1/auth/passwordless/verify
Verify a magic link token and exchange it for JWT tokens.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
token | string | Yes | Token from the magic link URL |
tenant_id | string | No | Tenant ID (required if not in X-Tenant-ID header) |
curl -X POST "https://api.ithbat.io/api/v1/auth/passwordless/verify" \
-H "Content-Type: application/json" \
-d '{
"token": "plnk_abc123xyz...",
"tenant_id": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a"
}'
Response 200
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "[email protected]",
"displayName": "Alice Smith",
"roles": ["user"],
"permissions": ["user:read"]
}
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
TOKEN_INVALID | 400 | Magic link token is invalid or has already been used |
TOKEN_EXPIRED | 400 | Magic link has expired (valid for 15 minutes) |
GET /api/v1/auth/social/{provider}/login
Initiate a social login flow. Redirects the browser to the identity provider's authorization page. Supported providers: google, github, microsoft, apple.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
provider | string | Identity provider name (e.g., google, github) |
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
redirect_uri | string | No | URI to redirect after authentication |
state | string | No | Opaque value for CSRF protection |
curl -L "https://api.ithbat.io/api/v1/auth/social/google/login?redirect_uri=https%3A%2F%2Fapp.acme.com%2Fcallback" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a"
This endpoint returns HTTP 302 and redirects to Google's OAuth authorization URL.
GET /api/v1/auth/social/{provider}/callback
OAuth callback endpoint. The identity provider redirects here after user authorization. Ithbat exchanges the authorization code, creates or links the user account, and redirects back to your application with JWT tokens.
This endpoint is called by the identity provider — your application does not call it directly. Configure your OAuth app's redirect URI as https://api.ithbat.io/api/v1/auth/social/{provider}/callback.
POST /api/v1/auth/mfa/setup
Authentication required.
Initialize TOTP MFA setup for the authenticated user. Returns a TOTP secret and QR code URI to display to the user.
curl -X POST "https://api.ithbat.io/api/v1/auth/mfa/setup" \
-H "Authorization: Bearer <access_token>"
Response 200
{
"success": true,
"data": {
"secret": "JBSWY3DPEHPK3PXP",
"qrCodeUri": "otpauth://totp/Ithbat%3Aalice%40acme.com?secret=JBSWY3DPEHPK3PXP&issuer=Ithbat",
"backupCodes": [
"12345-67890",
"23456-78901",
"34567-89012",
"45678-90123",
"56789-01234",
"67890-12345",
"78901-23456",
"89012-34567"
]
}
}
After calling setup, call POST /api/v1/auth/mfa/verify-setup with a valid TOTP code to activate MFA.
POST /api/v1/auth/mfa/verify-setup
Authentication required.
Confirm MFA setup by providing the first valid TOTP code from the authenticator app. MFA is not active until this step is completed.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | 6-digit TOTP code from the authenticator app |
curl -X POST "https://api.ithbat.io/api/v1/auth/mfa/verify-setup" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"code": "123456"}'
Response 200
{
"success": true,
"message": "MFA enabled successfully"
}
POST /api/v1/auth/mfa/verify
Verify an MFA code during the login flow. Use the mfaToken from the login response.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
mfaToken | string | Yes | The MFA token returned from the login response |
code | string | Yes | 6-digit TOTP code from the authenticator app |
curl -X POST "https://api.ithbat.io/api/v1/auth/mfa/verify" \
-H "Content-Type: application/json" \
-d '{
"mfaToken": "mfa_eyJhbGciOiJIUzI1NiJ9...",
"code": "123456"
}'
Response 200
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"email": "[email protected]",
"displayName": "Alice Smith",
"roles": ["admin"],
"permissions": ["admin"]
}
}
}
Error Codes
| Code | HTTP | Description |
|---|---|---|
MFA_TOKEN_INVALID | 401 | MFA token is invalid or has expired |
MFA_CODE_INVALID | 401 | TOTP code is incorrect |
MFA_CODE_ALREADY_USED | 401 | This TOTP code has already been used |
POST /api/v1/auth/mfa/verify-backup
Verify a backup code during the login flow when the authenticator app is unavailable. Each backup code can only be used once.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
mfaToken | string | Yes | The MFA token from the login response |
code | string | Yes | One of the backup codes from MFA setup |
curl -X POST "https://api.ithbat.io/api/v1/auth/mfa/verify-backup" \
-H "Content-Type: application/json" \
-d '{
"mfaToken": "mfa_eyJhbGciOiJIUzI1NiJ9...",
"code": "12345-67890"
}'
Response 200 — Same token response as POST /api/v1/auth/mfa/verify.
SAML 2.0 Endpoints
For SAML-based enterprise SSO, Ithbat exposes per-tenant SAML service provider endpoints.
| Method | Path | Description |
|---|---|---|
GET | /api/v1/auth/saml/{tenant_id}/metadata | Download SP metadata XML for IdP configuration |
GET | /api/v1/auth/saml/{tenant_id}/login | Initiate SAML login (redirects to IdP) |
POST | /api/v1/auth/saml/{tenant_id}/acs | Assertion Consumer Service — receives SAML response from IdP |
Configure your SAML identity provider using the metadata URL:
https://api.ithbat.io/api/v1/auth/saml/{tenant_id}/metadata
See the SAML Configuration Guide for full setup instructions.
Social Code Exchange
POST /api/v1/auth/social/exchange
Exchange a social provider authorization code for Ithbat IAM tokens. Use this in SPA or mobile flows where the frontend receives the authorization code directly from the social provider.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
provider | string | Yes | Social provider (google, github, microsoft, apple) |
code | string | Yes | Authorization code from the provider |
tenantId | string | Yes | Tenant ID |
redirectUri | string | Yes | Redirect URI used in the authorization request |
curl -X POST "https://api.ithbat.io/api/v1/auth/social/exchange" \
-H "Content-Type: application/json" \
-d '{
"provider": "google",
"code": "4/0AX4XfWh...",
"tenantId": "3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a",
"redirectUri": "https://app.acme.com/auth/callback"
}'
Response 200
{
"success": true,
"data": {
"accessToken": "eyJhbGciOiJSUzI1NiIs...",
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2g...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "u1a2b3c4-d5e6-7890-abcd-ef1234567890",
"email": "[email protected]",
"displayName": "Alice Smith",
"provider": "google"
}
}
}
Social Provider List
GET /api/v1/auth/social/providers
List the social login providers enabled for the current tenant.
curl "https://api.ithbat.io/api/v1/auth/social/providers" \
-H "X-Tenant-ID: 3e7a9f12-4b2c-4d8e-a1f0-9c2b3d4e5f6a"
Response 200
{
"success": true,
"data": {
"providers": [
{ "id": "google", "name": "Google", "enabled": true },
{ "id": "microsoft", "name": "Microsoft", "enabled": true },
{ "id": "github", "name": "GitHub", "enabled": false }
]
}
}