Skip to content
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

feat(users): Create config for TOTP Issuer #4776

Merged
merged 8 commits into from
Jun 3, 2024
5 changes: 3 additions & 2 deletions config/config.example.toml
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,9 @@ email_role_arn = "" # The amazon resource name ( arn ) of the role which
sts_role_session_name = "" # An identifier for the assumed role session, used to uniquely identify a session.

[user]
password_validity_in_days = 90 # Number of days after which password should be updated
two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside
password_validity_in_days = 90 # Number of days after which password should be updated
two_factor_auth_expiry_in_secs = 300 # Number of seconds after which 2FA should be done again if doing update/change from inside
totp_issuer_name = "Hyperswitch" # Name of the issuer for TOTP

#tokenization configuration which describe token lifetime and payment method for specific connector
[tokenization]
Expand Down
1 change: 1 addition & 0 deletions config/deployments/integration_test.toml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw
[user]
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Integ"

[frm]
enabled = true
Expand Down
1 change: 1 addition & 0 deletions config/deployments/production.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw
[user]
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Production"

[frm]
enabled = false
Expand Down
1 change: 1 addition & 0 deletions config/deployments/sandbox.toml
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw
[user]
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Sandbox"

[frm]
enabled = true
Expand Down
1 change: 1 addition & 0 deletions config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ sts_role_session_name = ""
[user]
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch Dev"

[bank_config.eps]
stripe = { banks = "arzte_und_apotheker_bank,austrian_anadi_bank_ag,bank_austria,bankhaus_carl_spangler,bankhaus_schelhammer_und_schattera_ag,bawag_psk_ag,bks_bank_ag,brull_kallmus_bank_ag,btv_vier_lander_bank,capital_bank_grawe_gruppe_ag,dolomitenbank,easybank_ag,erste_bank_und_sparkassen,hypo_alpeadriabank_international_ag,hypo_noe_lb_fur_niederosterreich_u_wien,hypo_oberosterreich_salzburg_steiermark,hypo_tirol_bank_ag,hypo_vorarlberg_bank_ag,hypo_bank_burgenland_aktiengesellschaft,marchfelder_bank,oberbank_ag,raiffeisen_bankengruppe_osterreich,schoellerbank_ag,sparda_bank_wien,volksbank_gruppe,volkskreditbank_ag,vr_bank_braunau" }
Expand Down
1 change: 1 addition & 0 deletions config/docker_compose.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ recon_admin_api_key = "recon_test_admin"
[user]
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch"

[locker]
host = ""
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/configs/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ pub struct Secrets {
pub struct UserSettings {
pub password_validity_in_days: u16,
pub two_factor_auth_expiry_in_secs: i64,
pub totp_issuer_name: String,
}

#[derive(Debug, Deserialize, Clone)]
Expand Down
4 changes: 3 additions & 1 deletion crates/router/src/consts/user.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
pub const MAX_NAME_LENGTH: usize = 70;
pub const MAX_COMPANY_NAME_LENGTH: usize = 70;
pub const BUSINESS_EMAIL: &str = "[email protected]";

pub const RECOVERY_CODES_COUNT: usize = 8;
pub const RECOVERY_CODE_LENGTH: usize = 8; // This is without counting the hyphen in between
pub const TOTP_ISSUER_NAME: &str = "Hyperswitch";

/// The number of digits composing the auth code.
pub const TOTP_DIGITS: usize = 6;
/// Duration in seconds of a step.
pub const TOTP_VALIDITY_DURATION_IN_SECONDS: u64 = 30;
/// Number of totps allowed as network delay. 1 would mean one totp before current totp and one totp after are valids.
pub const TOTP_TOLERANCE: u8 = 1;

pub const MAX_PASSWORD_LENGTH: usize = 70;
pub const MIN_PASSWORD_LENGTH: usize = 8;

Expand Down
25 changes: 21 additions & 4 deletions crates/router/src/core/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1635,7 +1635,11 @@ 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,
state.conf.user.totp_issuer_name.clone(),
)?;
let secret = totp.get_secret_base32().into();
tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?;

Expand Down Expand Up @@ -1668,7 +1672,12 @@ pub async fn reset_totp(
return Err(UserErrors::TwoFactorAuthRequired.into());
}

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,
state.conf.user.totp_issuer_name.clone(),
)?;

let secret = totp.get_secret_base32().into();
tfa_utils::insert_totp_secret_in_redis(&state, &user_token.user_id, &secret).await?;

Expand Down Expand Up @@ -1701,7 +1710,11 @@ pub async fn verify_totp(
.await?
.ok_or(UserErrors::InternalServerError)?;

let totp = tfa_utils::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),
state.conf.user.totp_issuer_name.clone(),
)?;

if totp
.generate_current()
Expand Down Expand Up @@ -1732,7 +1745,11 @@ pub async fn update_totp(
.await?
.ok_or(UserErrors::TotpSecretNotFound)?;

let totp = tfa_utils::generate_default_totp(user_from_db.get_email(), Some(new_totp_secret))?;
let totp = tfa_utils::generate_default_totp(
user_from_db.get_email(),
Some(new_totp_secret),
state.conf.user.totp_issuer_name.clone(),
)?;

if totp
.generate_current()
Expand Down
3 changes: 2 additions & 1 deletion crates/router/src/utils/user/two_factor_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
pub fn generate_default_totp(
email: pii::Email,
secret: Option<masking::Secret<String>>,
issuer: String,
) -> UserResult<TOTP> {
let secret = secret
.map(|sec| totp_rs::Secret::Encoded(sec.expose()))
Expand All @@ -25,7 +26,7 @@ pub fn generate_default_totp(
consts::user::TOTP_TOLERANCE,
consts::user::TOTP_VALIDITY_DURATION_IN_SECONDS,
secret,
Some(consts::user::TOTP_ISSUER_NAME.to_string()),
Some(issuer),
email.expose().expose(),
)
.change_context(UserErrors::InternalServerError)
Expand Down
1 change: 1 addition & 0 deletions loadtest/config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jwt_secret = "secret"
[user]
password_validity_in_days = 90
two_factor_auth_expiry_in_secs = 300
totp_issuer_name = "Hyperswitch"

[locker]
host = ""
Expand Down
Loading