Authentik setup and integration
This guide describes how to run Authentik as a container and integrate it with Rediflow for OIDC authentication.
Overview
- Authentik runs as a container (profile
authentik) and uses the same PostgreSQL instance as Rediflow, with a separate database per env (AUTHENTIK_POSTGRESQL__NAME:authentik_dev,authentik_test,authentik_qa,authentik_prod). - For QA or production with the registry image (
registry.gitlab.com/rediflow_eu/rediflow:latest), usecompose.deploy-qa-authentik.ymlorcompose.deploy-prod-authentik.yml. See Deploy QA and production for the full guide. - Rediflow acts as an OIDC client: when
OIDC_ISSUERandOIDC_CLIENT_IDare set, the app requires login and redirects unauthenticated users to Authentik. - After login, Authentik redirects back with an auth code; the app exchanges it for a token, resolves or creates a
Userby OIDCsub, and setsg.current_user,g.authentik_groups.
1. Start Authentik with Podman Compose
1.1 Generate credentials
Add to .env.dev (or your env file):
# Generate AUTHENTIK_SECRET_KEY (required for authentik profile)
AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60)
Or set manually:
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60)" >> .env.dev
1.2 Start services
podman compose --profile authentik --profile dev up -d
This starts:
db– PostgreSQL (shared; Authentik uses a separate DB per env)db-init-authentik– one-off that creates the Authentik database (name fromAUTHENTIK_POSTGRESQL__NAME)redis– required by Authentikauthentik-server– Authentik UI and API (ports 9000, 9443)authentik-worker– background tasksapp– Rediflow (if using dev profile)
1.3 Initial Authentik setup
- Open
http://localhost:9000/if/flow/initial-setup/(note the trailing slash). - Set a password for the default
akadminuser. - Complete the setup wizard if prompted.
2. Create OIDC application in Authentik
2.1 Create an OAuth2/OIDC provider
- Go to Applications → Providers → Create.
- Choose OAuth2/OIDC Provider.
- Configure:
- Name: e.g.
rediflow - Redirect URIs:
http://localhost:5000/oauth/callback(or your app URL in prod) - Client type: Confidential
- Signing Key: Create or select an RSA key
- Name: e.g.
- Save.
- Under Provider → Advanced protocol settings, ensure the Scopes include
openid,profile,email, andgroups(Authentik may expose groups via a custom scope or attribute).
2.2 Include groups in the token
Authentik sends group names via scope mappings. Configure a scope mapping for the groups scope that returns the user's groups (e.g. via user.ak_groups or user.all_groups()). See Provider property mappings.
Token format: Rediflow reads groups from the OIDC token as follows:
- userinfo or id_token claims:
groupsorak_groups - Values: list of strings (e.g.
["rediflow-admins", "rediflow-org-ACR"]) or list of dicts with anamekey (e.g.[{"name": "rediflow-editors"}])
Ensure the provider's Scopes include groups so the mapping is applied.
2.3 Create an application
- Go to Applications → Applications → Create.
- Name: e.g.
Rediflow - Provider: Select the provider created above.
- Slug: e.g.
rediflow(used in the issuer URL). - Save.
2.4 Get client credentials
From the provider or application settings, copy:
- Client ID
- Client Secret
The issuer URL is typically:
http://localhost:9000/application/o/rediflow/
(Replace rediflow with your application slug.)
3. Configure Rediflow
Add to .env.dev:
OIDC_ISSUER=http://localhost:9000/application/o/rediflow/
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
# Optional; default is {APP_URL}/oauth/callback
# OIDC_REDIRECT_URI=http://localhost:5000/oauth/callback
Restart the app:
podman compose --profile authentik --profile dev up -d --force-recreate app
4. Authentik groups for Rediflow
Create these groups in Authentik and assign users:
| Group | Purpose |
|---|---|
rediflow-super-admins |
Solution admins: bypass locked state, edit past months |
rediflow-admins |
Full visibility; manage orgs, role types, calendars |
rediflow-editors |
Edit projects (when visibility allows) |
rediflow-viewers |
View-only access |
rediflow-visibility-org |
Enforce org-scoped visibility |
rediflow-visibility-assigned |
Enforce assignment-only visibility |
rediflow-org-<short_name> |
Org membership (e.g. rediflow-org-ACR) |
For a fuller explanation of organisation visibility and when to use each mode, see Organisation visibility. See also Help: Authentik and project visibility for in-app details.
4.1 Rediflow branding
To apply Rediflow branding (title, theme, custom CSS) to the Authentik login screen:
Via script (recommended):
make setup-authentik-brand
Or with OIDC setup: uv run python scripts/setup_authentik_oidc.py --write-env --apply-brand
Optional env vars: REDIFLOW_LOGO_URL, REDIFLOW_FAVICON_URL (URLs for logo and favicon; e.g. https://your-app/static/img/logo.svg).
Via blueprint: Mount authentik-rediflow-brand/ into the Authentik container and run ak apply_blueprint /blueprints/rediflow-brand/blueprint.yaml. See authentik-rediflow-brand/README.md for details.
Manual: In Authentik Admin → System → Brands → Edit default brand. Set title to "Rediflow", upload or link logo/favicon, and add custom CSS if desired.
5. Test environment and seeded users
For local testing with containerised Authentik and pre-seeded users:
-
Copy
.env.test.exampleto.env.testand adjust if needed. -
Create the test database:
createdb -h localhost -p 15433 -U rediflow rediflow_test(or let compose create it). -
Run migrations:
APP_ENV=test uv run python main.py migrate(withDATABASE_URLfrom.env.test). -
Start the stack:
podman compose -f compose.yml -f compose.authentik-test.yml --profile authentik --profile dev up -d -
Open
http://localhost:9001/if/flow/initial-setup/and set the akadmin password (or useAUTHENTIK_BOOTSTRAP_PASSWORDfrom.env.test). -
Create the OIDC provider and application (automated or manual):
- Automated: Run
make setup-authentik-oidcto create the provider and application via API and update.env.testwith credentials. - Manual: Create the OIDC provider and application in Authentik (see section 2). Use redirect URI
http://localhost:5002/oauth/callback(app runs on port 5002 in test). Copy the client ID and secret into.env.test(OIDC_CLIENT_ID,OIDC_CLIENT_SECRET).
- Automated: Run
-
Restart the app if needed.
-
Seed users and pair them with Rediflow:
uv run python scripts/seed_authentik_test_users.py uv run python scripts/seed_authentik_test_users.py --link-persons # optional: link Person to UserODS-based seed (project + people from ODS, matches sane defaults):
make build-authentik-test-ods # creates docs/example_authentik_test_people.ods make seed-authentik-test-ods # seeds from docs/example.ods + example_authentik_test_people.ods, links Person to UserThe people ODS has persons with codes
admin@test,editor@test,viewer@test,orguser@test(matching Authentik usernames). Requiresdocs/example.odsfor the project.
The seed script creates:
| User | Groups | Rights |
|---|---|---|
| admin@test | rediflow-admins | Full access |
| editor@test | rediflow-editors | Edit projects |
| viewer@test | rediflow-viewers | View only |
| orguser@test | rediflow-editors, rediflow-org-EXAMPLE | Editor + org EXAMPLE |
All seeded users have password test-password. Rediflow User records are created with external_id set to the Authentik user UUID (OIDC sub), so login automatically pairs them.
6. Without Authentik (no OIDC)
If OIDC_ISSUER and OIDC_CLIENT_ID are not set, the app behaves as before: no login redirect, g.current_user and g.authentik_groups stay empty. POLICY_NO_AUTH_DEFAULT controls behaviour (allow_all or view_only).
For developers: How login enforcement works, public paths, and how to add routes to the allowlist: see Authentik: Enforcing login (developer guide).
7. Row Level Security (RLS)
With Authentik, the app sets the PostgreSQL session variable app.current_user_id per request. RLS policies on user_settings and shared_views restrict access by user. When no user is logged in (or OIDC is disabled), the variable is empty and policies allow full access for backward compatibility.
RLS policies apply only when the app connects as a non-owner role. By default, the app uses the same role that runs migrations (table owner), so RLS is bypassed. To enable RLS, use a two-role setup: migrations run as owner; the app connects as a separate role with grants.
7.1 Enabling RLS in .env.test
- Copy
.env.test.exampleto.env.test. - Ensure
POSTGRES_APP_USER,POSTGRES_APP_PASSWORD, andDATABASE_URL_APPare set (they are in the example). - Set
RLS_ENABLED=true. - Start the stack and run migrations (as owner):
make up-authentik-test set -a; . ./.env.test; set +a; uv run python main.py migrate head - Create the app role and grant permissions:
Or:make setup-rls-app-roleuv run rediflow setup-rls-app-role(with.env.testloaded). - Restart the app so it connects as
rediflow_app:podman compose -f compose.yml -f compose.authentik-test.yml --profile authentik --profile dev up -d --force-recreate app
Migrations always use DATABASE_URL (owner). The app uses DATABASE_URL_APP when RLS_ENABLED=true. See docs/plans/2026-02-16_232813-rls-authentik.md for details.
8. Troubleshooting
-
Initial setup
/if/flow/initial-setup/shows "Not Found": The initial-setup flow only exists when Authentik has not been configured. If you see "Not Found", either:- Already set up: Try
http://localhost:9001/and log in withakadminand your password. - Bootstrap failed: Default flows were not created. Restart Authentik and wait 2–3 minutes for it to finish booting. If it still fails, apply blueprints manually:
Then create the admin user if needed:podman exec rediflow-authentik-server ak apply_blueprint /blueprints/default/flow-default-authentication-flow.yaml podman exec rediflow-authentik-server ak apply_blueprint /blueprints/default/flow-default-invalidation-flow.yaml podman exec rediflow-authentik-server ak apply_blueprint /blueprints/default/flow-default-user-settings-flow.yaml podman exec rediflow-authentik-server ak apply_blueprint /blueprints/default/default-brand.yamlpodman exec -it rediflow-authentik-server ak shelland runfrom authentik.core.models import User; user = User.objects.create(username='akadmin', name='Admin', email='admin@localhost'); user.set_password('YourPassword'); user.is_active = True; user.save(), thenpodman exec rediflow-authentik-server ak create_admin_group akadmin.
- Already set up: Try
-
Authentik cannot connect to PostgreSQL: Ensure the
dbservice is healthy and reachable from theauthentik-servercontainer. CheckAUTHENTIK_POSTGRESQL__HOST=db,AUTHENTIK_POSTGRESQL__NAME, and credentials. -
Redirect URI mismatch: The redirect URI in Authentik must exactly match what the app uses (e.g.
http://localhost:5000/oauth/callback). No trailing slash. -
Groups not in token: Ensure Authentik is configured to include groups in the
groupsclaim or userinfo. Check the provider’s scope mapping. -
RLS not applying: RLS policies are bypassed by the table owner. Use a two-role setup (app role with grants, migrator role as owner) for RLS to take effect.