From a93205bc8291e72f66bcd0766fc713615083e73f Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Fri, 31 Jul 2026 20:46:35 +1000 Subject: [PATCH] Set explicit launch URL for the LiteLLM application Ben (akR-global-admin) does not see the LiteLLM tile on the Authentik user dashboard, while ArgoCD/Grafana/Rancher appear normally. The live API shows LiteLLM is configured identically to those apps: the app exists, its access binding akP-litellm-admin -> litellm is present, and akR-global-admin nests akP-litellm-admin (bidirectionally, same as the others). A CI-style plan against live state reports "No changes" -- so this is not terraform-correctable drift, and a plain re-apply fixes nothing. Yet check_access for Ben returns passing=false for litellm and passing=true for the rest: a stale cached access policy result inside Authentik. Add an optional per-app launch_url to the providers_oauth2 config (default null, which keeps Authentik's redirect-derived URL) and wire it to the application's meta_launch_url. Set it for LiteLLM to its UI. This makes the dashboard tile deterministic and, on apply, re-saves the application -- invalidating the stale access-policy cache so Ben's (already-correct) access re-evaluates and the tile appears. Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv --- config/providers_oauth2/litellm.yaml | 4 ++++ modules/authentik/main.tf | 2 ++ modules/authentik/variables.tf | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/config/providers_oauth2/litellm.yaml b/config/providers_oauth2/litellm.yaml index ebc28c7..0c35e40 100644 --- a/config/providers_oauth2/litellm.yaml +++ b/config/providers_oauth2/litellm.yaml @@ -6,6 +6,10 @@ authorization_flow: default-provider-authorization-implicit-consent invalidation_flow: default-provider-invalidation-flow client_type: confidential client_id: litellm +# Explicit dashboard tile launch URL (the LiteLLM UI). Authentik would otherwise +# derive this from the redirect_uri; setting it here makes the tile deterministic +# and forces an application re-save so the cached access policy is re-evaluated. +launch_url: https://litellm.k8s.syd1.au.unkin.net/ client_secret_vault: mount: kv path: kubernetes/namespace/litellm/default/oauth-credentials diff --git a/modules/authentik/main.tf b/modules/authentik/main.tf index 33c6fe4..5a28685 100644 --- a/modules/authentik/main.tf +++ b/modules/authentik/main.tf @@ -192,6 +192,8 @@ resource "authentik_application" "oauth2" { name = each.value.name slug = each.key protocol_provider = authentik_provider_oauth2.this[each.key].id + # Null keeps Authentik's derived launch URL (from the first redirect_uri). + meta_launch_url = each.value.launch_url } resource "authentik_application" "ldap" { diff --git a/modules/authentik/variables.tf b/modules/authentik/variables.tf index b96d052..1c54ed5 100644 --- a/modules/authentik/variables.tf +++ b/modules/authentik/variables.tf @@ -82,6 +82,11 @@ variable "providers_oauth2" { })), []) signing_key = optional(string, null) access_token_validity = optional(string, "minutes=10") + # Explicit launch URL for the app tile on the user dashboard ("My + # applications"). Null lets Authentik derive it from the first redirect_uri; + # set it to the app's UI to make the tile deterministic and to force an + # application re-save (which invalidates Authentik's cached access policy). + launch_url = optional(string, null) # Optional app-role claim computed from (hierarchical) group membership: emit # `claim` = the first matching rule's role, else `default`. The app requests # `claim` as a scope and reads it (e.g. LiteLLM GENERIC_USER_ROLE_ATTRIBUTE).