Email & Password Authentication
Email and password is the foundational authentication method in Ithbat IAM. This guide covers the complete flow: registration with email verification, login with JWT token issuance, password reset, and authenticated password changes.
Base URL
All authentication endpoints live under:
https://api.ithbat.io/api/v1/auth
All requests require the X-Tenant-ID header unless stated otherwise.
Registration
Request
POST /api/v1/auth/register
Required header: X-Tenant-ID: <tenant-uuid>
{
"email": "[email protected]",
"firstName": "Sara",
"familyName": "Al-Rashidi",
"fatherName": "Ahmad",
"grandfatherName": "Khalid",
"password": "SecurePass123!"
}
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User's email address |
firstName | string | Yes | Given name |
familyName | string | Yes | Family/last name |
fatherName | string | No | Father's name (used in MENA naming conventions) |
grandfatherName | string | No | Grandfather's name |
password | string | Yes | Must be at least 8 characters |
Response — 201 Created
{
"userId": "usr_01J8X...",
"email": "[email protected]",
"displayName": "Sara Al-Rashidi",
"tenantId": "ten_01J8X...",
"message": "Registration successful. Please check your email to verify your account."
}
The account is created immediately, but the user cannot log in until their email address is verified (unless the tenant has email verification disabled in settings).
Password Requirements
- Minimum 8 characters
- Additional complexity rules (uppercase, digits, special characters) are configured per tenant via the password policy settings
Email Verification
After registration, Ithbat IAM sends a verification email containing a time-limited token. The token expires after 24 hours.
Verify Email
POST /api/v1/auth/verify-email
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Response — 200 OK
{
"message": "Email verified successfully"
}
Resend Verification Email
POST /api/v1/auth/resend-verification
{
"email": "[email protected]"
}
The response is always 200 OK with a generic message to prevent email enumeration:
{
"message": "If the email exists and is not verified, a verification link has been sent"
}
Pass X-Tenant-ID if you know the tenant. If omitted, the system resolves the tenant from the email domain automatically.
Login
POST /api/v1/auth/login
Request
{
"email": "[email protected]",
"password": "SecurePass123!"
}
X-Tenant-ID is optional — when omitted, the tenant is resolved from the email domain. Always send it when you know it to avoid the extra lookup.
Response — 200 OK (standard login)
{
"accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
"idToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"user": {
"id": "usr_01J8X...",
"tenantId": "ten_01J8X...",
"email": "[email protected]",
"firstName": "Sara",
"fatherName": "Ahmad",
"grandfatherName": "Khalid",
"familyName": "Al-Rashidi",
"displayName": "Sara Al-Rashidi",
"roles": ["member"],
"permissions": ["profile:read", "profile:write"]
}
}
Response — 200 OK (MFA required)
When MFA is enabled on the account, the initial login response does not include tokens. Instead:
{
"mfaRequired": true,
"mfaToken": "mfa_challenge_token_here"
}
Use this mfaToken to complete the second factor challenge. See the MFA guide for the full flow.
Registration → Verification → Login Flow
sequenceDiagram
participant Client
participant Ithbat as Ithbat IAM
participant Email as Email Service
Client->>Ithbat: POST /api/v1/auth/register
Ithbat->>Ithbat: Validate fields, hash password
Ithbat->>Email: Send verification email
Ithbat-->>Client: 201 { userId, message }
Email-->>Client: Verification link (24h TTL)
Client->>Ithbat: POST /api/v1/auth/verify-email { token }
Ithbat->>Ithbat: Mark email as verified
Ithbat-->>Client: 200 { message: "Email verified successfully" }
Client->>Ithbat: POST /api/v1/auth/login { email, password }
Ithbat->>Ithbat: Verify credentials
Ithbat-->>Client: 200 { accessToken, refreshToken, idToken, user }
Password Reset
The password reset flow is three steps: initiate (sends email), validate token (optional UI check), complete reset.
Step 1 — Initiate Reset
POST /api/v1/auth/password-reset/initiate
{
"email": "[email protected]"
}
The response is always 200 OK with a generic message regardless of whether the email exists:
{
"message": "If the email exists, a password reset link has been sent"
}
The reset token expires after 1 hour.
Never tell users whether an email is registered in your system. The generic response is intentional — it prevents account enumeration attacks.
Step 2 — Validate Token (optional)
Use this endpoint to check token validity before showing the password reset form. This avoids displaying an input form to a user with an expired token.
POST /api/v1/auth/password-reset/validate
{
"token": "abc123def456..."
}
Response — 200 OK
{
"valid": true,
"message": "Token is valid"
}
Step 3 — Complete Reset
POST /api/v1/auth/password-reset/complete
{
"token": "abc123def456...",
"newPassword": "NewSecurePass456!"
}
Response — 200 OK
{
"message": "Password reset successfully"
}
After a successful reset, all active sessions for the user are invalidated.
Change Password (Authenticated)
Allows an authenticated user to change their own password. Requires the current password as confirmation.
POST /api/v1/auth/change-password
Required header: Authorization: Bearer <accessToken>
{
"current_password": "SecurePass123!",
"new_password": "NewSecurePass456!",
"revoke_other_sessions": true
}
| Field | Type | Required | Description |
|---|---|---|---|
current_password | string | Yes | The user's current password |
new_password | string | Yes | Minimum 8 characters |
revoke_other_sessions | boolean | No | If true, signs out all other active sessions |
Response — 200 OK
{
"message": "Password changed successfully"
}
Logout
POST /api/v1/auth/logout
Required header: Authorization: Bearer <accessToken>
{
"refreshToken": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..."
}
Passing refreshToken revokes that specific token. If omitted, the server revokes the session associated with the access token.
Response — 200 OK
{
"message": "Logged out successfully"
}
Code Examples
cURL — Register
curl -X POST https://api.ithbat.io/api/v1/auth/register \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: ten_01J8X..." \
-d '{
"email": "[email protected]",
"firstName": "Sara",
"familyName": "Al-Rashidi",
"password": "SecurePass123!"
}'
cURL — Login
curl -X POST https://api.ithbat.io/api/v1/auth/login \
-H "Content-Type: application/json" \
-H "X-Tenant-ID: ten_01J8X..." \
-d '{
"email": "[email protected]",
"password": "SecurePass123!"
}'
JavaScript SDK
import { IthbatSDK } from '@ithbatiam/sdk';
const ithbat = new IthbatSDK({
tenantId: 'ten_01J8X...',
baseUrl: 'https://api.ithbat.io',
});
// Register
const registration = await ithbat.auth.register({
email: '[email protected]',
firstName: 'Sara',
familyName: 'Al-Rashidi',
password: 'SecurePass123!',
});
// Login
const session = await ithbat.auth.login({
email: '[email protected]',
password: 'SecurePass123!',
});
console.log(session.accessToken);
console.log(session.user.displayName);
// Password reset
await ithbat.auth.initiatePasswordReset({ email: '[email protected]' });
// Complete reset with token from email link
await ithbat.auth.resetPassword({
token: 'abc123...',
newPassword: 'NewSecurePass456!',
});
Error Handling
| HTTP Status | Error Code | Cause |
|---|---|---|
400 | VALIDATION_ERROR | Missing required field |
400 | VALIDATION_ERROR | X-Tenant-ID header missing on register |
401 | UNAUTHORIZED | Invalid credentials |
401 | UNAUTHORIZED | Email not yet verified |
403 | FORBIDDEN | Account suspended or locked |
404 | NOT_FOUND | Tenant not found for email domain |
429 | RATE_LIMITED | Too many login attempts |
Error Response Format
{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid credentials",
"details": null
}
}
Login endpoints do not distinguish between "wrong password" and "account does not exist" in the error message. Both return Invalid credentials. This prevents user enumeration.
Next Steps
- Token Lifecycle — understand access tokens, refresh tokens, and session management
- Multi-Factor Authentication — add a second factor to login
- Passwordless Authentication — allow login without a password via magic link
- Social Login — let users sign in with Google, GitHub, and more