Set OAuth2 grant_types so authorization_code login works
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/plan Pipeline was successful

## Why

All Authentik OIDC logins (ArgoCD, Grafana, Rancher, LiteLLM, NetBox) fail
with `invalid_request` / "The request is otherwise malformed". Authentik
2026.5 added an explicit `grant_types` allow-list to the OAuth2 provider
(model default = empty list). Our module never set it, so every provider has
`grant_types = []`, and `authorize.py` rejects the authorization_code grant
(`if self.grant_type not in self.provider.grant_types`) before any user auth.

## Change

- modules/authentik: add a `grant_types` field to the `providers_oauth2`
  variable, defaulting to `["authorization_code", "refresh_token"]` (the
  standard confidential web-app set), and wire it into
  `authentik_provider_oauth2`.

## Plan

`0 to add, 5 to change, 0 to destroy` — each existing oauth2 provider's
`grant_types` goes `[] -> ["authorization_code", "refresh_token"]`; no other
attributes change. Baseline plan (pre-change) was clean (no netbox/state drift).

Claude-Session: https://claude.ai/code/session_015ur3i7D2azsMAWTSVABApv
This commit is contained in:
2026-07-28 22:09:06 +10:00
parent 21ef853a7c
commit 2b39450ae2
2 changed files with 7 additions and 0 deletions
+1
View File
@@ -159,6 +159,7 @@ resource "authentik_provider_oauth2" "this" {
signing_key = each.value.signing_key
access_token_validity = each.value.access_token_validity
allowed_redirect_uris = each.value.redirect_uris
grant_types = each.value.grant_types
}
resource "authentik_provider_ldap" "this" {
+6
View File
@@ -67,6 +67,12 @@ variable "providers_oauth2" {
# Managed identifiers of scope property mappings (e.g.
# goauthentik.io/providers/oauth2/scope-openid). Resolved to ids.
scope_mappings = optional(list(string), [])
# OAuth2 grant types the provider permits. Authentik 2026.5 added this as an
# explicit allow-list on the provider (models default = empty); an empty list
# rejects every authorize request with "invalid_request / The request is
# otherwise malformed". Default to the standard confidential web-app set so
# authorization_code (login) and refresh_token (offline access) work.
grant_types = optional(list(string), ["authorization_code", "refresh_token"])
# allowed_redirect_uris is list(map(string)); the API always stores a
# redirect_uri_type key, so it must be set here or every plan drifts.
redirect_uris = optional(list(object({