mirror of
https://github.com/dani-garcia/vaultwarden.git
synced 2026-03-12 01:45:56 -05:00
[PR #4637] [MERGED] Add support for MFA with Duo's Universal Prompt #7104
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/dani-garcia/vaultwarden/pull/4637
Author: @0x0fbc
Created: 6/11/2024
Status: ✅ Merged
Merged: 7/24/2024
Merged by: @dani-garcia
Base:
main← Head:feature/duo_universal📝 Commits (10+)
849ce1eAdd initial working Duo Universal Prompt support.6f86749Add db schema and models for Duo 2FA state storage36f90cdstore duo states in the database and validate during authentication328c4a3cleanup & comments41f94e2bump state/nonce length90b73c6replace stray use of TimeDeltaf489930more cleanup6f06fa9bind Duo oauth flow to device id, drop redundant device type handling4df7fcfdrop redundant alphanum string generation codee7a058cerror handling cleanup📊 Changes
18 files changed (+720 additions, -16 deletions)
View changed files
📝
.env.template(+13 -3)➕
migrations/mysql/2024-06-05-131359_add_2fa_duo_store/down.sql(+1 -0)➕
migrations/mysql/2024-06-05-131359_add_2fa_duo_store/up.sql(+8 -0)➕
migrations/postgresql/2024-06-05-131359_add_2fa_duo_store/down.sql(+1 -0)➕
migrations/postgresql/2024-06-05-131359_add_2fa_duo_store/up.sql(+8 -0)➕
migrations/sqlite/2024-06-05-131359_add_2fa_duo_store/down.sql(+1 -0)➕
migrations/sqlite/2024-06-05-131359_add_2fa_duo_store/up.sql(+8 -0)📝
src/api/core/two_factor/duo.rs(+1 -1)➕
src/api/core/two_factor/duo_oidc.rs(+500 -0)📝
src/api/core/two_factor/mod.rs(+1 -0)📝
src/api/identity.rs(+52 -11)📝
src/config.rs(+5 -1)📝
src/db/models/mod.rs(+2 -0)➕
src/db/models/two_factor_duo_context.rs(+84 -0)📝
src/db/schemas/mysql/schema.rs(+9 -0)📝
src/db/schemas/postgresql/schema.rs(+9 -0)📝
src/db/schemas/sqlite/schema.rs(+9 -0)📝
src/main.rs(+8 -0)📄 Description
Overview
This adds support for MFA using Duo's "Universal Prompt".
On March 30th, 2024, the Duo MFA integration that Vaultwarden uses, the 'Traditional Prompt' was end-of-lifed. While Duo's API continues to allow the traditional prompt to be used in some cases, it is entirely unsupported, and it will eventually stop working. Some Vaultwarden users have already begun reporting that their Duo API keys are no longer functional in Vaultwarden. Bitwarden introduced Universal Prompt support in release 2024.2.3 on March 5th.
Duo's Universal Prompt uses the OIDC Authorization Code flow. This flow requires us to pack information about the authentication we want to be prompted for MFA into an authorization request (a JWT signed with a secret key provided by Duo) and send the user to their service, where MFA is performed. The user is then returned to our service with a code that we use to call Duo's API and obtain the result of the MFA. Once we validate the information passed back by the user's client and returned by Duo's service, we can log the user in.
Detailed documentation is located at https://duo.com/docs/oauthapi
The web vault handles receiving the redirection from Duo. It has a 'connector' page responsible for communicating the authorization code back to the user's true client so it can be provided in a call to Vaultwarden's API.
Major additions/changes
Specific Review Items
Beyond what you'd normally check, I'd like to highlight a few decisions I made that you should probably consider in your review.
device_identifierreported by the client, and hashed to produce the OIDC nonce sent to Duo in the authorization request. Then, thedevice_identifierreported by the user's client when providing the authorization code is hashed with the saved nonce, and the resulting hash is compared to the OIDC nonce Duo reports when we call their API for the MFA result.get_duo_keys_emailfunction, which fetches the Duo keys from the database/config for a given user, I set its visibility topub(crate)and re-used it.Testing
Tested on the following clients; everything is working well:
The only major client issue I found was with the unpackaged AppImage Linux desktop client. When authenticating users on desktop clients, the connector in the web vault opens a
bitwarden://link, which my system refused to use the AppImage to open. It looks like the AppImage client either doesn't or can't register itself as thex-scheme-handlerforbitwarden, preventing the redirect connector from handing off to the client. It worked fine with the Flatpak packaged Bitwarden client, so I'm chalking it up to my not configuring the AppImage client correctly.There is also a known issue upstream in the web vault where the redirect connector shows 'successful authentication', does not automatically close, and the JS 'close' button does not work. See https://github.com/bitwarden/clients/issues/8554
I also tested this while running PostgreSQL and MariaDB using the versions packaged in Debian 12; no issues.
Fixes #4529
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.