From 366cdafd6a0c817ead198d3f94f9058d65e4370f Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Mon, 12 Oct 2026 00:18:21 +1100 Subject: [PATCH 1/4] Add stalwart OIDC application and provider - add config/providers_oauth2/stalwart.yaml reading its client_secret from kv/kubernetes/namespace/mail/stalwart/oauth-credentials - add permission group akP-mail-users bound to the stalwart application - nest akP-mail-users under akR-global-admin --- config/permissions/akP-mail-users.yaml | 3 +++ config/providers_oauth2/stalwart.yaml | 21 +++++++++++++++++++++ config/roles/akR-global-admin.yaml | 1 + 3 files changed, 25 insertions(+) create mode 100644 config/permissions/akP-mail-users.yaml create mode 100644 config/providers_oauth2/stalwart.yaml diff --git a/config/permissions/akP-mail-users.yaml b/config/permissions/akP-mail-users.yaml new file mode 100644 index 0000000..21745b0 --- /dev/null +++ b/config/permissions/akP-mail-users.yaml @@ -0,0 +1,3 @@ +# Permission group akP-mail-users (name = filename). Grants mailbox access: +# bound to the stalwart application, gating mail.unkin.net logins. +application: stalwart diff --git a/config/providers_oauth2/stalwart.yaml b/config/providers_oauth2/stalwart.yaml new file mode 100644 index 0000000..29d05a3 --- /dev/null +++ b/config/providers_oauth2/stalwart.yaml @@ -0,0 +1,21 @@ +# OAuth2/OIDC provider + application for Stalwart (mail server, web UI/JMAP at +# https://mail.unkin.net in the mail namespace). Stalwart's OIDC directory +# validates access tokens (JWT, userinfo fallback) and requires aud=stalwart +# plus the openid+email scopes; it maps preferred_username/name from profile. +# client_secret is read from Vault (seeded out of band), never committed. +name: stalwart +authorization_flow: default-provider-authorization-implicit-consent +invalidation_flow: default-provider-invalidation-flow +client_type: confidential +client_id: stalwart +launch_url: https://mail.unkin.net/ +client_secret_vault: + mount: kv + path: kubernetes/namespace/mail/stalwart/oauth-credentials +scope_mappings: + - goauthentik.io/providers/oauth2/scope-openid + - goauthentik.io/providers/oauth2/scope-email + - goauthentik.io/providers/oauth2/scope-profile +redirect_uris: + - matching_mode: strict + url: https://mail.unkin.net/oauth2/callback diff --git a/config/roles/akR-global-admin.yaml b/config/roles/akR-global-admin.yaml index d378b75..1f0b61b 100644 --- a/config/roles/akR-global-admin.yaml +++ b/config/roles/akR-global-admin.yaml @@ -10,6 +10,7 @@ permissions: - akP-traefik-admin - akP-logviewer-admin - akP-vlogs-admin + - akP-mail-users - akP-watchstate-admin - akP-repospawner-admin - akP-vault-admin From 0f8ec8a9601713ce19871a98e3e8957643a04667 Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Mon, 12 Oct 2026 00:20:08 +1100 Subject: [PATCH 2/4] Read stalwart client secret from the mail default SA path --- config/providers_oauth2/stalwart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/providers_oauth2/stalwart.yaml b/config/providers_oauth2/stalwart.yaml index 29d05a3..d92c73a 100644 --- a/config/providers_oauth2/stalwart.yaml +++ b/config/providers_oauth2/stalwart.yaml @@ -11,7 +11,7 @@ client_id: stalwart launch_url: https://mail.unkin.net/ client_secret_vault: mount: kv - path: kubernetes/namespace/mail/stalwart/oauth-credentials + path: kubernetes/namespace/mail/default/oauth-credentials scope_mappings: - goauthentik.io/providers/oauth2/scope-openid - goauthentik.io/providers/oauth2/scope-email From bfcc362239771b0c3cc76ef31149b06dffbd2891 Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Mon, 12 Oct 2026 00:22:44 +1100 Subject: [PATCH 3/4] Rename akP-mail-users to akP-mail-user --- config/permissions/{akP-mail-users.yaml => akP-mail-user.yaml} | 2 +- config/roles/akR-global-admin.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename config/permissions/{akP-mail-users.yaml => akP-mail-user.yaml} (53%) diff --git a/config/permissions/akP-mail-users.yaml b/config/permissions/akP-mail-user.yaml similarity index 53% rename from config/permissions/akP-mail-users.yaml rename to config/permissions/akP-mail-user.yaml index 21745b0..8d78fd6 100644 --- a/config/permissions/akP-mail-users.yaml +++ b/config/permissions/akP-mail-user.yaml @@ -1,3 +1,3 @@ -# Permission group akP-mail-users (name = filename). Grants mailbox access: +# Permission group akP-mail-user (name = filename). Grants mailbox access: # bound to the stalwart application, gating mail.unkin.net logins. application: stalwart diff --git a/config/roles/akR-global-admin.yaml b/config/roles/akR-global-admin.yaml index 1f0b61b..9f5c90c 100644 --- a/config/roles/akR-global-admin.yaml +++ b/config/roles/akR-global-admin.yaml @@ -10,7 +10,7 @@ permissions: - akP-traefik-admin - akP-logviewer-admin - akP-vlogs-admin - - akP-mail-users + - akP-mail-user - akP-watchstate-admin - akP-repospawner-admin - akP-vault-admin From dc5a24e564e9f210a7a35f3fabd1145a9aea3fde Mon Sep 17 00:00:00 2001 From: unkin-agent Date: Mon, 12 Oct 2026 00:43:53 +1100 Subject: [PATCH 4/4] Make stalwart a public PKCE client with account and admin callbacks --- config/providers_oauth2/stalwart.yaml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/config/providers_oauth2/stalwart.yaml b/config/providers_oauth2/stalwart.yaml index d92c73a..e35a8bf 100644 --- a/config/providers_oauth2/stalwart.yaml +++ b/config/providers_oauth2/stalwart.yaml @@ -2,20 +2,19 @@ # https://mail.unkin.net in the mail namespace). Stalwart's OIDC directory # validates access tokens (JWT, userinfo fallback) and requires aud=stalwart # plus the openid+email scopes; it maps preferred_username/name from profile. -# client_secret is read from Vault (seeded out of band), never committed. +# public, no secret: the web UI uses PKCE; the strict redirect URIs are the control. name: stalwart authorization_flow: default-provider-authorization-implicit-consent invalidation_flow: default-provider-invalidation-flow -client_type: confidential +client_type: public client_id: stalwart launch_url: https://mail.unkin.net/ -client_secret_vault: - mount: kv - path: kubernetes/namespace/mail/default/oauth-credentials scope_mappings: - goauthentik.io/providers/oauth2/scope-openid - goauthentik.io/providers/oauth2/scope-email - goauthentik.io/providers/oauth2/scope-profile redirect_uris: - matching_mode: strict - url: https://mail.unkin.net/oauth2/callback + url: https://mail.unkin.net/account/oauth/callback + - matching_mode: strict + url: https://mail.unkin.net/admin/oauth/callback