Add support for MFA with Duo's Universal Prompt (#4637)

* Add initial working Duo Universal Prompt support.

* Add db schema and models for Duo 2FA state storage

* store duo states in the database and validate during authentication

* cleanup & comments

* bump state/nonce length

* replace stray use of TimeDelta

* more cleanup

* bind Duo oauth flow to device id, drop redundant device type handling

* drop redundant alphanum string generation code

* error handling cleanup

* directly use JWT_VALIDITY_SECS constant instead of copying it to DuoClient instances

* remove redundant explicit returns, rustfmt

* rearrange constants, update comments, error message

* override charset on duo state column to ascii for mysql

* Reduce twofactor_duo_ctx state/nonce column size in postgres and maria

* Add fixes suggested by clippy

* rustfmt

* Update to use the make_http_request

* Don't handle OrganizationDuo

* move Duo API endpoint fmt strings out of macros and into format! calls

* Add missing indentation

Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>

* remove redundant expiry check when purging Duo contexts

---------

Co-authored-by: BlackDex <black.dex@gmail.com>
Co-authored-by: Daniel García <dani-garcia@users.noreply.github.com>
This commit is contained in:
0x0fbc
2024-07-24 09:50:35 -05:00
committed by GitHub
parent de66e56b6c
commit b4b2701905
18 changed files with 719 additions and 15 deletions

View File

@ -53,6 +53,7 @@ mod mail;
mod ratelimit;
mod util;
use crate::api::core::two_factor::duo_oidc::purge_duo_contexts;
use crate::api::purge_auth_requests;
use crate::api::{WS_ANONYMOUS_SUBSCRIPTIONS, WS_USERS};
pub use config::CONFIG;
@ -626,6 +627,13 @@ fn schedule_jobs(pool: db::DbPool) {
}));
}
// Clean unused, expired Duo authentication contexts.
if !CONFIG.duo_context_purge_schedule().is_empty() && CONFIG._enable_duo() && !CONFIG.duo_use_iframe() {
sched.add(Job::new(CONFIG.duo_context_purge_schedule().parse().unwrap(), || {
runtime.spawn(purge_duo_contexts(pool.clone()));
}));
}
// Cleanup the event table of records x days old.
if CONFIG.org_events_enabled()
&& !CONFIG.event_cleanup_schedule().is_empty()