610 lines
15 KiB
Markdown
610 lines
15 KiB
Markdown
# 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.
|