User Management API¶
REST API endpoints for managing users in deployed environments.
Overview¶
User management is handled via REST API endpoints that work with both local dev and deployed Lambda. This ensures consistent behavior and eliminates config file ambiguity.
Architecture¶
Auth Provider System¶
The backend uses a pluggable authentication provider system that ensures the Lambda always uses the correct Cognito pool ID:
Configuration Priority:
Environment variables (set by CloudFormation at deploy time) - PRIMARY TRUTH
Config file (baked into Lambda at build time) - FALLBACK
# backend/rawscribe/utils/auth_providers/cognito_provider.py
def get_user_pool_id(self) -> Optional[str]:
# CloudFormation sets this at deploy time (always fresh)
return os.environ.get('COGNITO_USER_POOL_ID') or \
self._cognito_config.get('userPoolId')
This architecture solves the “stale config” problem where Lambda had old pool IDs baked in after sync-configs updated local files. Environment variables from CloudFormation are the authoritative source.
Runtime Config Endpoint¶
Public endpoint that returns the actual auth configuration the Lambda is using:
GET /api/config/runtime
Response example:
{
"auth": {
"provider": "cognito",
"config": {
"userPoolId": "us-east-1_QkkFFWXUA",
"clientId": "1ue2h7glihso8gpq4pm4s0rs42",
"region": "us-east-1",
"source": "environment"
}
}
}
The source field indicates whether config came from environment variables (environment) or config file (config_file).
The frontend automatically queries this endpoint to get fresh auth configuration, eliminating mismatches between static config and deployed infrastructure.
Authentication¶
Getting JWT Tokens¶
User authentication is handled via AWS Cognito SDK (not backend API endpoint).
Makefile Usage:
# Get token via Cognito SDK
make get-rs-token ENV=stage ORG=myorg \
USER_NAME=user@example.com \
PASSWORD=SecurePass123!
Direct AWS CLI:
aws cognito-idp admin-initiate-auth \
--region us-east-1 \
--user-pool-id <pool-id> \
--client-id <client-id> \
--auth-flow ADMIN_NO_SRP_AUTH \
--auth-parameters USERNAME=user@example.com,PASSWORD=Pass123! \
--query 'AuthenticationResult.IdToken' \
--output text
Frontend Login:
Uses Cognito SDK directly (amplify or aws-sdk)
See
frontend/src/shared/lib/auth.tsxNo backend endpoint needed
Supported Deployments¶
User Management API works with:
✅ AWS deployments with Cognito (
provider: cognito)❌ On-prem deployments with JWT (
provider: jwt)
For on-prem deployments: Edit users in infra/.config/lambda/<env>-<org>.json:
{
"lambda": {
"auth": {
"users": [
{
"id": "admin_user",
"email": "admin@example.com",
"username": "admin",
"groups": ["ADMINS"],
"permissions": ["*"]
}
]
}
}
}
Test User Management¶
Create Test Users¶
Creates all default test users (admin, researcher, clinician).
Endpoint: POST /api/v1/user-management/test-users
Auth: Requires manage:users permission (ADMINS or LAB_MANAGERS)
Response:
[
{
"username": "testadmin@example.com",
"group": "ADMINS",
"status": "CONFIRMED",
"is_test_user": true
},
{
"username": "testresearcher@example.com",
"group": "RESEARCHERS",
"status": "CONFIRMED",
"is_test_user": true
},
{
"username": "testclinician@example.com",
"group": "CLINICIANS",
"status": "CONFIRMED",
"is_test_user": true
}
]
Makefile Usage:
make rs-create-test-users ENV=stage ORG=myorg
What it does:
Creates admin user via Cognito SDK (if doesn’t exist)
Authenticates as admin
Creates remaining test users via API
Displays credentials
List Test Users¶
Lists all test users with their credentials.
Endpoint: GET /api/v1/user-management/test-users
Auth: Requires manage:users permission
Response:
[
{
"username": "testadmin@example.com",
"password": "TestAdmin123!",
"group": "ADMINS",
"actual_groups": ["ADMINS"],
"status": "CONFIRMED",
"enabled": true
},
...
]
Makefile Usage:
make rs-list-test-users ENV=stage ORG=myorg
# Output:
# testadmin@example.com / TestAdmin123! [ADMINS] - CONFIRMED
# testresearcher@example.com / TestResearch123! [RESEARCHERS] - CONFIRMED
# testclinician@example.com / TestClinic123! [CLINICIANS] - CONFIRMED
Remove Test Users¶
Removes all test users from Cognito pool.
Endpoint: DELETE /api/v1/user-management/test-users
Auth: Requires manage:users permission
Response:
{
"removed": [
"testadmin@example.com",
"testresearcher@example.com",
"testclinician@example.com"
],
"count": 3
}
Makefile Usage:
make rs-remove-test-users ENV=stage ORG=myorg
Secure Production¶
Removes all test users and resets admin password to random value.
Endpoint: POST /api/v1/user-management/secure-production
Auth: Requires manage:users permission
Environment: Only works in stage or prod
Response:
{
"test_users_removed": [
"testadmin@example.com",
"testresearcher@example.com",
"testclinician@example.com"
],
"admin_passwords_reset": {
"admin@example.com": "xK9#mP2$vL8@wQ5!nR7&tY3^"
},
"message": "⚠️ SAVE THE ADMIN PASSWORDS ABOVE - They cannot be recovered!"
}
Makefile Usage:
make rs-secure-prod ENV=prod ORG=myorg
# Prompts for confirmation, then outputs:
# 🔒 IMPORTANT: Save the new admin passwords below!
# ================================================
# admin@example.com: xK9#mP2$vL8@wQ5!nR7&tY3^
# ================================================
# ⚠️ SAVE THESE PASSWORDS - They cannot be recovered!
Test User Credentials¶
Default test users created by the system:
Username |
Password |
Group |
Permissions |
|---|---|---|---|
testadmin@example.com |
TestAdmin123! |
ADMINS |
All ( |
testresearcher@example.com |
TestResearch123! |
RESEARCHERS |
submit:SOP*, view:own, view:group, draft:* |
testclinician@example.com |
TestClinic123! |
CLINICIANS |
submit:SOP*, view:own, draft:* |
Workflow¶
Fresh Deployment¶
# Deploy creates empty Cognito pool
ENABLE_AUTH=true CREATE_BUCKETS=true ORG=testorg ENV=stage make rs-deploy
# Auto-creates test users (creates admin first, then others via API)
# Displays credentials at end
Testing with Test Users¶
# List all test users
make rs-list-test-users ENV=stage ORG=testorg
# Login as admin
curl -X POST "https://api.example.com/api/auth/login" \
-H "Content-Type: application/json" \
-d '{"username":"testadmin@example.com","password":"TestAdmin123!"}' | jq
# Use in application
# Frontend: Use credentials to login
# Backend tests: Use credentials to authenticate
Cleanup¶
# Remove test users when done
make rs-remove-test-users ENV=stage ORG=testorg
Before Production¶
# Secure production environment
make rs-secure-prod ENV=prod ORG=myorg
# Saves new admin password securely
# Removes all test users
Security Notes¶
Test User Passwords¶
Obvious/simple passwords (TestAdmin123!)
Never use in production
Always run
rs-secure-prodbefore real production use
Permission Requirements¶
All endpoints require
manage:userspermissionOnly ADMINS and LAB_MANAGERS can manage users
Uses permission check, not hardcoded group check (flexible)
Admin Password Rotation¶
rs-secure-prodgenerates cryptographically secure passwords16-20 characters: uppercase, lowercase, digits, special chars
Meets Cognito password policy
Cannot be recovered - save immediately!