diff --git a/content/vault/v1.18.x/content/docs/auth/login-mfa/index.mdx b/content/vault/v1.18.x/content/docs/auth/login-mfa/index.mdx
index dfff6f3dc4..d6d0798f9f 100644
--- a/content/vault/v1.18.x/content/docs/auth/login-mfa/index.mdx
+++ b/content/vault/v1.18.x/content/docs/auth/login-mfa/index.mdx
@@ -254,7 +254,7 @@ $ vault write identity/mfa/method/totp \
digits=6
```
-Using the TOTP `method_id` and an `entity_id` from after a sucessful MFA login. Use these to generate a QR code.
+Vault generates an `entity_id` for users after a successful login. Use the TOTP `method_id` and the `entity_id` of the target user to generate a QR code.
```shell-session
$ vault write -field=barcode \
diff --git a/content/vault/v1.19.x/content/docs/auth/login-mfa/index.mdx b/content/vault/v1.19.x/content/docs/auth/login-mfa/index.mdx
index 8f71cbb7d2..683ad116bd 100644
--- a/content/vault/v1.19.x/content/docs/auth/login-mfa/index.mdx
+++ b/content/vault/v1.19.x/content/docs/auth/login-mfa/index.mdx
@@ -258,7 +258,7 @@ $ vault write identity/mfa/method/totp \
digits=6
```
-Using the TOTP `method_id` and an `entity_id` from after a sucessful MFA login. Use these to generate a QR code.
+Vault generates an `entity_id` for users after a successful login. Use the TOTP `method_id` and the `entity_id` of the target user to generate a QR code.
```shell-session
$ vault write -field=barcode \
diff --git a/content/vault/v1.20.x/content/docs/auth/login-mfa/index.mdx b/content/vault/v1.20.x/content/docs/auth/login-mfa/index.mdx
index 8f71cbb7d2..683ad116bd 100644
--- a/content/vault/v1.20.x/content/docs/auth/login-mfa/index.mdx
+++ b/content/vault/v1.20.x/content/docs/auth/login-mfa/index.mdx
@@ -258,7 +258,7 @@ $ vault write identity/mfa/method/totp \
digits=6
```
-Using the TOTP `method_id` and an `entity_id` from after a sucessful MFA login. Use these to generate a QR code.
+Vault generates an `entity_id` for users after a successful login. Use the TOTP `method_id` and the `entity_id` of the target user to generate a QR code.
```shell-session
$ vault write -field=barcode \
diff --git a/content/vault/v1.21.x (rc)/content/api-docs/secret/identity/mfa/totp.mdx b/content/vault/v1.21.x (rc)/content/api-docs/secret/identity/mfa/totp.mdx
index 411946c598..244c620dbc 100644
--- a/content/vault/v1.21.x (rc)/content/api-docs/secret/identity/mfa/totp.mdx
+++ b/content/vault/v1.21.x (rc)/content/api-docs/secret/identity/mfa/totp.mdx
@@ -13,7 +13,7 @@ This endpoint creates an MFA method of type TOTP.
|:-------|:----------------------------|
| `POST` | `/identity/mfa/method/totp` |
-### Parameters
+### Request parameters
- `method_name` `(string)` - The unique name identifier for this MFA method. Supported from Vault 1.13.0.
@@ -33,6 +33,9 @@ This endpoint creates an MFA method of type TOTP.
- `max_validation_attempts` `(int: 5)` - The maximum number of consecutive failed validation attempts.
+- `enable_self_enrollment` `(bool: false)` - When enabled, allows users to setup TOTP for their account by generating
+ a TOTP secret (QR code) during login if they do not already have one.
+
### Sample payload
```json
@@ -59,11 +62,13 @@ This endpoint updates the configuration of an MFA method of type TOTP.
|:-------|:---------------------------------------|
| `POST` | `/identity/mfa/method/totp/:method_id` |
-### Parameters
+### Path parameters
- `method_id` `(string: )` - UUID of the MFA method.
-- and all of the parameters documented under the preceding "Create" endpoint.
+### Request parameters
+
+All of the parameters documented under the preceding ["Create"](#create-totp-mfa-method) endpoint.
### Sample payload
@@ -88,7 +93,7 @@ ID.
|:-------|:---------------------------------------|
| `GET` | `/identity/mfa/method/totp/:method_id` |
-### Parameters
+### Path parameters
- `method_id` `(string: )` – UUID of the MFA method.
@@ -129,7 +134,7 @@ by a [login enforcement](/vault/api-docs/secret/identity/mfa/login-enforcement).
|:---------|:---------------------------------------|
| `DELETE` | `/identity/mfa/method/totp/:method_id` |
-### Parameters
+### Path parameters
- `method_id` `(string: )` - UUID of the MFA method.
@@ -182,7 +187,7 @@ method ID.
|:-------|:-------------------------------------|
| `POST` | `/identity/mfa/method/totp/generate` |
-### Parameters
+### Request parameters
- `method_id` `(string: )` - UUID of the MFA method.
@@ -225,7 +230,7 @@ the `admin-generate` API stores the generated secret on the given entity ID.
|:-------|:-------------------------------------------|
| `POST` | `/identity/mfa/method/totp/admin-generate` |
-### Parameters
+### Request parameters
- `method_id` `(string: )` - UUID of the MFA method.
@@ -275,7 +280,7 @@ secret.
|:-------|:------------------------------------------|
| `POST` | `/identity/mfa/method/totp/admin-destroy` |
-### Parameters
+### Request parameters
- `method_id` `(string: )` - UUID of the MFA method.
@@ -300,3 +305,51 @@ $ curl \
--data @payload.json \
http://127.0.0.1:8200/v1/identity/mfa/method/totp/admin-destroy
```
+
+## Self-enroll in TOTP MFA
+
+The self-enroll endpoint lets users setup TOTP MFA by generating a TOTP
+secret (QR code) during login if they do not already have one. To use
+self-enrollment you must set [`enable_self_enrollment`](./totp#enable_self_enrollment) to `true` for the TOTP MFA
+method.
+
+| Method | Path |
+|:-------|:----------------------------------------|
+| `POST` | `/identity/mfa/method/totp/self-enroll` |
+
+### Request parameters
+
+- `mfa_request_id` `(string: )` - The unique identifier of an MFA
+ requirement in the authentication response of a login request.
+
+- `mfa_method_id` `(string: )` - UUID of the MFA method.
+
+### Sample payload
+
+```json
+{
+ "mfa_request_id": "5879c74a-1418-1948-7be9-97b209d693a7",
+ "mfa_method_id": "4746fb81-028c-cd4e-026b-7dd18fe4c2f4"
+}
+```
+
+### Sample request
+
+```shell-session
+$ curl \
+ --header "X-Vault-Token: ..." \
+ --request POST \
+ --data @payload.json \
+ http://127.0.0.1:8200/v1/identity/mfa/method/totp/self-enroll
+```
+
+### Sample response
+
+```json
+{
+ "data": {
+ "barcode": "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",
+ "url": "otpauth://totp/vault:4746fb81-028c-cd4e-026b-7dd18fe4c2f4?algorithm=SHA1&digits=6&issuer=vault&period=30&secret=6HQ4RZ7GM6MMLRKVDCI23LXNZF7UDZ2U"
+ }
+}
+```
\ No newline at end of file
diff --git a/content/vault/v1.21.x (rc)/content/docs/auth/login-mfa/index.mdx b/content/vault/v1.21.x (rc)/content/docs/auth/login-mfa/index.mdx
index 8f71cbb7d2..3559627680 100644
--- a/content/vault/v1.21.x (rc)/content/docs/auth/login-mfa/index.mdx
+++ b/content/vault/v1.21.x (rc)/content/docs/auth/login-mfa/index.mdx
@@ -26,7 +26,8 @@ MFA in Vault includes the following login types:
- `Time-based One-time Password (TOTP)` - If configured and enabled on a login path,
this would require a TOTP passcode along with a Vault token to be presented
while invoking the API login request. The passcode will be validated against the
- TOTP key present in the caller's identify in Vault.
+ TOTP key present in the caller's identify in Vault.
+ TOTP supports [self-enrollment](/vault/docs/enterprise/mfa#self-enroll-mfa-totp).
- `Okta` - If Okta push is configured and enabled on a login path, then the enrolled
device of the user will receive a push notification to either approve or deny access
@@ -246,6 +247,29 @@ The following table lists the known authenticator applications and encryption al
| Google Authenticator mobile app | ✅ | ✅ |
| Yubico Authenticator for Desktop | ✅ | ✅ |
+#### Option 1: Configure TOTP for self-enrollment
+
+To make the Vault GUI prompt users with a QR code if they do not have TOTP setup for their account:
+
+1. Set `enable_self_enrollment` to `true` in the TOTP method configuration.
+
+ ```shell-session
+ $ vault write identity/mfa/method/totp \
+ generate=true \
+ issuer=Vault \
+ period=30 \
+ key_size=30 \
+ algorithm=SHA256 \
+ digits=6 \
+ enable_self_enrollment=true
+ ```
+
+1. Ensure you only have one MFA login enforcement enabled. You can associate
+ multiple MFA methods with the enforcement rule, but you can only have one
+ rule active at a time to allow self-enrollment.
+
+#### Option 2: Configure TOTP for admin-managed enrollment
+
Configure the Login MFA TOTP method and note down the resulting `method_id`.
```shell-session
@@ -258,7 +282,7 @@ $ vault write identity/mfa/method/totp \
digits=6
```
-Using the TOTP `method_id` and an `entity_id` from after a sucessful MFA login. Use these to generate a QR code.
+Vault generates an `entity_id` for users after a successful login. Use the TOTP `method_id` and the `entity_id` of the target user to generate a QR code.
```shell-session
$ vault write -field=barcode \
diff --git a/content/vault/v1.21.x (rc)/content/docs/enterprise/mfa/index.mdx b/content/vault/v1.21.x (rc)/content/docs/enterprise/mfa/index.mdx
index b0a5cc8055..77428f72a2 100644
--- a/content/vault/v1.21.x (rc)/content/docs/enterprise/mfa/index.mdx
+++ b/content/vault/v1.21.x (rc)/content/docs/enterprise/mfa/index.mdx
@@ -20,7 +20,7 @@ MFA in Vault can be of the following types.
- **Time-based One-time Password (TOTP)** - If configured and enabled on a path,
this would require a TOTP passcode along with Vault token, to be presented
while invoking the API request. The passcode will be validated against the
- TOTP key present in the identity of the caller in Vault.
+ TOTP key present in the identity of the caller in Vault. TOTP supports [self-enrollment](#self-enroll-mfa-totp).
- **Okta** - If Okta push is configured and enabled on a path, then the enrolled
device of the user will get a push notification to approve or deny the access
@@ -43,6 +43,19 @@ MFA methods are globally managed within the `System Backend` using the HTTP API.
Please see [MFA API](/vault/api-docs/system/mfa) for details on how to configure an MFA
method.
+## Self-enroll MFA TOTP
+
+The TOTP method supports self-enrollment so users can generate their own QR codes without admin assistance.
+
+```text
+$ vault write sys/mfa/method/totp/my_self_enroll_totp \
+ issuer=Vault \
+ period=30 \
+ key_size=30 \
+ algorithm=SHA256 \
+ enable_self_enrollment=true
+```
+
## MFA methods in policies
MFA requirements on paths are specified as `mfa_methods` along with other ACL
diff --git a/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/all.mdx b/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/all.mdx
index fa00634e3d..c0f3c952fa 100644
--- a/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/all.mdx
+++ b/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/all.mdx
@@ -602,6 +602,8 @@ alphabetic order by name.
@include 'telemetry-metrics/vault/replication/rpc/client/persist_alias.mdx'
+@include 'telemetry-metrics/vault/replication/rpc/client/persist_pending_login_mfa_secret.mdx'
+
@include 'telemetry-metrics/vault/replication/rpc/client/register_auth.mdx'
@include 'telemetry-metrics/vault/replication/rpc/client/register_lease.mdx'
diff --git a/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/availability.mdx b/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/availability.mdx
index 4ee44d435b..102bd352cb 100644
--- a/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/availability.mdx
+++ b/content/vault/v1.21.x (rc)/content/docs/internals/telemetry/metrics/availability.mdx
@@ -101,6 +101,8 @@ your Vault instance. Enterprise installations also include
@include 'telemetry-metrics/vault/replication/rpc/client/persist_alias.mdx'
+@include 'telemetry-metrics/vault/replication/rpc/client/persist_pending_login_mfa_secret.mdx'
+
@include 'telemetry-metrics/vault/replication/rpc/client/register_auth.mdx'
@include 'telemetry-metrics/vault/replication/rpc/client/register_lease.mdx'
diff --git a/content/vault/v1.21.x (rc)/content/partials/telemetry-metrics/vault/replication/rpc/client/persist_pending_login_mfa_secret.mdx b/content/vault/v1.21.x (rc)/content/partials/telemetry-metrics/vault/replication/rpc/client/persist_pending_login_mfa_secret.mdx
new file mode 100644
index 0000000000..d397b5a87d
--- /dev/null
+++ b/content/vault/v1.21.x (rc)/content/partials/telemetry-metrics/vault/replication/rpc/client/persist_pending_login_mfa_secret.mdx
@@ -0,0 +1,5 @@
+### vault.replication.rpc.client.persist_pending_login_mfa_secret ((#vault-replication-rpc-client-persist_pending_login_mfa_secret))
+
+Metric type | Value | Description
+----------- | ----- | -----------
+summary | ms | Time required by the client to persist the pending login MFA TOTP secret
\ No newline at end of file
diff --git a/content/vault/v1.21.x (rc)/content/partials/telemetry-metrics/vault/replication/rpc/server/persist_pending_login_mfa_secret.mdx b/content/vault/v1.21.x (rc)/content/partials/telemetry-metrics/vault/replication/rpc/server/persist_pending_login_mfa_secret.mdx
new file mode 100644
index 0000000000..a400f56864
--- /dev/null
+++ b/content/vault/v1.21.x (rc)/content/partials/telemetry-metrics/vault/replication/rpc/server/persist_pending_login_mfa_secret.mdx
@@ -0,0 +1,5 @@
+### vault.replication.rpc.server.persist_pending_login_mfa_secret ((#vault-replication-rpc-server-persist_pending_login_mfa_secret))
+
+Metric type | Value | Description
+----------- | ----- | -----------
+summary | ms | Time required by the server to persist the pending login MFA TOTP secret
\ No newline at end of file