# 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:///application/o// - 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