feat(users): add support to reset totp (#4821)

This commit is contained in:
Apoorv Dixit
2024-05-30 16:22:26 +05:30
committed by GitHub
parent 93d61d1053
commit aca6ad1bd1
5 changed files with 50 additions and 0 deletions

View File

@ -1634,7 +1634,39 @@ pub async fn begin_totp(
let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), None)?; let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), None)?;
let secret = totp.get_secret_base32().into(); let secret = totp.get_secret_base32().into();
tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?;
Ok(ApplicationResponse::Json(user_api::BeginTotpResponse {
secret: Some(user_api::TotpSecret {
secret,
totp_url: totp.get_url().into(),
}),
}))
}
pub async fn reset_totp(
state: AppState,
user_token: auth::UserFromToken,
) -> UserResponse<user_api::BeginTotpResponse> {
let user_from_db: domain::UserFromStorage = state
.store
.find_user_by_id(&user_token.user_id)
.await
.change_context(UserErrors::InternalServerError)?
.into();
if user_from_db.get_totp_status() != TotpStatus::Set {
return Err(UserErrors::TotpNotSetup.into());
}
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());
}
let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), None)?;
let secret = totp.get_secret_base32().into();
tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?; tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?;
Ok(ApplicationResponse::Json(user_api::BeginTotpResponse { Ok(ApplicationResponse::Json(user_api::BeginTotpResponse {

View File

@ -1218,6 +1218,7 @@ impl User {
.service( .service(
web::scope("/totp") web::scope("/totp")
.service(web::resource("/begin").route(web::get().to(totp_begin))) .service(web::resource("/begin").route(web::get().to(totp_begin)))
.service(web::resource("/reset").route(web::get().to(totp_reset)))
.service( .service(
web::resource("/verify") web::resource("/verify")
.route(web::post().to(totp_verify)) .route(web::post().to(totp_verify))

View File

@ -214,6 +214,7 @@ impl From<Flow> for ApiIdentifier {
| Flow::VerifyEmailRequest | Flow::VerifyEmailRequest
| Flow::UpdateUserAccountDetails | Flow::UpdateUserAccountDetails
| Flow::TotpBegin | Flow::TotpBegin
| Flow::TotpReset
| Flow::TotpVerify | Flow::TotpVerify
| Flow::TotpUpdate | Flow::TotpUpdate
| Flow::RecoveryCodeVerify | Flow::RecoveryCodeVerify

View File

@ -648,6 +648,20 @@ pub async fn totp_begin(state: web::Data<AppState>, req: HttpRequest) -> HttpRes
.await .await
} }
pub async fn totp_reset(state: web::Data<AppState>, req: HttpRequest) -> HttpResponse {
let flow = Flow::TotpReset;
Box::pin(api::server_wrap(
flow,
state.clone(),
&req,
(),
|state, user, _, _| user_core::reset_totp(state, user),
&auth::DashboardNoPermissionAuth,
api_locking::LockAction::NotApplicable,
))
.await
}
pub async fn totp_verify( pub async fn totp_verify(
state: web::Data<AppState>, state: web::Data<AppState>,
req: HttpRequest, req: HttpRequest,

View File

@ -404,6 +404,8 @@ pub enum Flow {
UserFromEmail, UserFromEmail,
/// Begin TOTP /// Begin TOTP
TotpBegin, TotpBegin,
// Reset TOTP
TotpReset,
/// Verify TOTP /// Verify TOTP
TotpVerify, TotpVerify,
/// Update TOTP secret /// Update TOTP secret