From 9ee6686efc4376c46aa19f0991009f85d124662f Mon Sep 17 00:00:00 2001 From: Mani Chandra Dulam Date: Fri, 24 May 2024 15:37:36 +0530 Subject: [PATCH 1/4] feat: create config for totp issuer and force totp --- config/config.example.toml | 1 + config/deployments/integration_test.toml | 1 + config/deployments/production.toml | 1 + config/deployments/sandbox.toml | 1 + config/development.toml | 1 + config/docker_compose.toml | 1 + loadtest/config/development.toml | 3 ++- 7 files changed, 8 insertions(+), 1 deletion(-) diff --git a/config/config.example.toml b/config/config.example.toml index d5bdfb5a6a7c..cd861f345750 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -353,6 +353,7 @@ sts_role_session_name = "" # An identifier for the assumed role session, used to [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 +totp_issuer_name = "Hyperswitch" # Name of the issuer for TOTP #tokenization configuration which describe token lifetime and payment method for specific connector [tokenization] diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index 9551cd2a80d8..f9e94f5f8159 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -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 diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 5f9408674383..947bb45b6ef6 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -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 diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index d5f63524e6bd..0d769778f043 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -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 diff --git a/config/development.toml b/config/development.toml index a9f7f4d7b4d8..e5be7597bf81 100644 --- a/config/development.toml +++ b/config/development.toml @@ -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" [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" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 6661d164032d..2039101bdac2 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -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 = "" diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 2c3e83ad2ba9..f907ac2cbc14 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -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 = "" @@ -320,4 +321,4 @@ client_secret = "" partner_id = "" [unmasked_headers] -keys = "user-agent" \ No newline at end of file +keys = "user-agent" From 6d0ea2f1deb8dc49e0e424a2b5d9f883acea3da1 Mon Sep 17 00:00:00 2001 From: Mani Chandra Dulam Date: Mon, 27 May 2024 14:46:33 +0530 Subject: [PATCH 2/4] feat: create config for force totp --- config/config.example.toml | 1 + config/deployments/integration_test.toml | 1 + config/deployments/production.toml | 1 + config/deployments/sandbox.toml | 1 + config/development.toml | 3 ++- config/docker_compose.toml | 1 + crates/router/src/configs/settings.rs | 2 ++ crates/router/src/consts/user.rs | 4 +++- crates/router/src/core/user.rs | 15 +++++++++++---- crates/router/src/utils/user/two_factor_auth.rs | 3 ++- loadtest/config/development.toml | 1 + 11 files changed, 26 insertions(+), 7 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index cd861f345750..d429a8a45eda 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -354,6 +354,7 @@ sts_role_session_name = "" # An identifier for the assumed role session, used to 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 +force_two_factor_auth = false # Whether to force two factor authentication for all users #tokenization configuration which describe token lifetime and payment method for specific connector [tokenization] diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index f9e94f5f8159..7ecfe35f1c7c 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -115,6 +115,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Integ" +force_two_factor_auth = false [frm] enabled = true diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 947bb45b6ef6..1055b989180b 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -122,6 +122,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Production" +force_two_factor_auth = false [frm] enabled = false diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 0d769778f043..22339eb18f5a 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -122,6 +122,7 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Sandbox" +force_two_factor_auth = false [frm] enabled = true diff --git a/config/development.toml b/config/development.toml index e5be7597bf81..5cea22837d07 100644 --- a/config/development.toml +++ b/config/development.toml @@ -270,7 +270,8 @@ sts_role_session_name = "" [user] password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 -totp_issuer_name = "Hyperswitch" +totp_issuer_name = "Hyperswitch Dev" +force_two_factor_auth = false [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" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 2039101bdac2..2f63d9402bba 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -55,6 +55,7 @@ recon_admin_api_key = "recon_test_admin" password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch" +force_two_factor_auth = false [locker] host = "" diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index b8a315f944b8..5c783ea991b0 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -396,6 +396,8 @@ 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, + pub force_two_factor_auth: bool, } #[derive(Debug, Deserialize, Clone)] diff --git a/crates/router/src/consts/user.rs b/crates/router/src/consts/user.rs index 2f347dc3d3eb..63a6b54f3070 100644 --- a/crates/router/src/consts/user.rs +++ b/crates/router/src/consts/user.rs @@ -1,15 +1,17 @@ pub const MAX_NAME_LENGTH: usize = 70; pub const MAX_COMPANY_NAME_LENGTH: usize = 70; pub const BUSINESS_EMAIL: &str = "biz@hyperswitch.io"; + 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; diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index 4fd9fa865cd4..c5e13124bc54 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -1632,7 +1632,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 recovery_codes = domain::RecoveryCodes::generate_new(); let key_store = user_from_db.get_or_create_key_store(&state).await?; @@ -1694,8 +1698,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() @@ -1823,7 +1830,7 @@ pub async fn terminate_two_factor_auth( .change_context(UserErrors::InternalServerError)? .into(); - if !skip_two_factor_auth { + if !skip_two_factor_auth || state.conf.user.force_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? { diff --git a/crates/router/src/utils/user/two_factor_auth.rs b/crates/router/src/utils/user/two_factor_auth.rs index e9e3f66005cf..7fddafca4426 100644 --- a/crates/router/src/utils/user/two_factor_auth.rs +++ b/crates/router/src/utils/user/two_factor_auth.rs @@ -15,6 +15,7 @@ use crate::{ pub fn generate_default_totp( email: pii::Email, secret: Option>, + issuer: String, ) -> UserResult { let secret = secret .map(|sec| totp_rs::Secret::Encoded(sec.expose())) @@ -28,7 +29,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) diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index f907ac2cbc14..9b9c97590bff 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -32,6 +32,7 @@ jwt_secret = "secret" password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch" +force_two_factor_auth = false [locker] host = "" From d593b64a2158ccadaae1b94d279c8cc66b73723a Mon Sep 17 00:00:00 2001 From: Mani Chandra Dulam Date: Tue, 28 May 2024 15:17:05 +0530 Subject: [PATCH 3/4] refactor: remove `force_two_factor_auth` config --- config/config.example.toml | 1 - config/deployments/integration_test.toml | 1 - config/deployments/production.toml | 1 - config/deployments/sandbox.toml | 1 - config/development.toml | 1 - config/docker_compose.toml | 1 - crates/router/src/configs/settings.rs | 1 - crates/router/src/core/user.rs | 2 +- loadtest/config/development.toml | 1 - 9 files changed, 1 insertion(+), 9 deletions(-) diff --git a/config/config.example.toml b/config/config.example.toml index d429a8a45eda..cd861f345750 100644 --- a/config/config.example.toml +++ b/config/config.example.toml @@ -354,7 +354,6 @@ sts_role_session_name = "" # An identifier for the assumed role session, used to 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 -force_two_factor_auth = false # Whether to force two factor authentication for all users #tokenization configuration which describe token lifetime and payment method for specific connector [tokenization] diff --git a/config/deployments/integration_test.toml b/config/deployments/integration_test.toml index 7ecfe35f1c7c..f9e94f5f8159 100644 --- a/config/deployments/integration_test.toml +++ b/config/deployments/integration_test.toml @@ -115,7 +115,6 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Integ" -force_two_factor_auth = false [frm] enabled = true diff --git a/config/deployments/production.toml b/config/deployments/production.toml index 1055b989180b..947bb45b6ef6 100644 --- a/config/deployments/production.toml +++ b/config/deployments/production.toml @@ -122,7 +122,6 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Production" -force_two_factor_auth = false [frm] enabled = false diff --git a/config/deployments/sandbox.toml b/config/deployments/sandbox.toml index 22339eb18f5a..0d769778f043 100644 --- a/config/deployments/sandbox.toml +++ b/config/deployments/sandbox.toml @@ -122,7 +122,6 @@ slack_invite_url = "https://join.slack.com/t/hyperswitch-io/shared_invite/zt-2aw password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Sandbox" -force_two_factor_auth = false [frm] enabled = true diff --git a/config/development.toml b/config/development.toml index 5cea22837d07..d879e1ad3cc1 100644 --- a/config/development.toml +++ b/config/development.toml @@ -271,7 +271,6 @@ sts_role_session_name = "" password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch Dev" -force_two_factor_auth = false [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" } diff --git a/config/docker_compose.toml b/config/docker_compose.toml index 2f63d9402bba..2039101bdac2 100644 --- a/config/docker_compose.toml +++ b/config/docker_compose.toml @@ -55,7 +55,6 @@ recon_admin_api_key = "recon_test_admin" password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch" -force_two_factor_auth = false [locker] host = "" diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index 5c783ea991b0..560d274b6a71 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -397,7 +397,6 @@ pub struct UserSettings { pub password_validity_in_days: u16, pub two_factor_auth_expiry_in_secs: i64, pub totp_issuer_name: String, - pub force_two_factor_auth: bool, } #[derive(Debug, Deserialize, Clone)] diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index c5e13124bc54..9327a5afa549 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -1830,7 +1830,7 @@ pub async fn terminate_two_factor_auth( .change_context(UserErrors::InternalServerError)? .into(); - if !skip_two_factor_auth || state.conf.user.force_two_factor_auth { + 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? { diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml index 9b9c97590bff..f907ac2cbc14 100644 --- a/loadtest/config/development.toml +++ b/loadtest/config/development.toml @@ -32,7 +32,6 @@ jwt_secret = "secret" password_validity_in_days = 90 two_factor_auth_expiry_in_secs = 300 totp_issuer_name = "Hyperswitch" -force_two_factor_auth = false [locker] host = "" From 45c4a44459240eb093c7e672116a74ce2576fe01 Mon Sep 17 00:00:00 2001 From: Mani Chandra Dulam Date: Fri, 31 May 2024 13:31:52 +0530 Subject: [PATCH 4/4] fix: hack --- crates/router/src/core/user.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/crates/router/src/core/user.rs b/crates/router/src/core/user.rs index 04b61ddd1f85..5c263b779a9e 100644 --- a/crates/router/src/core/user.rs +++ b/crates/router/src/core/user.rs @@ -1669,7 +1669,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?;