From a728523c5e0d59b402309f439337bd4c53c986f2 Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Sat, 28 Mar 2026 04:20:00 +0100 Subject: [PATCH 1/8] Add documentation for second-factor authentication (2FA) Document the implementation and usage of second-factor authentication (2FA) in Wire, including prerequisites, enabling/disabling instructions, and troubleshooting tips. --- .../second-factor-authentication.md | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 src/understand/second-factor-authentication.md diff --git a/src/understand/second-factor-authentication.md b/src/understand/second-factor-authentication.md new file mode 100644 index 0000000..4632db3 --- /dev/null +++ b/src/understand/second-factor-authentication.md @@ -0,0 +1,140 @@ +# Second-factor authentication (2FA) + +## Overview + +Wire can require team users to enter a 6-digit verification code (sent to their email) when performing sensitive operations. It's controlled by the `sndFactorPasswordChallenge` [feature flag](team-feature-settings.md) in galley, and it's off by default. + +## What operations require 2FA + +When enabled, a verification code is required for: + +- **Login** (after entering the correct password) +- **Adding a new device/client** (logging in from a new browser or device) +- **Creating [SCIM](../developer/reference/provisioning/scim-token.md) provisioning tokens** +- **Deleting a team** + +Personal (non-team) users aren't affected, the `2FA` feature is only for team accounts. + +[SSO](single-sign-on/README.md) users aren't affected either since they authenticate through their identity provider (idP) instead of Wire's password flow. + +If you want 2FA for SSO users, you need to set it up in your idP if it supports it. + +## Prerequisites + +2FA sends codes by email, so you need a working email delivery path. That's either: + +- A production SMTP relay configured as a smarthost +- The [`demo-smtp`](../how-to/install/troubleshooting.md) chart for testing (emails stay in the pod's local mail queue, never actually delivered) + +If email delivery is broken, users won't be able to log in once 2FA is on, because they'll never get their code, so it's critical to get email sending working first. + +## Enabling 2FA + +Add this to `values/wire-server/values.yaml` under galley's [feature flags](team-feature-settings.md). If you're not familiar with helm values overrides, read [Overriding helm configuration settings](helm.md#overriding-helm-configuration-settings) first. + +```yaml +galley: + config: + settings: + featureFlags: + sndFactorPasswordChallenge: + defaults: + status: enabled + lockStatus: locked +``` + +Then helm upgrade: + +```sh +helm upgrade --install --wait wire-server ./charts/wire-server \ + --values ./values/wire-server/values.yaml \ + --values ./values/wire-server/secrets.yaml +``` + +Galley pods will restart with the new config. For the full helm deployment process, see [Installing wire-server using Helm](../how-to/install/helm-prod.md). + +### Lock status + +The `lockStatus` setting controls whether team admins can change this setting (`2FA` enabled or not) on a per-team basis: + +| Value | Behavior | +|------------|----------------------------------------------------------------------------------------| +| `locked` | Team admins can't change it. Your default applies to all teams. | +| `unlocked` | Team admins can toggle 2FA for their own team via the team management API. | + +For most setups you'll want `locked`, since 2FA is typically meant to be enforced across the organization. + +## Disabling 2FA + +Set status to `disabled`: + +```yaml +galley: + config: + settings: + featureFlags: + sndFactorPasswordChallenge: + defaults: + status: disabled + lockStatus: locked +``` + +Or just remove the `sndFactorPasswordChallenge` section, it defaults to disabled. + +## Rate limiting + +After 3 wrong code attempts, the code gets invalidated. New code requests are rate-limited, default is 5 minutes between requests. See also [Rate limiting of code generation requests](team-feature-settings.md#rate-limiting-of-code-generation-requests) for the full details. + +You can configure the delay in brig: + +```yaml +brig: + config: + optSettings: + set2FACodeGenerationDelaySecs: 300 +``` + +Value is in seconds. 300 (5 minutes) is the default and works fine for most cases. + +## Verifying it works + +Check galley's config to make sure the flag is there: + +```sh +kubectl get configmap galley -o yaml | grep -A4 sndFactorPasswordChallenge +``` + +You should see `status: enabled`. + +To actually test it: log in with a team user account. After the password, the webapp should ask for a verification code. If you're not sure how to create a team user, see [Investigative tasks](../how-to/administrate/users.md#create-a-team-using-the-scim-api). + +## Getting verification codes from demo-smtp + +If you're using [`demo-smtp`](../how-to/install/troubleshooting.md) (which doesn't deliver to real mailboxes), you can retrieve the code directly from its mail queue: + +```sh +# Find the pod +kubectl get pods -l app=demo-smtp + +# Get the code from the latest email +kubectl exec -- sh -c \ + 'ls -t /var/spool/exim4/input/*-D | head -1 | xargs grep X-Zeta-Code' +``` + +The `X-Zeta-Code` header has the 6-digit code. + +This is more fully documented in the [`troubleshooting page`](../how-to/install/troubleshooting.md) + +## Troubleshooting + +**Users can't log in after enabling 2FA**: Most likely email delivery is broken. If using `demo-smtp`, check that `RELAY_NETWORKS` includes the pod network CIDR (usually `10.233.0.0/16` or whatever your cluster uses). Look at brig logs: + +```sh +kubectl logs -l app=brig --tail=50 | grep -i smtp +``` + +**Code never arrives**: Look in the demo-smtp mail queue (see section above) to confirm the email was generated. With a real SMTP relay, check that relay's logs. Common issue: SPF/DKIM/DMARC rejection by the recipient's mail server. + +**"Error 6" in the webapp**: Generic client error, usually a 500 from brig. Check the browser's «console» for errors. Also check brig logs for the real error. Most common cause is SMTP delivery failure. + +For general debugging tips, see [Triaging Issues](../how-to/support/triaging_issues.md) and [Collecting information with the Web Inspector](../how-to/support/inspector.md). From 00d4e9b4b4398d8eb93d896f4d99c45936e7a89f Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Sat, 28 Mar 2026 04:22:17 +0100 Subject: [PATCH 2/8] Add Second-factor authentication section to mkdocs --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/mkdocs.yml b/mkdocs.yml index 971fd5e..a2ddab9 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,6 +72,7 @@ nav: - Federation: understand/configure-federation.md - Installing and setting up Legal Hold: understand/legalhold.md - Messaging Layer Security (MLS): understand/mls.md + - Second-factor authentication (2FA): understand/second-factor-authentication.md - User Searchability: understand/searchability.md - Server and team feature settings: understand/team-feature-settings.md - Developer Notes: From 4c7cbc98d92fbd3830ca6fef0f907bf245809383 Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Sat, 28 Mar 2026 04:23:43 +0100 Subject: [PATCH 3/8] Update section titles in README.md --- src/understand/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/understand/README.md b/src/understand/README.md index 22a9613..5e1ef0c 100644 --- a/src/understand/README.md +++ b/src/understand/README.md @@ -91,13 +91,16 @@ ## 13. Security and Messaging - [Messaging Layer Security (MLS)](mls.md) -## 14. User Searchability +## 14. Second-factor Authentication +- [Second-factor authentication (2FA)](second-factor-authentication.md) + +## 15. User Searchability - [User Searchability](searchability.md) - [Searching users on the same backend](searchability.md#searching-users-on-the-same-backend) - [Searching users on another federated backend](searchability.md#searching-users-on-another-federated-backend) - [Changing the settings for a given team](searchability.md#changing-the-settings-for-a-given-team) -## 15. Server and Team Settings +## 16. Server and Team Settings - [Server and team feature settings](team-feature-settings.md) - [2nd factor password challenge](team-feature-settings.md#nd-factor-password-challenge) - [Rate limiting of code generation requests](team-feature-settings.md#rate-limiting-of-code-generation-requests) From 25023cc7baeef7d7e61ee9ad2fecebef0e11c82d Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Wed, 1 Apr 2026 01:50:28 +0200 Subject: [PATCH 4/8] Rename section for second-factor authentication Updated section title from 'Second-factor Authentication' to 'Email OTP' in README. --- src/understand/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/understand/README.md b/src/understand/README.md index 5e1ef0c..b8bf963 100644 --- a/src/understand/README.md +++ b/src/understand/README.md @@ -91,8 +91,8 @@ ## 13. Security and Messaging - [Messaging Layer Security (MLS)](mls.md) -## 14. Second-factor Authentication -- [Second-factor authentication (2FA)](second-factor-authentication.md) +## 14. Email OTP +- [Email OTP](second-factor-authentication.md) ## 15. User Searchability - [User Searchability](searchability.md) From 41f72463228ecb1750a8923659b89589aa1ed8ad Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Wed, 1 Apr 2026 01:51:36 +0200 Subject: [PATCH 5/8] Rename the file to email otp --- src/understand/{second-factor-authentication.md => email-otp.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/understand/{second-factor-authentication.md => email-otp.md} (100%) diff --git a/src/understand/second-factor-authentication.md b/src/understand/email-otp.md similarity index 100% rename from src/understand/second-factor-authentication.md rename to src/understand/email-otp.md From 164a049e102e2cf9190346ef19de653e008b715a Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Wed, 1 Apr 2026 01:54:32 +0200 Subject: [PATCH 6/8] Rename 2FA to Email OTP in documentation --- src/understand/email-otp.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/understand/email-otp.md b/src/understand/email-otp.md index 4632db3..5d2c106 100644 --- a/src/understand/email-otp.md +++ b/src/understand/email-otp.md @@ -1,10 +1,10 @@ -# Second-factor authentication (2FA) +# Email OTP ## Overview Wire can require team users to enter a 6-digit verification code (sent to their email) when performing sensitive operations. It's controlled by the `sndFactorPasswordChallenge` [feature flag](team-feature-settings.md) in galley, and it's off by default. -## What operations require 2FA +## What operations require OTP When enabled, a verification code is required for: @@ -13,22 +13,22 @@ When enabled, a verification code is required for: - **Creating [SCIM](../developer/reference/provisioning/scim-token.md) provisioning tokens** - **Deleting a team** -Personal (non-team) users aren't affected, the `2FA` feature is only for team accounts. +Personal (non-team) users aren't affected, the `Email OTP` feature is only for team accounts. [SSO](single-sign-on/README.md) users aren't affected either since they authenticate through their identity provider (idP) instead of Wire's password flow. -If you want 2FA for SSO users, you need to set it up in your idP if it supports it. +If you want `Email OTP` for SSO users, you need to set it up in your idP if it supports it. ## Prerequisites -2FA sends codes by email, so you need a working email delivery path. That's either: +OTP sends codes by email, so you need a working email delivery path. That's either: - A production SMTP relay configured as a smarthost - The [`demo-smtp`](../how-to/install/troubleshooting.md) chart for testing (emails stay in the pod's local mail queue, never actually delivered) -If email delivery is broken, users won't be able to log in once 2FA is on, because they'll never get their code, so it's critical to get email sending working first. +If email delivery is broken, users won't be able to log in once `Email OTP` is on, because they'll never get their code, so it's critical to get email sending working first. -## Enabling 2FA +## Enabling Email OTP Add this to `values/wire-server/values.yaml` under galley's [feature flags](team-feature-settings.md). If you're not familiar with helm values overrides, read [Overriding helm configuration settings](helm.md#overriding-helm-configuration-settings) first. @@ -55,16 +55,16 @@ Galley pods will restart with the new config. For the full helm deployment proce ### Lock status -The `lockStatus` setting controls whether team admins can change this setting (`2FA` enabled or not) on a per-team basis: +The `lockStatus` setting controls whether team admins can change this setting (`Email OTP` enabled or not) on a per-team basis: | Value | Behavior | |------------|----------------------------------------------------------------------------------------| | `locked` | Team admins can't change it. Your default applies to all teams. | -| `unlocked` | Team admins can toggle 2FA for their own team via the team management API. | +| `unlocked` | Team admins can toggle `Email OTP` for their own team via the team management API. | -For most setups you'll want `locked`, since 2FA is typically meant to be enforced across the organization. +For most setups you'll want `locked`, since `Email OTP` is typically meant to be enforced across the organization. -## Disabling 2FA +## Disabling Email OTP Set status to `disabled`: @@ -127,7 +127,7 @@ This is more fully documented in the [`troubleshooting page`](../how-to/install/ ## Troubleshooting -**Users can't log in after enabling 2FA**: Most likely email delivery is broken. If using `demo-smtp`, check that `RELAY_NETWORKS` includes the pod network CIDR (usually `10.233.0.0/16` or whatever your cluster uses). Look at brig logs: +**Users can't log in after enabling Email OTP**: Most likely email delivery is broken. If using `demo-smtp`, check that `RELAY_NETWORKS` includes the pod network CIDR (usually `10.233.0.0/16` or whatever your cluster uses). Look at brig logs: ```sh kubectl logs -l app=brig --tail=50 | grep -i smtp From 359c9e59f026c070a7423a31f2eb0abd47dd54b6 Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Wed, 1 Apr 2026 01:55:04 +0200 Subject: [PATCH 7/8] Fix link for Email OTP in README --- src/understand/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/understand/README.md b/src/understand/README.md index b8bf963..b09957e 100644 --- a/src/understand/README.md +++ b/src/understand/README.md @@ -92,7 +92,7 @@ - [Messaging Layer Security (MLS)](mls.md) ## 14. Email OTP -- [Email OTP](second-factor-authentication.md) +- [Email OTP](email-otp.md) ## 15. User Searchability - [User Searchability](searchability.md) From 7e2a2dd44ee6ef8c50603b38349c9e99e64d596a Mon Sep 17 00:00:00 2001 From: Arthur Wolf Date: Wed, 1 Apr 2026 01:55:52 +0200 Subject: [PATCH 8/8] Replace 2FA with Email OTP in mkdocs.yml --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index a2ddab9..84f886e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -72,7 +72,7 @@ nav: - Federation: understand/configure-federation.md - Installing and setting up Legal Hold: understand/legalhold.md - Messaging Layer Security (MLS): understand/mls.md - - Second-factor authentication (2FA): understand/second-factor-authentication.md + - Email OTP: understand/email-otp.md - User Searchability: understand/searchability.md - Server and team feature settings: understand/team-feature-settings.md - Developer Notes: