kaboot/docs/AUTHENTIK_SETUP.md

475 lines
13 KiB
Markdown

# Authentik Setup Guide for Kaboot
This guide walks through configuring Authentik as the OAuth2/OIDC identity provider for Kaboot.
## Quick Start (Automated Setup)
The recommended approach uses Authentik Blueprints for automatic configuration:
```bash
# 1. Run setup script (generates all secrets including admin password)
./scripts/setup.sh
# 2. Start the stack
docker compose up -d
# 3. Wait for Authentik to initialize (~30 seconds)
docker compose logs -f authentik-server | grep -i blueprint
# 4. Set password for test user
docker compose exec authentik-server ak set_password kaboottest
# Enter: kaboottest (or your preferred password)
# 5. (Optional) Create app password for service account via UI
# See "Step 7: Create a Service Account" below
```
The blueprint automatically creates:
- Kaboot OAuth2/OIDC Provider (public client, client_id: `kaboot-spa`)
- Kaboot Application with proper redirect URIs
- `kaboot-users` Group
- Enrollment flow with sign-up capability
- Password complexity policy
- Test user (`kaboottest`)
- Service account (`kaboot-test-service`)
Your admin credentials are printed by `setup.sh` - save them!
---
## Manual Setup (Alternative)
If you prefer manual configuration or need to customize the setup, follow the steps below.
## Prerequisites
- Docker and Docker Compose installed
- Kaboot stack running (`docker compose up -d`)
- Access to `http://localhost:9000`
## Step 1: Initial Authentik Setup
1. Navigate to `http://localhost:9000/if/flow/initial-setup/`
- **Important**: Include the trailing slash `/`
2. Create the admin account:
- Email: Your email address
- Password: Choose a strong password
3. Log in with the credentials you just created
## Step 2: Create the Kaboot Application
1. In the Authentik admin interface, go to **Applications** > **Applications**
2. Click **Create with provider**
3. **Application Settings**:
| Field | Value |
|-------|-------|
| Name | `Kaboot` |
| Slug | `kaboot` |
| Launch URL | `http://localhost:5173` |
4. Click **Next**
## Step 3: Configure OAuth2/OIDC Provider
1. Select **OAuth2/OIDC** as the Provider Type
2. Click **Next**
3. **Provider Configuration**:
| Field | Value |
|-------|-------|
| Name | `Kaboot OAuth2` |
| Authorization flow | `default-provider-authorization-implicit-consent` |
| Client type | `Public` |
| Client ID | `kaboot-spa` |
4. **Redirect URIs** (one per line):
```
http://localhost:5173/callback
http://localhost:5173/silent-renew.html
http://localhost:5173
```
5. **Advanced Settings**:
| Field | Value |
|-------|-------|
| Subject mode | `Based on the User's hashed ID` |
| Include claims in id_token | `Yes` |
| Issuer mode | `Each provider has a different issuer` |
6. **Scopes** - Ensure these are selected:
- `openid`
- `profile`
- `email`
- `offline_access` (for refresh tokens)
7. Click **Submit**
## Step 4: Enable User Registration (Sign Up)
By default, Authentik only shows a login form. To allow users to sign up, you need to create an enrollment flow and link it.
### Step 4.1: Create the Enrollment Prompt Stage
1. Go to **Flows and Stages** > **Stages**
2. Click **Create**
3. Select **Prompt Stage** and click **Next**
4. Configure:
| Field | Value |
|-------|-------|
| Name | `enrollment-prompt` |
5. In the **Fields** section, move these to the **Selected** side:
- `default-source-enrollment-field-username` (username)
- `default-user-settings-field-email` (email)
- `default-password-change-field-password` (password)
- `default-password-change-field-password-repeat` (password_repeat)
6. (Optional) In **Validation policies**, select `password-complexity` if you created it in Step 4.2
7. Click **Finish**
### Step 4.2: (Optional) Create Password Complexity Policy
1. Go to **Customisation** > **Policies**
2. Click **Create** and select **Password Policy**
3. Configure:
| Field | Value |
|-------|-------|
| Name | `password-complexity` |
| Password field | `password` |
| Minimum length | `8` |
| Amount of uppercase characters | `1` |
| Amount of lowercase characters | `1` |
| Amount of digits | `1` |
4. Click **Finish**
You'll add this to the enrollment prompt stage later.
### Step 4.3: Create a Group for Kaboot Users
1. Go to **Directory** > **Groups**
2. Click **Create**
3. Configure:
| Field | Value |
|-------|-------|
| Name | `kaboot-users` |
4. Click **Create**
### Step 4.4: Create the User Write Stage
1. Go to **Flows and Stages** > **Stages**
2. Click **Create**
3. Select **User Write Stage** and click **Next**
4. Configure:
| Field | Value |
|-------|-------|
| Name | `enrollment-user-write` |
| User creation mode | `Create users when required` |
| Create users as inactive | Unchecked |
| Group | `kaboot-users` |
5. Click **Finish**
### Step 4.5: Create the User Login Stage
1. Go to **Flows and Stages** > **Stages**
2. Click **Create**
3. Select **User Login Stage** and click **Next**
4. Configure:
| Field | Value |
|-------|-------|
| Name | `enrollment-user-login` |
| Session duration | `hours=24` |
| Stay signed in offset | `days=30` |
| Network binding | `No binding` |
| GeoIP binding | `No binding` |
5. Click **Finish**
### Step 4.6: Create the Enrollment Flow
1. Go to **Flows and Stages** > **Flows**
2. Click **Create**
3. Configure:
| Field | Value |
|-------|-------|
| Name | `Enrollment Flow` |
| Title | `Sign Up` |
| Slug | `enrollment-flow` |
| Designation | `Enrollment` |
| Authentication | `No requirement` |
4. Click **Create**
5. Click on the newly created `enrollment-flow`
6. Go to the **Stage Bindings** tab
7. Click **Bind existing stage** and add stages in this order:
| Stage | Order |
|-------|-------|
| `enrollment-prompt` | 10 |
| `enrollment-user-write` | 20 |
| `enrollment-user-login` | 30 |
### Step 4.7: Bind the Group to the Kaboot Application
1. Go to **Applications** > **Applications** > **Kaboot**
2. Go to the **Policy / Group / User Bindings** tab
3. Click **Bind existing group**
4. Select `kaboot-users`
5. Click **Bind**
Now users in the `kaboot-users` group (which includes all users who sign up) will have access to Kaboot.
### Step 4.8: Link Enrollment Flow to Login
1. Go to **Flows and Stages** > **Stages**
2. Find and click on `default-authentication-identification`
3. Scroll down to **Flow settings**
4. In the **Enrollment flow** dropdown, select `enrollment-flow`
5. Click **Update**
Now when users visit the login page, they'll see a "Need an account? Sign up." link.
### Optional: Add Password Recovery
1. In **Flows and Stages** > **Stages** > `default-authentication-identification`
2. Set **Recovery flow** to `default-recovery-flow` (if it exists)
3. Click **Update**
## Step 5: Verify OIDC Endpoints
After creation, go to **Applications** > **Providers** > **Kaboot OAuth2**
Note these endpoints (you'll need them for frontend configuration):
| Endpoint | URL |
|----------|-----|
| Issuer | `http://localhost:9000/application/o/kaboot/` |
| Authorization | `http://localhost:9000/application/o/authorize/` |
| Token | `http://localhost:9000/application/o/token/` |
| UserInfo | `http://localhost:9000/application/o/userinfo/` |
| JWKS | `http://localhost:9000/application/o/kaboot/jwks/` |
## Step 5: Test the Configuration
1. Open the OpenID Configuration URL in your browser:
```
http://localhost:9000/application/o/kaboot/.well-known/openid-configuration
```
2. You should see a JSON response with all OIDC endpoints
## Step 6: Create a Test User
Create a regular user for manual browser testing.
1. Go to **Directory** > **Users**
2. Click **Create**
3. Fill in user details:
| Field | Value |
|-------|-------|
| Username | `kaboottest` |
| Name | `Kaboot Test` |
| Email | `kaboottest@test.com` |
4. After creation, click on the user and go to the **Credentials** tab
5. Click **Set password** and set it to `kaboottest`
6. **Bind the user to the Kaboot application**:
- Go to **Applications** > **Applications** > **Kaboot**
- Click the **Policy / Group / User Bindings** tab
- Click **Bind existing user**
- Select `kaboottest` and click **Bind**
## Step 7: Create a Service Account for API Testing
Create a service account that can obtain tokens programmatically for automated tests.
1. Go to **Directory** > **Users**
2. Click **Create Service Account**
3. Fill in details:
| Field | Value |
|-------|-------|
| Username | `kaboot-test-service` |
| Create group | Unchecked |
4. Click **Create**
5. **Create an App Password** for the service account:
- Click on the newly created `kaboot-test-service` user
- Go to the **App passwords** tab
- Click **Create App Password**
- Name it `api-tests`
- Copy the generated password (you won't see it again!)
6. **Bind the service account to the Kaboot application**:
- Go to **Applications** > **Applications** > **Kaboot**
- Click the **Policy / Group / User Bindings** tab
- Click **Bind existing user**
- Select `kaboot-test-service` and click **Bind**
7. **Save credentials to `server/.env.test`**:
```bash
TEST_USERNAME=kaboot-test-service
TEST_PASSWORD=<paste-app-password-here>
```
8. **Verify token generation works**:
```bash
cd server
npm run test:get-token
```
You should see "Token obtained successfully" and the access token printed.
## Environment Variables
### Development (localhost only)
For local development on a single machine:
```bash
KABOOT_HOST=localhost
```
### Development (network/mobile access)
To access from other devices (phones, tablets), set `KABOOT_HOST` to your machine's IP:
```bash
KABOOT_HOST=192.168.1.100
```
The setup script (`./scripts/setup.sh`) auto-detects your IP and configures:
- `.env` - Backend CORS and docker-compose variables
- `.env.local` - Frontend Vite environment variables
**Important**: You must also update redirect URIs in Authentik to include:
- `http://<your-ip>:5173/callback`
- `http://<your-ip>:5173/silent-renew.html`
- `http://<your-ip>:5173`
Then run the dev server with `npm run dev -- --host` to bind to all interfaces.
## Troubleshooting
### "Invalid redirect URI" error
- Ensure all redirect URIs are added exactly as configured in the provider
- Check for trailing slashes - they must match exactly
### "Client not found" error
- Verify the Client ID matches `kaboot-spa`
- Ensure the application is enabled (not archived)
### CORS errors
- Authentik handles CORS automatically for configured redirect URIs
- Ensure your frontend origin (`http://localhost:5173`) is in the redirect URIs
### Token validation fails on backend
- Verify `OIDC_ISSUER` and `OIDC_JWKS_URI` are correct
- The backend must be able to reach Authentik at `http://authentik-server:9000` (Docker network)
## Required OIDC Claims
The Kaboot backend validates the following JWT claims:
| Claim | Required | Description |
|-------|----------|-------------|
| `sub` | Yes | User identifier (subject) |
| `iss` | Yes | Must match `OIDC_ISSUER` env var |
| `aud` | Recommended | Must match `OIDC_AUDIENCE` env var if set |
| `preferred_username` | No | Display name, falls back to `sub` |
| `email` | No | User's email address |
| `groups` | No | Array of group names for access control |
### Audience Claim Configuration
The `aud` (audience) claim prevents tokens issued for other applications from being accepted. The blueprint configures this automatically via the `kaboot` scope.
**Backend Configuration:**
```bash
# Set to your OIDC client ID
OIDC_AUDIENCE=kaboot-spa
```
**Frontend Configuration:**
The frontend must request the `kaboot` scope to include the audience claim:
```typescript
// src/config/oidc.ts
scope: 'openid profile email offline_access groups kaboot'
```
**Manual Authentik Setup (if not using blueprints):**
1. Go to **Customisation** > **Property Mappings**
2. Click **Create** > **Scope Mapping**
3. Configure:
| Field | Value |
|-------|-------|
| Name | `Kaboot Audience Scope` |
| Scope name | `kaboot` |
| Expression | `return {"aud": "kaboot-spa"}` |
4. Go to **Applications** > **Providers** > **Kaboot OAuth2**
5. Edit and add the new scope mapping to **Scopes**
### Groups Claim for Access Control
The `groups` claim controls access to premium features:
| Group | Access Level |
|-------|--------------|
| `kaboot-users` | Basic access (required to use app) |
| `kaboot-ai-access` | Unlimited AI generations, OCR access |
| `kaboot-admin` | Admin features |
The groups scope mapping is configured in the blueprint. For manual setup:
1. Create a scope mapping with expression:
```python
return {"groups": [group.name for group in request.user.ak_groups.all()]}
```
2. Add it to the provider's scopes
## Production Notes
For production deployment, see [PRODUCTION.md](./PRODUCTION.md) for full instructions.