Skip to main content

Login MFA

OpenBao supports Multi-factor Authentication (MFA) for authenticating to an auth method using different authentication types. Login MFA is built on top of the Identity system of OpenBao.

MFA types

MFA in OpenBao 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 an OpenBao 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 OpenBao.

  • 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 to the API. The Okta username will be derived from the caller identity's alias.

  • Duo - If Duo 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 to the API. The Duo username will be derived from the caller identity's alias. Note that Duo could also be configured to use passcodes for authentication.

  • PingID - If PingID push is configured and enabled on a login path, the enrolled device of the user will receive a push notification to either approve or deny access to the API. The PingID username will be derived from the caller identity's alias.

Login MFA procedure

warning

NOTE: OpenBao's built-in Login MFA feature does not protect against brute forcing of TOTP passcodes by default. We recommend that per-client rate limits are applied to the relevant login and/or mfa paths (e.g. /sys/mfa/validate). External MFA methods (Duo, Ping and Okta) may already provide configurable rate limiting. Rate limiting of Login MFA paths are enforced by default.

Login MFA can be configured to secure further authenticating to an auth method. To enable login MFA, an MFA method needs to be configured. Please see Login MFA API for details on how to configure an MFA method. Once an MFA method is configured, an operator can configure an MFA enforcement using the returned unique MFA method ID. Please see Login MFA Enforcement API for details on how to configure an MFA enforcement config. MFA could be enforced for an entity, a group of entities, a specific auth method accessor, or an auth method type. A login request that matches any MFA enforcement restrictions is subject to further MFA validation, such as a one-time passcode, before being authenticated.

There are two ways to validate a login request that is subject to MFA validation.

Single-Phase login

In the Single-phase login, the required MFA information is embedded in a login request using the X-Vault-MFA header. In this case, the MFA validation is done as a part of the login request.

MFA credentials are retrieved from the X-Vault-MFA HTTP header. The format of the header is either mfa_method_id[:passcode] or mfa_method_id[:passcode=<passcode>], and one can use either of the above two formats. The item in the [] is optional. If there are multiple MFA methods that need to be validated, a user can pass in multiple X-Vault-MFA HTTP headers.

Sample request

$ curl \
--header "X-Vault-Token: ..." \
--header "X-Vault-MFA: d16fd3c2-50de-0b9b-eed3-0301dadeca10:695452" \
http://127.0.0.1:8200/v1/auth/userpass/login/alice

If an MFA method does not require a passcode, the login request MFA header only contains the method ID.

 $ curl \
--header "X-Vault-Token: ..." \
--header "X-Vault-MFA: d16fd3c2-50de-0b9b-eed3-0301dadeca10" \
http://127.0.0.1:8200/v1/auth/userpass/login/alice

An operator can configure a name for an MFA method. This name should be unique in the namespace in which the MFA method is configured. The MFA method name can be used in the MFA header.

$ curl \
--header "X-Vault-Token: ..." \
--header "X-Vault-MFA: sample_mfa_method_name:695452" \
http://127.0.0.1:8200/v1/auth/userpass/login/alice

In cases where the MFA method is configured in a specific namespace, the MFA method name should be prefixed with the namespace path. Below shows an example where an MFA method is configured in ns1.

$ curl \
--header "X-Vault-Token: ..." \
--header "X-Vault-MFA: ns1/sample_mfa_method_name:695452" \
http://127.0.0.1:8200/v1/auth/userpass/login/alice

Two-Phase login

The more conventional and prevalent MFA method is a two-request mechanism, also referred to as Two-phase Login MFA. In Two-phase login, the X-Vault-MFA header is not provided in the request. In this case, after sending a regular login request, the user receives an auth response in which MFA requirements are included. MFA requirements contain an MFA request ID which identifies the login request that needs validation. In addition, MFA requirements contain MFA constraints that determine which MFA types should be used to validate the request, the corresponding method IDs, and a boolean value showing whether the MFA method uses passcodes or not. MFA constraints form a nested map in MFA Requirement and represent all MFA enforcements that match a login request. While the example below is for the userpass login, note that this can affect the login response on any auth mount protected by MFA validation.

Sample Two-Phase login response

{
"request_id": "1044c151-13ea-1cf5-f6ed-000c42efd477",
"lease_id": "",
"lease_duration": 0,
"renewable": false,
"data": null,
"warnings": [
"A login request was issued that is subject to MFA validation. Please make sure to validate the login by sending another request to mfa/validate endpoint."
],
"auth": {
"client_token": "",
"accessor": "",
"policies": null,
"token_policies": null,
"identity_policies": null,
"metadata": null,
"orphan": false,
"entity_id": "",
"lease_duration": 0,
"renewable": false,
"mfa_requirement": {
"mfa_request_id": "d0c9eec7-6921-8cc0-be62-202b289ef163",
"mfa_constraints": {
"enforcementConfigUserpass": {
"any": [
{
"type": "totp",
"id": "820997b3-110e-c251-7e8b-ff4aa428a6e1",
"uses_passcode": true,
"name": "sample_mfa_method_name",
}
]
}
}
}
}
}

Note that the uses_passcode boolean value will always show true for TOTP, and false for Okta and PingID. For Duo method, the value can be configured as part of the method configuration, using the use_passcode parameter. Please see Duo API for details on how to configure the boolean value for Duo.

To validate the MFA restricted login request, the user sends a second request to the validate endpoint including the MFA request ID and MFA payload. MFA payload contains a map of methodIDs and their associated credentials. If the configured MFA methods, such as PingID, Okta, and Duo, do not require a passcode, the associated credentials will be a list with one empty string.

Sample payload

{
"mfa_request_id": "5879c74a-1418-1948-7be9-97b209d693a7",
"mfa_payload": {
"d16fd3c2-50de-0b9b-eed3-0301dadeca10": ["910201"]
}
}

If an MFA method is configured in a namespace, the MFA method name prefixed with the namespace path can be used in the validation payload.

{
"mfa_request_id": "5879c74a-1418-1948-7be9-97b209d693a7",
"mfa_payload": {
"ns1/sample_mfa_method_name": ["910201"]
}
}

Sample request

$ curl \
--header "X-Vault-Token: ..." \
--request POST \
--data @payload.json \
http://127.0.0.1:8200/v1/sys/mfa/validate

Sample CLI request

A user is also able to use the CLI write command to validate the login request.

$ bao write sys/mfa/validate -format=json @payload.json

Interactive CLI for login MFA

OpenBao supports an interactive way of authenticating to an auth method using CLI only if the login request is subject to a single MFA method validation. In this situation, if the MFA method is configured to use passcodes, after sending a regular login request, the user is prompted to insert the passcode. Upon successful MFA validation, a client token is returned. If the configured MFA methods, such as PingID, Okta, and Duo, do not require a passcode and have out of band mechanisms for verifying the extra factor, the user is notified to check their authenticator application. This alleviates a user from sending the second request separately to validate a login request. To disable the interactive login experience, a user needs to pass in the non-interactive flag to the login request.

$ bao write -non-interactive sys/mfa/validate -format=json @payload.json

TOTP passcode validation rate limit

Rate limiting of Login MFA paths are enforced by default. OpenBao allows for 5 consecutive failed TOTP passcode validations. This value can also be configured by adding max_validation_attempts to the TOTP configuration. If the number of consecutive failed TOTP passcode validation exceeds the configured value, the user needs to wait until a fresh TOTP passcode is available.