-
-
Notifications
You must be signed in to change notification settings - Fork 860
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework the way 2FA is enabled/disabled (fixes #3309) #3959
Changes from 3 commits
25f38a0
c90218a
f23ea6d
e6d7ab2
437c351
2bfbc1d
91e3fbc
b08bc3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
use crate::{build_totp_2fa, generate_totp_2fa_secret}; | ||
use activitypub_federation::config::Data; | ||
use actix_web::web::Json; | ||
use lemmy_api_common::{ | ||
context::LemmyContext, | ||
person::GenerateTotpSecretResponse, | ||
sensitive::Sensitive, | ||
}; | ||
use lemmy_db_schema::{ | ||
source::local_user::{LocalUser, LocalUserUpdateForm}, | ||
traits::Crud, | ||
}; | ||
use lemmy_db_views::structs::{LocalUserView, SiteView}; | ||
use lemmy_utils::error::{LemmyError, LemmyErrorType}; | ||
|
||
/// Generate a new secret for two-factor-authentication. Afterwards you need to call [toggle_totp] | ||
/// to enable it. This can only be called if 2FA is currently disabled. | ||
#[tracing::instrument(skip(context))] | ||
pub async fn generate_totp_secret( | ||
local_user_view: LocalUserView, | ||
context: Data<LemmyContext>, | ||
) -> Result<Json<GenerateTotpSecretResponse>, LemmyError> { | ||
let site_view = SiteView::read_local(&mut context.pool()).await?; | ||
|
||
if local_user_view.local_user.totp_2fa_enabled { | ||
return Err(LemmyErrorType::TotpAlreadyEnabled)?; | ||
} | ||
|
||
let secret = generate_totp_2fa_secret(); | ||
let secret_url = | ||
build_totp_2fa(&site_view.site.name, &local_user_view.person.name, &secret)?.get_url(); | ||
|
||
let local_user_form = LocalUserUpdateForm { | ||
totp_2fa_secret: Some(Some(secret)), | ||
..Default::default() | ||
}; | ||
LocalUser::update( | ||
&mut context.pool(), | ||
local_user_view.local_user.id, | ||
&local_user_form, | ||
) | ||
.await?; | ||
|
||
Ok(Json(GenerateTotpSecretResponse { | ||
totp_secret_url: Sensitive::new(secret_url), | ||
})) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use crate::check_totp_2fa_valid; | ||
use actix_web::{ | ||
web::{Data, Json}, | ||
HttpResponse, | ||
}; | ||
use lemmy_api_common::{context::LemmyContext, person::ToggleTotp}; | ||
use lemmy_db_schema::{ | ||
source::local_user::{LocalUser, LocalUserUpdateForm}, | ||
traits::Crud, | ||
}; | ||
use lemmy_db_views::structs::{LocalUserView, SiteView}; | ||
use lemmy_utils::error::{LemmyError, LemmyErrorType}; | ||
|
||
/// Enable or disable two-factor-authentication. The current setting is determined from | ||
/// [LocalUser.totp_2fa_enabled]. | ||
/// | ||
/// To enable, you need to first call [generate_totp_secret] and then pass a valid token to this | ||
/// function. | ||
/// | ||
/// Disabling is only possible if 2FA was previously enabled. Again it is necessary to pass a valid | ||
/// token. | ||
#[tracing::instrument(skip(context))] | ||
pub async fn toggle_totp( | ||
data: Json<ToggleTotp>, | ||
local_user_view: LocalUserView, | ||
context: Data<LemmyContext>, | ||
) -> Result<HttpResponse, LemmyError> { | ||
let site_view = SiteView::read_local(&mut context.pool()).await?; | ||
|
||
// require valid 2fa token to enable or disable 2fa | ||
if local_user_view.local_user.totp_2fa_secret.is_none() { | ||
return Err(LemmyErrorType::MissingTotpToken.into()); | ||
} | ||
check_totp_2fa_valid( | ||
dessalines marked this conversation as resolved.
Show resolved
Hide resolved
|
||
&local_user_view.local_user, | ||
&Some(data.totp_totp_token.clone()), | ||
&site_view.site.name, | ||
&local_user_view.person.name, | ||
)?; | ||
|
||
// toggle the 2fa setting | ||
let new_totp_state = !local_user_view.local_user.totp_2fa_enabled; | ||
let mut local_user_form = LocalUserUpdateForm { | ||
totp_2fa_enabled: Some(new_totp_state), | ||
..Default::default() | ||
}; | ||
|
||
// clear totp secret if 2fa is being disabled | ||
if !new_totp_state { | ||
local_user_form.totp_2fa_secret = None; | ||
} | ||
|
||
LocalUser::update( | ||
&mut context.pool(), | ||
local_user_view.local_user.id, | ||
&local_user_form, | ||
) | ||
.await?; | ||
|
||
Ok(HttpResponse::Ok().finish()) | ||
dessalines marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -119,10 +119,6 @@ pub struct SaveUserSettings { | |
pub show_new_post_notifs: Option<bool>, | ||
/// A list of languages you are able to see discussion in. | ||
pub discussion_languages: Option<Vec<LanguageId>>, | ||
/// Generates a TOTP / 2-factor authentication token. | ||
/// | ||
/// None leaves it as is, true will generate or regenerate it, false clears it out. | ||
pub generate_totp_2fa: Option<bool>, | ||
pub auth: Sensitive<String>, | ||
/// Open links in a new tab | ||
pub open_links_in_new_tab: Option<bool>, | ||
|
@@ -443,3 +439,17 @@ pub struct VerifyEmail { | |
#[cfg_attr(feature = "full", ts(export))] | ||
/// A response to verifying your email. | ||
pub struct VerifyEmailResponse {} | ||
|
||
#[derive(Debug, Serialize, Deserialize, Clone)] | ||
#[cfg_attr(feature = "full", derive(TS))] | ||
#[cfg_attr(feature = "full", ts(export))] | ||
pub struct GenerateTotpSecretResponse { | ||
pub totp_secret_url: Sensitive<String>, | ||
} | ||
|
||
#[derive(Debug, Serialize, Deserialize, Clone)] | ||
#[cfg_attr(feature = "full", derive(TS))] | ||
#[cfg_attr(feature = "full", ts(export))] | ||
pub struct ToggleTotp { | ||
pub totp_totp_token: String, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This needs a comment about how to disable totp also (maybe sending an empty or invalid string) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should probably also have a response, probably a simple Because right now the responses for enabling / disabling TOTP are the same. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added |
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see you got this one, good.