inital
This commit is contained in:
609
AUTHENTIK_SETUP.md
Normal file
609
AUTHENTIK_SETUP.md
Normal file
@@ -0,0 +1,609 @@
|
||||
# Authentik Setup Guide
|
||||
|
||||
This guide walks you through configuring Authentik for OAuth 2.0 / OpenID Connect authentication with the Feuerwehr Dashboard.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Authentik Installation](#authentik-installation)
|
||||
- [Creating the Application](#creating-the-application)
|
||||
- [Provider Configuration](#provider-configuration)
|
||||
- [Redirect URIs Setup](#redirect-uris-setup)
|
||||
- [Scopes Configuration](#scopes-configuration)
|
||||
- [Getting Client Credentials](#getting-client-credentials)
|
||||
- [Testing Authentication](#testing-authentication)
|
||||
- [Common Issues](#common-issues)
|
||||
- [Advanced Configuration](#advanced-configuration)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before you begin, you need:
|
||||
|
||||
- An Authentik instance (self-hosted or cloud)
|
||||
- Admin access to Authentik
|
||||
- Your Feuerwehr Dashboard URL (e.g., `https://dashboard.yourdomain.com`)
|
||||
- Your backend API URL (e.g., `https://api.yourdomain.com`)
|
||||
|
||||
## Authentik Installation
|
||||
|
||||
If you don't have Authentik yet, here's a quick setup guide.
|
||||
|
||||
### Option 1: Docker Compose (Recommended)
|
||||
|
||||
Create `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres:16-alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- database:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
|
||||
POSTGRES_USER: ${PG_USER:-authentik}
|
||||
POSTGRES_DB: ${PG_DB:-authentik}
|
||||
env_file:
|
||||
- .env
|
||||
|
||||
redis:
|
||||
image: redis:alpine
|
||||
restart: unless-stopped
|
||||
|
||||
server:
|
||||
image: ghcr.io/goauthentik/server:2024.2
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
ports:
|
||||
- "${AUTHENTIK_PORT_HTTP:-9000}:9000"
|
||||
- "${AUTHENTIK_PORT_HTTPS:-9443}:9443"
|
||||
depends_on:
|
||||
- postgresql
|
||||
- redis
|
||||
|
||||
worker:
|
||||
image: ghcr.io/goauthentik/server:2024.2
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
|
||||
AUTHENTIK_POSTGRESQL__HOST: postgresql
|
||||
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
|
||||
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
|
||||
AUTHENTIK_REDIS__HOST: redis
|
||||
depends_on:
|
||||
- postgresql
|
||||
- redis
|
||||
|
||||
volumes:
|
||||
database:
|
||||
driver: local
|
||||
```
|
||||
|
||||
Create `.env`:
|
||||
|
||||
```bash
|
||||
PG_PASS=<secure-database-password>
|
||||
AUTHENTIK_SECRET_KEY=<generate-with-openssl-rand-base64-32>
|
||||
AUTHENTIK_PORT_HTTP=9000
|
||||
AUTHENTIK_PORT_HTTPS=9443
|
||||
```
|
||||
|
||||
Start Authentik:
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
Access Authentik at `http://localhost:9000` and complete the initial setup wizard.
|
||||
|
||||
### Option 2: Kubernetes
|
||||
|
||||
See [Authentik Kubernetes Documentation](https://goauthentik.io/docs/installation/kubernetes) for Helm charts.
|
||||
|
||||
## Creating the Application
|
||||
|
||||
### Step 1: Access Authentik Admin Interface
|
||||
|
||||
1. Log in to your Authentik instance
|
||||
2. Navigate to **Admin Interface** (gear icon in top right)
|
||||
|
||||
### Step 2: Create Provider
|
||||
|
||||
1. In the admin panel, go to **Applications** → **Providers**
|
||||
2. Click **Create** button
|
||||
3. Select **OAuth2/OpenID Provider**
|
||||
|
||||
Configure the provider:
|
||||
|
||||
```
|
||||
Name: Feuerwehr Dashboard Provider
|
||||
Authorization Flow: default-provider-authorization-implicit-consent
|
||||
Protocol Settings:
|
||||
```
|
||||
|
||||
**Client Type**:
|
||||
- Select: `Confidential`
|
||||
|
||||
**Client ID**:
|
||||
- Auto-generated (you'll copy this later)
|
||||
- Or set custom: `feuerwehr-dashboard`
|
||||
|
||||
**Client Secret**:
|
||||
- Auto-generated (you'll copy this later)
|
||||
|
||||
**Redirect URIs**:
|
||||
```
|
||||
http://localhost:5173/auth/callback
|
||||
http://localhost/auth/callback
|
||||
https://dashboard.yourdomain.com/auth/callback
|
||||
```
|
||||
|
||||
Add one URI per line. Include all environments (development, staging, production).
|
||||
|
||||
**Signing Key**:
|
||||
- Select: `authentik Self-signed Certificate` (default)
|
||||
|
||||
**Token Validity**:
|
||||
```
|
||||
Access token validity: 3600 (1 hour)
|
||||
Refresh token validity: 86400 (24 hours)
|
||||
```
|
||||
|
||||
Click **Create** to save the provider.
|
||||
|
||||
### Step 3: Create Application
|
||||
|
||||
1. Go to **Applications** → **Applications**
|
||||
2. Click **Create** button
|
||||
|
||||
Configure the application:
|
||||
|
||||
```
|
||||
Name: Feuerwehr Dashboard
|
||||
Slug: feuerwehr-dashboard
|
||||
Provider: Feuerwehr Dashboard Provider (select from dropdown)
|
||||
Launch URL: https://dashboard.yourdomain.com
|
||||
```
|
||||
|
||||
**UI Settings** (optional):
|
||||
```
|
||||
Icon: (upload fire department logo)
|
||||
Publisher: Your Fire Department Name
|
||||
Description: Fire department operations dashboard
|
||||
```
|
||||
|
||||
Click **Create** to save.
|
||||
|
||||
### Step 4: Configure Scopes
|
||||
|
||||
1. Go back to **Providers** → **Feuerwehr Dashboard Provider**
|
||||
2. Scroll to **Advanced protocol settings**
|
||||
3. Click **Edit** on **Scopes**
|
||||
|
||||
Ensure the following scopes are selected:
|
||||
|
||||
- [x] `openid` - Required for OpenID Connect
|
||||
- [x] `profile` - User profile information
|
||||
- [x] `email` - User email address
|
||||
|
||||
Optional scopes:
|
||||
- [ ] `offline_access` - For refresh tokens (recommended)
|
||||
|
||||
Click **Update**.
|
||||
|
||||
## Provider Configuration
|
||||
|
||||
### Step 5: Configure Advanced Settings
|
||||
|
||||
Edit your provider and configure these advanced settings:
|
||||
|
||||
**Token Settings**:
|
||||
```
|
||||
Include claims in ID token: Yes
|
||||
Access token validity: 3600 seconds (1 hour)
|
||||
Refresh token validity: 86400 seconds (24 hours)
|
||||
```
|
||||
|
||||
**Subject Mode**:
|
||||
```
|
||||
Based on the User's hashed ID
|
||||
```
|
||||
|
||||
This ensures consistent user IDs.
|
||||
|
||||
**Signing Algorithm**:
|
||||
```
|
||||
RS256 (default)
|
||||
```
|
||||
|
||||
### Step 6: Configure Claims
|
||||
|
||||
Ensure the following claims are mapped:
|
||||
|
||||
Standard claims (should be automatic):
|
||||
- `sub` - Subject (user ID)
|
||||
- `email` - User email
|
||||
- `name` - Full name
|
||||
- `preferred_username` - Username
|
||||
- `given_name` - First name
|
||||
- `family_name` - Last name
|
||||
|
||||
These are automatically included with the `profile` and `email` scopes.
|
||||
|
||||
## Redirect URIs Setup
|
||||
|
||||
Your redirect URIs must match exactly between Authentik and your application.
|
||||
|
||||
### Development Environment
|
||||
|
||||
```
|
||||
http://localhost:5173/auth/callback
|
||||
```
|
||||
|
||||
This is the Vite dev server URL.
|
||||
|
||||
### Production Environment
|
||||
|
||||
```
|
||||
https://dashboard.yourdomain.com/auth/callback
|
||||
```
|
||||
|
||||
Replace `yourdomain.com` with your actual domain.
|
||||
|
||||
### Docker Local Testing
|
||||
|
||||
```
|
||||
http://localhost/auth/callback
|
||||
http://localhost:80/auth/callback
|
||||
```
|
||||
|
||||
For testing the production Docker build locally.
|
||||
|
||||
### Important Notes
|
||||
|
||||
- URLs are **case-sensitive**
|
||||
- Must include protocol (`http://` or `https://`)
|
||||
- No trailing slashes
|
||||
- Port numbers must match if specified
|
||||
|
||||
## Scopes Configuration
|
||||
|
||||
### Required Scopes
|
||||
|
||||
Your application requires these scopes:
|
||||
|
||||
1. **openid** - Identifies this as an OpenID Connect request
|
||||
2. **profile** - Provides basic profile information
|
||||
3. **email** - Provides user email address
|
||||
|
||||
### Requesting Scopes
|
||||
|
||||
The dashboard automatically requests these scopes in the OAuth flow.
|
||||
|
||||
Backend configuration (`backend/src/config/oauth.ts`):
|
||||
```typescript
|
||||
scopes: ['openid', 'profile', 'email']
|
||||
```
|
||||
|
||||
Frontend login flow (`frontend/src/services/authService.ts`):
|
||||
```typescript
|
||||
const scopes = 'openid profile email';
|
||||
```
|
||||
|
||||
## Getting Client Credentials
|
||||
|
||||
### Step 7: Copy Client Credentials
|
||||
|
||||
1. Go to **Applications** → **Providers**
|
||||
2. Click on **Feuerwehr Dashboard Provider**
|
||||
3. Find the **Client ID** and **Client Secret**
|
||||
|
||||
**Client ID**: Will look like `abc123def456...` or custom `feuerwehr-dashboard`
|
||||
|
||||
**Client Secret**: Click the **eye icon** to reveal, then **copy button**
|
||||
|
||||
### Step 8: Get Provider URLs
|
||||
|
||||
1. In the provider details, find **OpenID Configuration URL**:
|
||||
```
|
||||
https://auth.yourdomain.com/application/o/feuerwehr-dashboard/.well-known/openid-configuration
|
||||
```
|
||||
|
||||
2. Important URLs from this configuration:
|
||||
- **Issuer**: `https://auth.yourdomain.com/application/o/feuerwehr-dashboard/`
|
||||
- **Authorization Endpoint**: Auto-discovered
|
||||
- **Token Endpoint**: Auto-discovered
|
||||
- **Userinfo Endpoint**: Auto-discovered
|
||||
|
||||
### Step 9: Configure Dashboard
|
||||
|
||||
Update your Feuerwehr Dashboard `.env` file:
|
||||
|
||||
```bash
|
||||
# Authentik OAuth Configuration
|
||||
AUTHENTIK_CLIENT_ID=<your-client-id>
|
||||
AUTHENTIK_CLIENT_SECRET=<your-client-secret>
|
||||
AUTHENTIK_ISSUER=https://auth.yourdomain.com/application/o/feuerwehr-dashboard/
|
||||
AUTHENTIK_REDIRECT_URI=https://dashboard.yourdomain.com/auth/callback
|
||||
|
||||
# For development, use:
|
||||
# AUTHENTIK_ISSUER=http://localhost:9000/application/o/feuerwehr-dashboard/
|
||||
# AUTHENTIK_REDIRECT_URI=http://localhost:5173/auth/callback
|
||||
```
|
||||
|
||||
**Important**: The `AUTHENTIK_ISSUER` must end with a trailing slash `/`.
|
||||
|
||||
## Testing Authentication
|
||||
|
||||
### Step 10: Test the Flow
|
||||
|
||||
1. **Start your application**:
|
||||
```bash
|
||||
# Development
|
||||
cd backend && npm run dev
|
||||
cd frontend && npm run dev
|
||||
|
||||
# Or production
|
||||
make prod
|
||||
```
|
||||
|
||||
2. **Open the dashboard** in your browser:
|
||||
```
|
||||
Development: http://localhost:5173
|
||||
Production: https://dashboard.yourdomain.com
|
||||
```
|
||||
|
||||
3. **Click "Login" button**
|
||||
|
||||
4. **You should be redirected to Authentik** login page
|
||||
|
||||
5. **Enter your Authentik credentials**
|
||||
|
||||
6. **Consent screen** (if enabled):
|
||||
- Review permissions
|
||||
- Click "Authorize"
|
||||
|
||||
7. **Redirect back to dashboard**:
|
||||
- Should show your dashboard
|
||||
- User profile should be loaded
|
||||
- Check browser console for any errors
|
||||
|
||||
### Step 11: Verify Token Exchange
|
||||
|
||||
Check backend logs:
|
||||
|
||||
```bash
|
||||
make logs-prod
|
||||
# or
|
||||
cd backend && npm run dev
|
||||
```
|
||||
|
||||
Look for:
|
||||
```
|
||||
[INFO] OAuth callback received
|
||||
[INFO] Token exchange successful
|
||||
[INFO] User authenticated: <username>
|
||||
```
|
||||
|
||||
### Step 12: Test User Profile
|
||||
|
||||
In the dashboard:
|
||||
1. Navigate to Profile page
|
||||
2. Verify your information is displayed:
|
||||
- Username
|
||||
- Email
|
||||
- Name
|
||||
|
||||
### Step 13: Test Logout
|
||||
|
||||
1. Click "Logout" button
|
||||
2. Should redirect to login page
|
||||
3. Verify session is cleared
|
||||
4. Attempting to access dashboard should redirect to login
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Issue 1: Redirect URI Mismatch
|
||||
|
||||
**Error**: `redirect_uri_mismatch` or `invalid_redirect_uri`
|
||||
|
||||
**Solution**:
|
||||
1. Check the redirect URI in Authentik **exactly** matches your app
|
||||
2. Include protocol (`http://` or `https://`)
|
||||
3. Check for trailing slashes
|
||||
4. Verify port numbers match
|
||||
|
||||
### Issue 2: Invalid Client Credentials
|
||||
|
||||
**Error**: `invalid_client`
|
||||
|
||||
**Solution**:
|
||||
1. Verify `AUTHENTIK_CLIENT_ID` is correct
|
||||
2. Verify `AUTHENTIK_CLIENT_SECRET` is correct (no extra spaces)
|
||||
3. Check if client secret was regenerated in Authentik
|
||||
4. Ensure client type is "Confidential"
|
||||
|
||||
### Issue 3: CORS Errors
|
||||
|
||||
**Error**: CORS policy blocked request
|
||||
|
||||
**Solution**:
|
||||
1. Ensure `CORS_ORIGIN` in backend `.env` matches frontend URL
|
||||
2. For development: `CORS_ORIGIN=http://localhost:5173`
|
||||
3. For production: `CORS_ORIGIN=https://dashboard.yourdomain.com`
|
||||
4. Restart backend after changing CORS settings
|
||||
|
||||
### Issue 4: Token Validation Failed
|
||||
|
||||
**Error**: `Invalid token` or `Token signature verification failed`
|
||||
|
||||
**Solution**:
|
||||
1. Verify `AUTHENTIK_ISSUER` URL is correct
|
||||
2. Ensure issuer URL ends with `/`
|
||||
3. Check Authentik is accessible from backend server
|
||||
4. Verify JWT signing key hasn't changed
|
||||
|
||||
### Issue 5: Scope Errors
|
||||
|
||||
**Error**: `invalid_scope` or missing user data
|
||||
|
||||
**Solution**:
|
||||
1. Ensure `openid`, `profile`, `email` scopes are configured in Authentik
|
||||
2. Check scopes are requested in login flow
|
||||
3. Verify user has consented to scopes
|
||||
|
||||
### Issue 6: User Not Created in Database
|
||||
|
||||
**Error**: Authentication works but user not found
|
||||
|
||||
**Solution**:
|
||||
1. Check backend logs for database errors
|
||||
2. Verify database migrations ran
|
||||
3. Check `users` table exists:
|
||||
```bash
|
||||
docker exec -it feuerwehr_db_prod psql -U prod_user -d feuerwehr_prod -c "\dt"
|
||||
```
|
||||
4. Manually run migrations if needed
|
||||
|
||||
### Issue 7: Token Refresh Fails
|
||||
|
||||
**Error**: Refresh token invalid or expired
|
||||
|
||||
**Solution**:
|
||||
1. Check token validity settings in Authentik
|
||||
2. Increase refresh token validity (e.g., 86400 seconds)
|
||||
3. Verify `offline_access` scope is included
|
||||
4. Clear browser cookies and re-authenticate
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Customizing Login Flow
|
||||
|
||||
Create custom authentication flow in Authentik:
|
||||
|
||||
1. Go to **Flows & Stages** → **Flows**
|
||||
2. Duplicate `default-provider-authorization-implicit-consent`
|
||||
3. Add custom stages (MFA, email verification, etc.)
|
||||
4. Update provider to use custom flow
|
||||
|
||||
### Adding Multi-Factor Authentication
|
||||
|
||||
1. Go to **Flows & Stages** → **Stages**
|
||||
2. Create authenticator validation stage
|
||||
3. Add to your authorization flow
|
||||
4. Users will be prompted for MFA on login
|
||||
|
||||
### Branding
|
||||
|
||||
Customize Authentik appearance:
|
||||
|
||||
1. Go to **System** → **Branding**
|
||||
2. Upload logo
|
||||
3. Set primary color to match fire department branding
|
||||
4. Configure footer links
|
||||
|
||||
### User Management
|
||||
|
||||
Add users to Authentik:
|
||||
|
||||
1. Go to **Directory** → **Users**
|
||||
2. Click **Create**
|
||||
3. Fill in user details
|
||||
4. Set password
|
||||
5. Assign to groups (if using RBAC)
|
||||
|
||||
### Group-Based Access Control
|
||||
|
||||
Implement role-based access:
|
||||
|
||||
1. Create groups in **Directory** → **Groups**
|
||||
2. Assign users to groups
|
||||
3. In your app, read `groups` claim from token
|
||||
4. Implement authorization based on groups
|
||||
|
||||
Example groups:
|
||||
- `feuerwehr-admin` - Full access
|
||||
- `feuerwehr-operator` - Standard access
|
||||
- `feuerwehr-viewer` - Read-only access
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
After configuration, verify:
|
||||
|
||||
- [ ] Login redirects to Authentik
|
||||
- [ ] Successful authentication redirects back
|
||||
- [ ] User profile loads correctly
|
||||
- [ ] Tokens are stored securely
|
||||
- [ ] Logout clears session
|
||||
- [ ] Token refresh works
|
||||
- [ ] Protected routes require authentication
|
||||
- [ ] Invalid tokens are rejected
|
||||
- [ ] CORS is properly configured
|
||||
- [ ] Works on all browsers (Chrome, Firefox, Safari)
|
||||
|
||||
## Configuration Reference
|
||||
|
||||
### Minimum Required Settings
|
||||
|
||||
**Authentik Provider**:
|
||||
```
|
||||
Client Type: Confidential
|
||||
Client ID: <auto-generated>
|
||||
Client Secret: <auto-generated>
|
||||
Redirect URIs: https://dashboard.yourdomain.com/auth/callback
|
||||
Scopes: openid, profile, email
|
||||
Access Token Validity: 3600
|
||||
Refresh Token Validity: 86400
|
||||
```
|
||||
|
||||
**Dashboard .env**:
|
||||
```bash
|
||||
AUTHENTIK_CLIENT_ID=<from-authentik>
|
||||
AUTHENTIK_CLIENT_SECRET=<from-authentik>
|
||||
AUTHENTIK_ISSUER=https://auth.yourdomain.com/application/o/feuerwehr-dashboard/
|
||||
AUTHENTIK_REDIRECT_URI=https://dashboard.yourdomain.com/auth/callback
|
||||
```
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Use HTTPS in production** - Never use HTTP for OAuth flows
|
||||
2. **Keep secrets secret** - Never commit credentials to Git
|
||||
3. **Rotate secrets regularly** - Change client secrets periodically
|
||||
4. **Use strong passwords** - For Authentik admin and users
|
||||
5. **Enable MFA** - Require multi-factor authentication for admin users
|
||||
6. **Monitor logs** - Watch for failed login attempts
|
||||
7. **Limit token validity** - Use short-lived access tokens
|
||||
8. **Validate redirect URIs** - Only allow known URLs
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Authentik Documentation](https://goauthentik.io/docs/)
|
||||
- [OAuth 2.0 Specification](https://oauth.net/2/)
|
||||
- [OpenID Connect](https://openid.net/connect/)
|
||||
- [Authentik Community Forum](https://github.com/goauthentik/authentik/discussions)
|
||||
|
||||
## Support
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. Check Authentik logs: `docker-compose logs -f server`
|
||||
2. Check dashboard backend logs: `make logs-prod`
|
||||
3. Review browser console for errors
|
||||
4. Consult [Common Issues](#common-issues) section
|
||||
5. Search Authentik GitHub issues
|
||||
6. Create detailed issue report
|
||||
|
||||
---
|
||||
|
||||
**Next Steps**: After completing Authentik setup, proceed to [DEPLOYMENT.md](DEPLOYMENT.md) for production deployment.
|
||||
Reference in New Issue
Block a user