Overview
OmniEHR uses JWT (JSON Web Token) based authentication. After successful login, clients receive a token that must be included in theAuthorization header for all protected endpoints.
Authentication Flow
- Login: Send credentials to
/api/auth/login - Receive Token: Get JWT token and user profile
- Use Token: Include token in
Authorizationheader for subsequent requests - Token Expiry: Tokens expire based on
JWT_EXPIRES_INconfiguration
Base URL
Rate Limiting
Authentication endpoints are rate-limited to 100 requests per 15 minutes per IP address.Login
Authenticate with email and password to receive a JWT token.Password validation is performed server-side. Only active users can log in.
Endpoint
Request Body
User email address (case-insensitive, trimmed)
User password (minimum 1 character for login validation)
Example Request
Success Response (200)
JWT access token for authenticated requests
User ID (MongoDB ObjectId as string)
User email address
User’s full name
User’s organization
User role:
admin, practitioner, or auditorAccount status
Timestamp of last login (ISO 8601 format)
Account creation timestamp
Error Responses
HTTP status code
Error description
401 Unauthorized
Invalid credentials or inactive account:400 Bad Request
Validation error:429 Too Many Requests
Rate limit exceeded:Implementation Details
From/server/src/routes/authRoutes.js:23-51:
- Email Validation: Email is trimmed and converted to lowercase
- User Lookup: Searches for user by email in database
- Account Status Check: Verifies user account is active
- Password Verification: Uses bcrypt to compare passwords
- Login Timestamp Update: Updates
lastLoginAtfield - Token Generation: Creates JWT with user claims
JWT Token Payload
The token contains the following claims (from/server/src/routes/authRoutes.js:42-47):
Subject - User ID
User email address
User role for authorization
User’s full name
Issued at timestamp (Unix epoch)
Expiration timestamp (Unix epoch)
Get Current User Profile
Retrieve the authenticated user’s profile information.Endpoint
Authentication
Required: JWT Bearer tokenExample Request
Success Response (200)
Error Responses
401 Unauthorized
Missing token:404 Not Found
User not found in database:Using Authentication Tokens
Authorization Header Format
All protected endpoints require the JWT token in theAuthorization header:
Implementation
Theauthenticate middleware (from /server/src/middleware/auth.js:4-20):
- Extracts the
Authorizationheader - Verifies it starts with “Bearer ”
- Extracts the token (everything after “Bearer ”)
- Verifies the token signature using
JWT_SECRET - Decodes the token payload
- Attaches payload to
req.userfor downstream handlers
Token Verification
Token verification usesjsonwebtoken library (from /server/src/utils/jwt.js:8-10):
- Token signature
- Token expiration
- Token structure
Example: Making Authenticated Requests
Role-Based Authorization
Beyond authentication, many endpoints require specific roles.Available Roles
Full system access - user management, all FHIR operations
Healthcare provider - FHIR read/write operations, limited to own data
Read-only access - FHIR resources and audit logs
Authorization Middleware
Theauthorize middleware (from /server/src/middleware/auth.js:22-32) checks if the authenticated user has one of the required roles:
Role Requirements by Endpoint Group
FHIR Resources
From/server/src/routes/fhirRoutes.js:53-55:
- Read Operations (GET):
admin,practitioner,auditor - Write Operations (POST, PUT):
admin,practitioner - Patient Write Operations:
adminonly
Admin Endpoints
- User Management:
adminonly - Practitioner Directory:
admin,practitioner(self-view only) - Audit Logs:
admin,auditor
Authorization Error
If the user lacks required permissions:Token Expiration
Tokens expire based on theJWT_EXPIRES_IN environment variable.
Expiration Format Examples
"24h"- 24 hours"7d"- 7 days"60m"- 60 minutes"3600"- 3600 seconds
Handling Expired Tokens
When a token expires, the API returns:- Detect 401 responses
- Prompt user to log in again
- Obtain a new token
- Retry the original request
Token Refresh Strategy
Best practices:- Set
JWT_EXPIRES_INto a reasonable duration (e.g., “24h” for web apps) - Implement client-side token expiration checks
- Prompt for re-authentication before token expires
- Clear stored tokens on logout
Security Best Practices
Token Storage
Recommended approaches:- HttpOnly Cookies: Most secure for browser apps
- Memory Only: Store in JavaScript variable (lost on refresh)
- Secure Storage: Mobile apps should use platform-specific secure storage
Password Requirements
When registering users via/api/admin/users, passwords must meet these requirements (from /server/src/services/validation.js:9-16):
- Minimum 12 characters
- Maximum 128 characters
- At least one uppercase letter (A-Z)
- At least one lowercase letter (a-z)
- At least one digit (0-9)
- At least one special character
HTTPS Required
Token Signing
Tokens are signed using theJWT_SECRET environment variable with HMAC-SHA256 algorithm (from /server/src/utils/jwt.js:4-6).
Important:
- Use a strong, random secret (minimum 32 characters)
- Never commit secrets to version control
- Rotate secrets periodically
- Use different secrets for different environments
Testing Authentication
Health Check (No Auth Required)
Complete Authentication Flow
Next Steps
FHIR Resources
Learn about FHIR resource endpoints
Admin API
User management and registration
Error Handling
Handle API errors gracefully
Rate Limits
Understand rate limiting policies