From 246196407acee4beca35242a8b4a1e7d052d2099 Mon Sep 17 00:00:00 2001 From: Story Crater Bot <19826264+Riotpiaole@users.noreply.github.com> Date: Tue, 21 Jul 2026 23:40:49 -0700 Subject: [PATCH] =?UTF-8?q?fix(iam):=20set=20OAuth2=20provider=20grant=5Ft?= =?UTF-8?q?ypes=20+=20non-deprecated=20groups=20claim=20=E2=80=94=20empty?= =?UTF-8?q?=20grant=5Ftypes=20made=20authentik=20reject=20authorization=5F?= =?UTF-8?q?code,=20breaking=20SSO=20login=20for=20every=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- k8s/security/iam/authentik-provision-job.yaml | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/k8s/security/iam/authentik-provision-job.yaml b/k8s/security/iam/authentik-provision-job.yaml index 5caa541..840f6d9 100644 --- a/k8s/security/iam/authentik-provision-job.yaml +++ b/k8s/security/iam/authentik-provision-job.yaml @@ -154,8 +154,16 @@ data: { "name": "homelab: groups claim", "scope_name": "groups", + # request.user.ak_groups is deprecated in authentik 2026.x (logs a + # deprecation warning on every token issue) -> use request.user.groups. "expression": ( - "return {\"groups\": [group.name for group in request.user.ak_groups.all()]}" + "return {\"groups\": [group.name for group in request.user.groups.all()]}" + ), + }, + # Force the expression onto the already-created mapping on re-run. + patch_existing={ + "expression": ( + "return {\"groups\": [group.name for group in request.user.groups.all()]}" ), }, ) @@ -292,15 +300,22 @@ data: "property_mappings": SCOPE_PKS, "sub_mode": "hashed_user_id", "include_claims_in_id_token": True, + # authentik 2026.x requires grant_types to be set explicitly; the + # API defaults it to [] when omitted, which makes /authorize reject + # every login with "Invalid grant_type for provider" -> + # invalid_request. authorization_code = the web SSO flow all these + # apps use; refresh_token = long-lived sessions (offline_access). + "grant_types": ["authorization_code", "refresh_token"], "redirect_uris": [ {"matching_mode": "strict", "url": u} for u in cfg["redirect_uris"] ], }, - # Keep the redirect_uris/mappings in sync on re-run, but never touch - # client_secret again once created (that's the source of truth in the - # k8s Secret, and re-sending it here is harmless/idempotent anyway). + # Keep the redirect_uris/mappings/grant_types in sync on re-run, but + # never touch client_secret again once created (that's the source of + # truth in the k8s Secret, and re-sending it here is harmless anyway). patch_existing={ "property_mappings": SCOPE_PKS, + "grant_types": ["authorization_code", "refresh_token"], "redirect_uris": [ {"matching_mode": "strict", "url": u} for u in cfg["redirect_uris"] ],