From 0417ecd9a18a75093cad9a2892b87226cc1806a3 Mon Sep 17 00:00:00 2001 From: lhahn Date: Wed, 14 Oct 2026 18:07:06 +0200 Subject: [PATCH] Add OpenID Connect SSO with optional authentik blueprint - SSO_* settings (login only, master password still decrypts the vault) - optional authentik blueprint: provider with authorization_code/refresh_token grants, application and an email mapping with email_verified, which vaultwarden requires to link SSO logins to existing accounts - blueprints are copied into the authentik container, it only applies files from /blueprints Co-Authored-By: Claude Opus 5.5 --- defaults/main.yml | 19 +++++++ tasks/main.yml | 20 +++++++ .../opt/authentik/vaultwarden-sso.yaml.j2 | 52 +++++++++++++++++++ templates/opt/vaultwarden/.env.j2 | 13 +++++ 4 files changed, 104 insertions(+) create mode 100644 templates/opt/authentik/vaultwarden-sso.yaml.j2 diff --git a/defaults/main.yml b/defaults/main.yml index 3456289..18d6b5d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -34,3 +34,22 @@ vaultwarden_smtp_user: user@my-domain.tld vaultwarden_smtp_pass: ThisCouldBeYourAdd vaultwarden_loglevel: warn + +#OpenID Connect single sign on (login only; the master password still decrypts the vault) +vaultwarden_sso_enabled: false +vaultwarden_sso_only: false +vaultwarden_sso_signups_match_email: true +vaultwarden_sso_authority: "https://idp.{{ domain_external }}/application/o/{{ vaultwarden_sso_slug }}/" +vaultwarden_sso_scopes: "email profile offline_access" +vaultwarden_sso_client_id: vaultwarden +vaultwarden_sso_client_secret: SSOClientSecret + +#create provider + application in a local authentik through a blueprint +vaultwarden_sso_authentik: false +vaultwarden_sso_slug: vaultwarden +vaultwarden_sso_name: Vaultwarden +vaultwarden_sso_authentik_data: "{{ cloud_apps }}/authentik/inst/data" +vaultwarden_sso_authentik_container: inst-worker-1 +vaultwarden_sso_authentik_signing_key: "authentik Self-signed Certificate" +vaultwarden_sso_authentik_authorization_flow: default-provider-authorization-implicit-consent +vaultwarden_sso_authentik_invalidation_flow: default-provider-invalidation-flow diff --git a/tasks/main.yml b/tasks/main.yml index 116f8c9..34b82e3 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -41,3 +41,23 @@ community.docker.docker_compose_v2: project_src: "{{ vaultwarden_inst }}" state: present + +- name: setup authentik blueprint for vaultwarden sso + template: + src: opt/authentik/vaultwarden-sso.yaml.j2 + dest: "{{ vaultwarden_sso_authentik_data }}/vaultwarden-sso.yaml" + mode: 0600 + owner: "1000" + group: "1000" + register: vaultwarden_sso_blueprint + when: vaultwarden_sso_enabled | bool and vaultwarden_sso_authentik | bool + +# authentik only applies blueprints from its own blueprints folder +- name: apply authentik blueprint for vaultwarden sso + command: + cmd: "{{ item }}" + loop: + - "docker cp {{ vaultwarden_sso_authentik_data }}/vaultwarden-sso.yaml {{ vaultwarden_sso_authentik_container }}:/blueprints/custom-vaultwarden-sso.yaml" + - "docker exec {{ vaultwarden_sso_authentik_container }} ak apply_blueprint custom-vaultwarden-sso.yaml" + no_log: true + when: vaultwarden_sso_blueprint is changed diff --git a/templates/opt/authentik/vaultwarden-sso.yaml.j2 b/templates/opt/authentik/vaultwarden-sso.yaml.j2 new file mode 100644 index 0000000..b950212 --- /dev/null +++ b/templates/opt/authentik/vaultwarden-sso.yaml.j2 @@ -0,0 +1,52 @@ +# managed by ansible (cloud-vaultwarden); applied with `ak apply_blueprint` +version: 1 +metadata: + name: "{{ vaultwarden_sso_name }} SSO" +entries: + # vaultwarden only links an SSO login to an existing account for verified addresses + - model: authentik_providers_oauth2.scopemapping + id: email-verified + identifiers: + name: "{{ vaultwarden_sso_name }} OpenID 'email' (verified)" + attrs: + scope_name: email + description: Email address (verified) + expression: | + return { + "email": request.user.email, + "email_verified": True, + } + + - model: authentik_providers_oauth2.oauth2provider + id: provider + identifiers: + name: "{{ vaultwarden_sso_name }}" + attrs: + authorization_flow: !Find [authentik_flows.flow, [slug, {{ vaultwarden_sso_authentik_authorization_flow }}]] + invalidation_flow: !Find [authentik_flows.flow, [slug, {{ vaultwarden_sso_authentik_invalidation_flow }}]] + client_type: confidential + # newer authentik versions only allow explicitly listed grant types + grant_types: + - authorization_code + - refresh_token + client_id: "{{ vaultwarden_sso_client_id }}" + client_secret: "{{ vaultwarden_sso_client_secret }}" + redirect_uris: + - matching_mode: strict + url: "https://{{ vaultwarden_domain }}/identity/connect/oidc-signin" + signing_key: !Find [authentik_crypto.certificatekeypair, [name, "{{ vaultwarden_sso_authentik_signing_key }}"]] + sub_mode: hashed_user_id + property_mappings: + - !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-openid]] + - !KeyOf email-verified + - !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-profile]] + - !Find [authentik_providers_oauth2.scopemapping, [managed, goauthentik.io/providers/oauth2/scope-offline_access]] + + - model: authentik_core.application + identifiers: + slug: "{{ vaultwarden_sso_slug }}" + attrs: + name: "{{ vaultwarden_sso_name }}" + provider: !KeyOf provider + meta_launch_url: "https://{{ vaultwarden_domain }}/" + policy_engine_mode: any diff --git a/templates/opt/vaultwarden/.env.j2 b/templates/opt/vaultwarden/.env.j2 index 4581967..30fa979 100644 --- a/templates/opt/vaultwarden/.env.j2 +++ b/templates/opt/vaultwarden/.env.j2 @@ -19,6 +19,19 @@ ADMIN_TOKEN='{{ vaultwarden_admin_token }}' {% endif %} +### SSO ### +SSO_ENABLED={{ vaultwarden_sso_enabled | bool | lower }} +{% if vaultwarden_sso_enabled | bool %} +SSO_ONLY={{ vaultwarden_sso_only | bool | lower }} +SSO_SIGNUPS_MATCH_EMAIL={{ vaultwarden_sso_signups_match_email | bool | lower }} +SSO_AUTHORITY={{ vaultwarden_sso_authority }} +SSO_SCOPES="{{ vaultwarden_sso_scopes }}" +SSO_PKCE=true +SSO_CLIENT_ID={{ vaultwarden_sso_client_id }} +SSO_CLIENT_SECRET='{{ vaultwarden_sso_client_secret }}' +{% endif %} + + ### SMTP ### SMTP_HOST={{ vaultwarden_smtp_host }} SMTP_PORT={{ vaultwarden_smtp_port }}