- src/lib/auth/oidc-state.ts (new): pack {state, codeVerifier} into a
short-lived signed JWT, store in an httpOnly cookie. Replaces the
process-local Map that broke under multi-worker deployments where
/api/auth/login and /api/auth/callback would land on different workers.
- src/pages/api/auth/{login,callback,logout,profile,status}.ts: drop the
Map-based state-store calls; use oidc-state for set/get/clear.
- src/lib/auth/oidc-client.ts, session-manager.ts, config/authentik.ts:
small adjustments to fit the new state surface.
- src/components/auth/AuthenticatedLayout.astro, src/layouts/Layout.astro:
trim a lot of layout boilerplate (~125 lines each).
- astro.config.mjs, docker-compose.local.yml: minor cleanup.
- authentik-blueprints/heady-oidc.yaml (new): declarative provider +
application blueprint to ship alongside Heady deployments.
83 lines
3.4 KiB
YAML
83 lines
3.4 KiB
YAML
# Authentik blueprint: Heady OIDC application + provider + scope mappings.
|
|
#
|
|
# This blueprint declaratively creates everything Heady needs to authenticate
|
|
# users against Authentik. Drop it in /blueprints/local/ inside the Authentik
|
|
# container (the docker-compose mounts ../authentik-blueprints to that path)
|
|
# and Authentik will reconcile it on startup.
|
|
#
|
|
# Load order matters: scope mappings must exist before the provider can
|
|
# reference them; the provider must exist before the application can bind
|
|
# to it. Authentik's blueprint engine handles dependency ordering via the
|
|
# `!KeyOf` / `!Find` tags.
|
|
|
|
version: 1
|
|
metadata:
|
|
name: heady-oidc
|
|
labels:
|
|
blueprints.goauthentik.io/instantiate: 'true'
|
|
|
|
context:
|
|
# Override these in deployment by passing -e VAR=value to the Authentik
|
|
# container or by writing site-specific values directly.
|
|
heady_redirect_uri: http://localhost:3007/api/auth/callback
|
|
heady_app_slug: heady
|
|
heady_app_name: Heady
|
|
|
|
entries:
|
|
# ─── Scope mapping that exposes the user's group memberships ──────────
|
|
# Authentik's defaults include openid/email/profile but NOT groups; Heady's
|
|
# role mapper needs `groups` in the userinfo response to map Authentik
|
|
# groups → Heady roles (admin / network_admin / etc).
|
|
- model: authentik_providers_oauth2.scopemapping
|
|
id: heady-groups-mapping
|
|
identifiers:
|
|
managed: heady.scopemapping.groups
|
|
attrs:
|
|
name: 'Heady: groups'
|
|
scope_name: groups
|
|
description: List the groups a user belongs to.
|
|
expression: |
|
|
return {
|
|
"groups": [g.name for g in user.ak_groups.all()],
|
|
}
|
|
|
|
# ─── OAuth2 / OIDC provider ───────────────────────────────────────────
|
|
# Confidential client with PKCE. Uses the implicit-consent authorization
|
|
# flow shipped with Authentik so users aren't prompted on each login.
|
|
- model: authentik_providers_oauth2.oauth2provider
|
|
id: heady-oidc-provider
|
|
identifiers:
|
|
name: Heady OIDC
|
|
attrs:
|
|
client_type: confidential
|
|
authorization_flow:
|
|
!Find [authentik_flows.flow, [slug, default-provider-authorization-implicit-consent]]
|
|
invalidation_flow:
|
|
!Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
|
sub_mode: user_email
|
|
include_claims_in_id_token: true
|
|
access_token_validity: hours=1
|
|
refresh_token_validity: days=30
|
|
redirect_uris:
|
|
- matching_mode: strict
|
|
url: !Context heady_redirect_uri
|
|
property_mappings:
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, openid]]
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, email]]
|
|
- !Find [authentik_providers_oauth2.scopemapping, [scope_name, profile]]
|
|
- !KeyOf heady-groups-mapping
|
|
|
|
# ─── Application binding ──────────────────────────────────────────────
|
|
# The Application is what users see in the Authentik portal and what
|
|
# the OIDC issuer URL resolves to:
|
|
# https://<authentik>/application/o/<slug>/
|
|
- model: authentik_core.application
|
|
identifiers:
|
|
slug: !Context heady_app_slug
|
|
attrs:
|
|
name: !Context heady_app_name
|
|
provider: !KeyOf heady-oidc-provider
|
|
meta_description: Heady VPN management console
|
|
open_in_new_tab: false
|
|
policy_engine_mode: any
|