Appearance
User Profile and Security Settings
Overview
This document provides a complete reference for user profile management and security settings, including profile updates, password management, and Multi-Factor Authentication (MFA).
Authentication
All profile endpoints require JWT authentication. Include the JWT token in the Authorization header:
Authorization: Bearer <your-jwt-token>Base URL
All endpoints are prefixed with /api/tenant/users/me
Endpoints
GET /api/tenant/users/me
Retrieve the current authenticated user's profile information.
Authentication: Required (JWT token)
Request:
http
GET /api/tenant/users/me
Authorization: Bearer <jwt-token>Response (200 OK):
json
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "550e8400-e29b-41d4-a716-446655440001",
"email": "user@example.com",
"name": "John Doe",
"role": "admin",
"permissions": {
"conversations": {
"view": true,
"create": true,
"edit": true,
"delete": true
},
"settings": {
"view": true,
"edit": true
},
"users": {
"view": true,
"invite": true,
"edit": true,
"delete": true
},
"analytics": {
"view": true
},
"integrations": {
"view": true,
"edit": true
}
},
"email_verified": true,
"status": "active",
"invited_by": null,
"last_login_at": "2025-01-13T20:00:00Z",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-13T20:00:00Z"
}
}Response Fields:
id(string, UUID): Unique user identifiertenant_id(string, UUID): Tenant identifier the user belongs toemail(string): User's email addressname(string, nullable): User's full name (can be null)role(string): User role - either "admin" or "user"permissions(object): Granular permissions objectemail_verified(boolean): Whether the user's email has been verifiedstatus(string): User status - "active", "invited", or "suspended"invited_by(string, UUID, nullable): ID of user who invited this user (if applicable)last_login_at(string, ISO 8601, nullable): Timestamp of last logincreated_at(string, ISO 8601): Account creation timestampupdated_at(string, ISO 8601): Last update timestamp
Error Responses:
401 Unauthorized- Missing or invalid authentication token404 Not Found- User not found
PUT /api/tenant/users/me
Update the current authenticated user's profile information. You can update name, email, and/or password. All fields are optional, but at least one must be provided.
Authentication: Required (JWT token)
Request:
http
PUT /api/tenant/users/me
Authorization: Bearer <jwt-token>
Content-Type: application/jsonRequest Body:
json
{
"name": "Jane Doe",
"email": "newemail@example.com",
"password": "newSecurePassword123",
"currentPassword": "oldPassword123"
}Request Fields:
name(string, optional): User's full name. Set tonullor empty string to clear the name.email(string, optional): New email address. Must be unique within the tenant.password(string, optional): New password. Must be at least 8 characters long.currentPassword(string, required ifpasswordis provided): Current password for verification when changing password.
Response (200 OK):
json
{
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "550e8400-e29b-41d4-a716-446655440001",
"email": "newemail@example.com",
"name": "Jane Doe",
"role": "admin",
"permissions": {
"conversations": {
"view": true,
"create": true,
"edit": true,
"delete": true
},
"settings": {
"view": true,
"edit": true
},
"users": {
"view": true,
"invite": true,
"edit": true,
"delete": true
},
"analytics": {
"view": true
},
"integrations": {
"view": true,
"edit": true
}
},
"email_verified": true,
"status": "active"
}
}Error Responses:
400 Bad Request- Invalid request:- Missing
currentPasswordwhenpasswordis provided - Password length less than 8 characters
- No fields provided for update
- Missing
401 Unauthorized- Missing or invalid authentication token, or incorrect current password404 Not Found- User not found409 Conflict- Email address already in use by another user in the tenant
Update Examples:
Update name only:
json
{
"name": "John Smith"
}Update email only:
json
{
"email": "newemail@example.com"
}Update password:
json
{
"password": "newSecurePassword123",
"currentPassword": "oldPassword123"
}Update multiple fields:
json
{
"name": "Jane Doe",
"email": "jane@example.com"
}Clear name (set to null):
json
{
"name": null
}Security Considerations
Password Updates: When updating a password, the current password must be provided for verification. This prevents unauthorized password changes.
Email Uniqueness: Email addresses must be unique within a tenant. Attempting to use an email that's already in use by another user will result in a 409 Conflict error.
Password Requirements: New passwords must be at least 12 characters long and include:
- At least one uppercase letter
- At least one lowercase letter
- At least one number
- At least one special character
- Must not be a common password
The system uses bcrypt for password hashing.
Authentication: All endpoints require valid JWT authentication. The token must be included in the Authorization header.
User Isolation: Users can only update their own profile. The system automatically enforces this by using the authenticated user's ID from the JWT token.
Frontend Integration
The frontend uses these endpoints through the tenantService in src/lib/api.ts:
typescript
// Get current user
const user = await tenantService.getCurrentUser();
// Update user profile
const updatedUser = await tenantService.updateCurrentUser({
name: "John Doe",
email: "john@example.com",
password: "newPassword123",
currentPassword: "oldPassword123"
});Database Schema
The user profile data is stored in the tenant_users table:
id(UUID, PRIMARY KEY)tenant_id(UUID, FOREIGN KEY)email(VARCHAR(255), NOT NULL, UNIQUE per tenant)name(VARCHAR(255), nullable) - Added via migration20260125000000_add_name_to_tenant_users.sqlpassword_hash(TEXT, nullable)role(VARCHAR(20), DEFAULT 'user')permissions(JSONB)email_verified(BOOLEAN, DEFAULT FALSE)status(VARCHAR(20), DEFAULT 'invited')mfa_enabled(BOOLEAN, DEFAULT false) - Added via migration20260126000000_add_mfa_support.sqlmfa_method(VARCHAR(20), DEFAULT 'none') - 'totp', 'sms', or 'none'mfa_secret(TEXT, nullable) - Encrypted TOTP secretmfa_backup_codes(TEXT[], nullable) - Array of hashed backup codesmfa_phone_number(VARCHAR(20), nullable) - Phone number for SMS MFAmfa_enrolled_at(TIMESTAMP, nullable) - When MFA was first enabledmfa_last_used_at(TIMESTAMP, nullable) - Last successful MFA verificationcreated_at(TIMESTAMP)updated_at(TIMESTAMP)
Migration Notes
- The
namefield was added to thetenant_userstable via migration20260125000000_add_name_to_tenant_users.sql. This field is nullable to support existing users who may not have a name set. - MFA support fields were added via migration
20260126000000_add_mfa_support.sql, includingmfa_enabled,mfa_method,mfa_secret,mfa_backup_codes,mfa_phone_number,mfa_enrolled_at, andmfa_last_used_at.
Multi-Factor Authentication (MFA)
MFA Overview
The platform supports Multi-Factor Authentication (MFA) to add an extra layer of security to your account. MFA is highly recommended for all users, especially administrators.
MFA Methods
Two MFA methods are available:
TOTP (Authenticator App): Use apps like Google Authenticator, Microsoft Authenticator, Authy, or 1Password
- More secure (no phone number required)
- Works offline
- Industry standard (RFC 6238)
SMS: Receive verification codes via text message
- Requires a phone number in E.164 format (e.g., +14165551234)
- Requires system phone number to be configured
Enabling MFA
- Navigate to Profile → Security Settings
- Click Enable MFA
- Choose your preferred method:
- Authenticator App: Scan QR code with your authenticator app
- SMS: Enter your phone number and verify with SMS code
- Enter the verification code to complete enrollment
- Save your backup codes - these are shown only once during enrollment
Backup Codes
- 10 backup codes are generated when you enable MFA
- Each code can only be used once
- Codes are hashed before storage (cannot be retrieved after enrollment)
- Download or copy codes during enrollment
- Regenerate codes if needed (invalidates old codes)
Using MFA During Login
When MFA is enabled:
- Enter your email and password
- If MFA is enabled, you'll be prompted for a verification code
- Enter the code from your authenticator app OR SMS code OR backup code
- Complete login after successful verification
Disabling MFA
To disable MFA:
- Navigate to Profile → Security Settings
- Enter your password to confirm
- Click Disable MFA
Note: Disabling MFA removes the extra security layer. Consider keeping MFA enabled for better account security.
Admin Recommendations
Administrators see a recommendation banner to enable MFA for enhanced security of platform data.
Password Reset
Forgot Password Flow
If you forget your password:
- Click "Forgot your password?" on the login screen
- Enter your email address
- Check your email for a password reset link
- Click the link (valid for 60 minutes)
- Enter a new password meeting the requirements above
- Log in with your new password
Password Reset Requirements
- Reset links expire after 60 minutes
- Each reset link can only be used once
- New password must meet the same requirements as regular password changes
- Password reset does not require MFA verification
Related Documentation
- Settings Navigation - UI navigation for profile page
- User Management - Admin-level user management
- Security Practices - Security docs overview
- Multi-Factor Authentication Guide - Detailed MFA documentation

