feat(users): Create terminate 2fa API (#4731)

This commit is contained in:
Riddhiagrawal001
2024-05-23 17:31:35 +05:30
committed by GitHub
parent ae77373b4c
commit 42e5ef1551
10 changed files with 115 additions and 7 deletions

View File

@ -24,8 +24,9 @@ use crate::{
routes::{app::ReqState, AppState},
services::{authentication as auth, authorization::roles, ApplicationResponse},
types::{domain, transformers::ForeignInto},
utils,
utils::{self, user::two_factor_auth as tfa_utils},
};
pub mod dashboard_metadata;
#[cfg(feature = "dummy_connector")]
pub mod sample_data;
@ -1631,7 +1632,7 @@ pub async fn begin_totp(
}));
}
let totp = utils::user::two_factor_auth::generate_default_totp(user_from_db.get_email(), None)?;
let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), None)?;
let recovery_codes = domain::RecoveryCodes::generate_new();
let key_store = user_from_db.get_or_create_key_store(&state).await?;
@ -1693,10 +1694,8 @@ pub async fn verify_totp(
.await?
.ok_or(UserErrors::InternalServerError)?;
let totp = utils::user::two_factor_auth::generate_default_totp(
user_from_db.get_email(),
Some(user_totp_secret),
)?;
let totp =
tfa_utils::generate_default_totp(user_from_db.get_email(), Some(user_totp_secret))?;
if totp
.generate_current()
@ -1739,7 +1738,7 @@ pub async fn generate_recovery_codes(
state: AppState,
user_token: auth::UserFromSinglePurposeToken,
) -> UserResponse<user_api::RecoveryCodes> {
if !utils::user::two_factor_auth::check_totp_in_redis(&state, &user_token.user_id).await? {
if !tfa_utils::check_totp_in_redis(&state, &user_token.user_id).await? {
return Err(UserErrors::TotpRequired.into());
}
@ -1766,3 +1765,55 @@ pub async fn generate_recovery_codes(
recovery_codes: recovery_codes.into_inner(),
}))
}
pub async fn terminate_two_factor_auth(
state: AppState,
user_token: auth::UserFromSinglePurposeToken,
skip_two_factor_auth: bool,
) -> UserResponse<user_api::TokenResponse> {
let user_from_db: domain::UserFromStorage = state
.store
.find_user_by_id(&user_token.user_id)
.await
.change_context(UserErrors::InternalServerError)?
.into();
if !skip_two_factor_auth {
if !tfa_utils::check_totp_in_redis(&state, &user_token.user_id).await?
&& !tfa_utils::check_recovery_code_in_redis(&state, &user_token.user_id).await?
{
return Err(UserErrors::TwoFactorAuthRequired.into());
}
if user_from_db.get_recovery_codes().is_none() {
return Err(UserErrors::TwoFactorAuthNotSetup.into());
}
if user_from_db.get_totp_status() != TotpStatus::Set {
state
.store
.update_user_by_user_id(
user_from_db.get_user_id(),
storage_user::UserUpdate::TotpUpdate {
totp_status: Some(TotpStatus::Set),
totp_secret: None,
totp_recovery_codes: None,
},
)
.await
.change_context(UserErrors::InternalServerError)?;
}
}
let current_flow = domain::CurrentFlow::new(user_token.origin, domain::SPTFlow::TOTP.into())?;
let next_flow = current_flow.next(user_from_db, &state).await?;
let token = next_flow.get_token(&state).await?;
auth::cookies::set_cookie_response(
user_api::TokenResponse {
token: token.clone(),
token_type: next_flow.get_flow().into(),
},
token,
)
}