Local Authentication
Local authentication provides email and password-based user management without external OAuth dependencies. This is production-ready authentication with full control over user accounts and passwords.
For organizations using Google Workspace or other identity providers, consider Google OAuth or OIDC.
How It Works
┌──────────────┐ ┌─────────────────┐ ┌────────────┐
│ Browser │────▶│ Stategraph │────▶│ PostgreSQL │
│ │ │ Server │ │ │
└──────────────┘ └─────────────────┘ └────────────┘
│ │
│ 1. Enter email │
│ & password │
│ │
│ 2. POST /login │
│ │
│◀─── Session Cookie ─│
│ │
│ 3. Authenticated │
▼ requests │
- User enters email and password
- Stategraph validates credentials and creates a session
- Session token is stored as an HTTP-only cookie
- Subsequent requests are authenticated via the session cookie
Initial Setup
When you first deploy Stategraph with local authentication (the default), you'll see a setup wizard that guides you through creating the first admin account.
First-Time Setup Wizard
- Navigate to your Stategraph URL (e.g., http://localhost:8080)
- You'll see the setup form prompting you to create an admin account
- Fill in the required fields:
- Email: Your email address (used for login)
- Password: Minimum 8 characters, maximum 128 characters
- Name: Your display name
-
Organization: Your organization name
-
Click Create Admin Account
- You'll be automatically logged in and redirected to the Stategraph UI
The first user created is automatically granted admin privileges.
Example Setup
# Deploy Stategraph (Docker Compose example)
docker compose up -d
# Open browser to http://localhost:8080
# Fill in the setup form:
Email: admin@example.com
Password: your-secure-password
Name: Admin User
Organization: My Organization
User Management
Creating Users (Admin Only)
Admins can create additional users through the Settings page:
- Log in as an admin user
- Navigate to Settings > Users
- Click Create User
- Fill in user details:
- Name: Display name
- Email: Email address (used for login)
- Password: Minimum 8 characters
-
Is Admin: Toggle to grant admin privileges
-
Click Create to create the user
User Roles
| Role | Capabilities |
|---|---|
| Admin | Full access: create/edit/delete users, manage all states and tenants, view all settings |
| Regular User | Access assigned tenants, create API keys, manage own states |
Changing Passwords
Users changing their own password:
- Navigate to Settings > Account
- Click Change Password
- Enter current password for verification
- Enter new password (8-128 characters)
- Confirm new password
Admins changing any user's password:
- Navigate to Settings > Users
- Click on the user you want to modify
- Click Change Password
- Enter new password (no verification required)
- Confirm new password
Managing Admin Access
Admins can grant or remove admin privileges from other users:
- Navigate to Settings > Users
- Click on the user you want to modify
- Toggle the Is Admin switch
- Confirm the change
Important: You cannot remove admin privileges from yourself if you're the last admin. This prevents accidental lockout.
Deleting Users
Admins can delete users:
- Navigate to Settings > Users
- Click on the user you want to delete
- Click Delete User
- Type the user's email to confirm deletion
- Click Delete to confirm
Note: Deleted users are soft-deleted (marked as deleted in the database but not removed). Their API keys are immediately invalidated.
Service Accounts (API Users)
Service accounts provide programmatic access for CI/CD pipelines and automation without interactive login.
Creating Service Accounts
Service accounts are created similarly to regular users but with type api:
- Navigate to Settings > Service Accounts
- Enter a name for the service account (e.g., "github-actions", "ci-production")
- Click Create
- Copy the generated API token (shown only once)
Service accounts:
- Cannot log in interactively (no password)
- Receive an API token on creation
- Are tied to a specific tenant
- Provide clear audit trails in transaction logs
Via API:
curl -X POST http://localhost:8080/api/v1/api-users \
-H "Content-Type: application/json" \
-H "Cookie: session=<your-session-cookie>" \
-d '{
"name": "ci-production",
"tenant_id": "<tenant-uuid>"
}'
Response:
{
"user_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
Authentication Flow
Login Flow
- User navigates to Stategraph
- If not authenticated, redirected to login page
- User enters email and password
- POST request to
/api/v1/login/password - Server validates credentials
- Session token created and stored as HTTP-only cookie
- User redirected to Stategraph UI
Login Endpoint
POST /api/v1/login/password
Content-Type: application/json
{
"email": "user@example.com",
"password": "your-password"
}
Response:
{
"session_token": "eyJhbGciOiJIUzI1NiIs...",
"success": true
}
The session_token can be used for Bearer authentication.
Logout
GET /api/v1/logout
Clears the session cookie and logs the user out.
API Endpoints
Authentication Endpoints
Get Login Options
GET /api/v1/login/options
Returns available authentication methods (local, OAuth, etc.).
Response:
{
"options": []
}
When OAuth is configured, the options array contains available providers.
Login with Password
POST /api/v1/login/password
Content-Type: application/json
{
"email": "user@example.com",
"password": "your-password"
}
Check Setup Status
GET /api/v1/setup/status
Returns whether initial setup is needed.
Response:
{
"needs_setup": false
}
Create First Admin
POST /api/v1/setup/admin
Content-Type: application/json
{
"email": "admin@example.com",
"password": "secure-password",
"name": "Admin User",
"organization": "My Org"
}
Only works when no users exist in the system.
Logout
GET /api/v1/logout
User Management Endpoints (Admin Only)
List Users
GET /api/v1/users?type=user&limit=25&offset=0
Query parameters:
- type: Filter by user type (user or api)
- limit: Maximum results (default: 25)
- offset: Pagination offset
- search: Search by name or email
Response:
{
"users": [
{
"id": "f30ed1f9-be44-46a3-9050-03e9561e94f0",
"name": "John Doe",
"email": "john@example.com",
"is_admin": false,
"type": "user",
"created_at": "2024-01-15T10:30:00Z"
}
],
"total_count": 10,
"limit": 25,
"has_more": false
}
Get User Details
GET /api/v1/users/detail?user_id=<user-id>
Response:
{
"id": "f30ed1f9-be44-46a3-9050-03e9561e94f0",
"name": "John Doe",
"email": "john@example.com",
"is_admin": false,
"type": "user",
"created_at": "2024-01-15T10:30:00Z"
}
Note: The last_login field is included when the user has logged in at least once.
Create User
POST /api/v1/users
Content-Type: application/json
{
"name": "Jane Doe",
"email": "jane@example.com",
"password": "secure-password",
"is_admin": false
}
Response:
{
"id": "a1b2c3d4-5678-90ab-cdef-1234567890ab",
"name": "Jane Doe",
"email": "jane@example.com",
"is_admin": false
}
Update User
PUT /api/v1/users/update?user_id=<user-id>
Content-Type: application/json
{
"name": "Jane Smith",
"email": "jane.smith@example.com"
}
Delete User
DELETE /api/v1/users/delete?user_id=<user-id>
Response: 204 No Content
Change User Password
POST /api/v1/users/change-password?user_id=<user-id>
Content-Type: application/json
{
"new_password": "new-secure-password",
"current_password": "old-password" # Only required when changing own password
}
Toggle Admin Status
POST /api/v1/users/toggle-admin?user_id=<user-id>
Content-Type: application/json
{
"is_admin": true
}
Service Account Endpoints
Create Service Account
POST /api/v1/api-users
Content-Type: application/json
{
"name": "ci-production",
"tenant_id": "<tenant-uuid>"
}
Response:
{
"user_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"token": "eyJhbGciOiJIUzI1NiIs..."
}
Important: Save the token immediately - it's only shown once.
Creating API Keys
Once authenticated, you can create API keys for CLI and Terraform access:
- Log in to Stategraph
- Navigate to Settings > API Keys
- Click Create API Key
- Optionally provide a name/description
- Copy the generated token
Use the API key with the CLI:
export STATEGRAPH_API_KEY="<your-api-key>"
stategraph states list --tenant <tenant-id>
Or with Terraform:
terraform {
backend "http" {
address = "http://localhost:8080/api/v1/states/backend/<state-id>"
username = "session"
password = "<your-api-key>"
}
}
Security Considerations
Password Requirements
- Minimum length: 8 characters
- Maximum length: 128 characters
- No complexity requirements enforced (consider using strong passwords)
Session Security
- Sessions are stored as HTTP-only cookies (not accessible via JavaScript)
- Session tokens are JWT tokens signed with a secret key
- Use HTTPS in production to protect credentials and session tokens in transit
Best Practices
- Use HTTPS: Always deploy with HTTPS in production
- Strong passwords: Enforce strong password policies at the organizational level
- Regular audits: Review user list and admin access regularly
- Service accounts: Use service accounts for CI/CD instead of personal credentials
- Principle of least privilege: Only grant admin access when necessary
- Monitor access: Review transaction logs for unusual activity
Admin Responsibilities
Admins can:
- Create and delete any user
- Change any user's password without verification
- Grant and revoke admin privileges
- View all states and tenants
- Cannot accidentally remove the last admin
Transitioning to OAuth
When you're ready to switch to OAuth:
- Configure OAuth environment variables (Google OAuth or OIDC)
- Restart Stategraph with OAuth configuration
- Existing local users remain in the database
- New OAuth users are created on first login
- Existing API keys continue to work
Note: Once OAuth is enabled, the local authentication login page is replaced with OAuth login. Existing local users cannot log in via password unless OAuth is disabled.
Next Steps
- Configure Google OAuth for SSO
- Configure OIDC for other providers
- Create your first Terraform state
- Set up CI/CD with service accounts