Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
b2568dd
feat(detached_auth): add support to detach authentication from router
NishantJoshi00 May 28, 2024
2609b96
feat(auth): add HeaderAuth for ApiKeyAuth and PublishableKeyAuth
NishantJoshi00 May 28, 2024
2274b46
feat(auth): add HeaderAuth to ApiKeyAuth and PublishableKeyAuth
NishantJoshi00 May 28, 2024
6ef449f
chore: add configuration for partial-auth
NishantJoshi00 May 29, 2024
fd402f6
chore: fix feature flag discrepancies
NishantJoshi00 May 29, 2024
9856e03
Merge branch 'main' into partial-auth
NishantJoshi00 May 29, 2024
4e431cf
chore: change Option to Result and address comments
NishantJoshi00 Jun 3, 2024
6d13c4b
Merge branch 'main' of https://github.com/juspay/hyperswitch into par…
NishantJoshi00 Jun 13, 2024
38db705
Apply suggestions from code review
NishantJoshi00 Jun 25, 2024
1bea898
Merge https://github.com/juspay/hyperswitch into partial-auth
NishantJoshi00 Jun 28, 2024
40985b6
Merge branch 'partial-auth' of https://github.com/juspay/hyperswitch …
NishantJoshi00 Jun 28, 2024
6a59e2c
chore: fix merge conflicts
NishantJoshi00 Jun 28, 2024
52069ea
chore: add metrics for partial auth
NishantJoshi00 Jun 28, 2024
08d28cf
Update crates/router/src/routes/app.rs
NishantJoshi00 Jun 28, 2024
6264fc6
Merge branch 'main' into partial-auth
NishantJoshi00 Jun 28, 2024
83b0355
chore: remove trait impl trait
NishantJoshi00 Jun 28, 2024
98662b0
Merge branch 'main' into partial-auth
NishantJoshi00 Jul 2, 2024
edd0638
chore: add Send
NishantJoshi00 Jul 2, 2024
32663e5
Merge https://github.com/juspay/hyperswitch into partial-auth
NishantJoshi00 Jul 2, 2024
a8278ba
Merge branch 'partial-auth' of https://github.com/juspay/hyperswitch …
NishantJoshi00 Jul 2, 2024
cbc359b
chore: fix `partial-auth` for clippy
NishantJoshi00 Jul 2, 2024
e2ad866
chore: fix conflicts
NishantJoshi00 Jul 8, 2024
22c6615
Merge branch 'main' of https://github.com/juspay/hyperswitch into par…
NishantJoshi00 Jul 19, 2024
1c4901d
Merge https://github.com/juspay/hyperswitch into partial-auth
NishantJoshi00 Jul 29, 2024
87e1689
chore: remove partial-auth from default
NishantJoshi00 Jul 29, 2024
d6f5371
Merge branch 'main' of https://github.com/juspay/hyperswitch into par…
NishantJoshi00 Jul 29, 2024
9614fd3
chore: fix MSRV build CI
NishantJoshi00 Jul 29, 2024
b897016
chore: fix MSRV checks
NishantJoshi00 Jul 30, 2024
f2b1231
Merge branch 'main' of https://github.com/juspay/hyperswitch into par…
NishantJoshi00 Jul 31, 2024
26fe418
chore: resolve merge conflicts
NishantJoshi00 Jul 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions config/development.toml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@ validity = 1
[api_keys]
hash_key = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"

checksum_auth_context = "TEST"
checksum_auth_key = "54455354"


[connectors]
aci.base_url = "https://eu-test.oppwa.com/"
adyen.base_url = "https://checkout-test.adyen.com/"
Expand Down
3 changes: 2 additions & 1 deletion crates/common_utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ logs = ["dep:router_env"]

[dependencies]
async-trait = { version = "0.1.79", optional = true }
blake3 = "1.5.1"
bytes = "1.6.0"
diesel = "2.1.5"
error-stack = "0.4.1"
Expand All @@ -30,6 +31,7 @@ regex = "1.10.4"
reqwest = { version = "0.11.27", features = ["json", "native-tls", "gzip", "multipart"] }
ring = { version = "0.17.8", features = ["std", "wasm32_unknown_unknown_js"] }
rustc-hash = "1.1.0"
semver = { version = "1.0.22", features = ["serde"] }
serde = { version = "1.0.197", features = ["derive"] }
serde_json = "1.0.115"
serde_urlencoded = "0.7.1"
Expand All @@ -38,7 +40,6 @@ strum = { version = "0.26.2", features = ["derive"] }
thiserror = "1.0.58"
time = { version = "0.3.35", features = ["serde", "serde-well-known", "std"] }
tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"], optional = true }
semver = { version = "1.0.22", features = ["serde"] }
utoipa = { version = "4.2.0", features = ["preserve_order", "preserve_path_order"] }
uuid = { version = "1.8.0", features = ["v7"] }

Expand Down
37 changes: 37 additions & 0 deletions crates/common_utils/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,43 @@ impl VerifySignature for HmacSha512 {
}
}

///
/// Blake3
#[derive(Debug)]
pub struct Blake3(String);

impl Blake3 {
/// Create a new instance of Blake3 with a key
pub fn new(key: impl Into<String>) -> Self {
Self(key.into())
}
}

impl SignMessage for Blake3 {
fn sign_message(
&self,
secret: &[u8],
msg: &[u8],
) -> CustomResult<Vec<u8>, errors::CryptoError> {
let key = blake3::derive_key(&self.0, secret);
let output = blake3::keyed_hash(&key, msg).as_bytes().to_vec();
Ok(output)
}
}

impl VerifySignature for Blake3 {
fn verify_signature(
&self,
secret: &[u8],
signature: &[u8],
msg: &[u8],
) -> CustomResult<bool, errors::CryptoError> {
let key = blake3::derive_key(&self.0, secret);
let output = blake3::keyed_hash(&key, msg);
Ok(output.as_bytes() == signature)
}
}

/// Represents the GCM-AES-256 algorithm
#[derive(Debug)]
pub struct GcmAes256;
Expand Down
10 changes: 9 additions & 1 deletion crates/masking/src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use std::{fmt, marker::PhantomData};

use crate::{strategy::Strategy, PeekInterface};
use crate::{strategy::Strategy, PeekInterface, StrongSecret};

///
/// Secret thing.
Expand Down Expand Up @@ -81,6 +81,14 @@ where
{
f(self.inner_secret).into()
}

/// Convert to [`StrongSecret`]
pub fn into_strong(self) -> StrongSecret<SecretValue, MaskingStrategy>
where
SecretValue: zeroize::DefaultIsZeroes,
{
StrongSecret::new(self.inner_secret)
}
}

impl<SecretValue, MaskingStrategy> PeekInterface<SecretValue>
Expand Down
7 changes: 6 additions & 1 deletion crates/router/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ readme = "README.md"
license.workspace = true

[features]
default = ["kv_store", "stripe", "oltp", "olap", "backwards_compatibility", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "business_profile_routing", "connector_choice_mca_id", "profile_specific_fallback_routing", "retry", "frm"]
default = ["kv_store", "stripe", "oltp", "olap", "backwards_compatibility", "accounts_cache", "dummy_connector", "payouts", "payout_retry", "business_profile_routing", "connector_choice_mca_id", "profile_specific_fallback_routing", "retry", "frm", "partial-auth"]
email = ["external_services/email", "scheduler/email", "olap"]
frm = ["api_models/frm"]
stripe = ["dep:serde_qs"]
Expand All @@ -31,6 +31,11 @@ payout_retry = ["payouts"]
recon = ["email", "api_models/recon"]
retry = []

# Partial Auth
# The feature reduces the overhead of the router authenticating the merchant for every request, and trusts on `x-merchant-id` header to be present in the request.
# This is named as partial-auth because the router will still try to authenticate if the `x-merchant-id` header is not present.
partial-auth = []

[dependencies]
actix-cors = "0.6.5"
actix-multipart = "0.6.1"
Expand Down
11 changes: 6 additions & 5 deletions crates/router/src/compatibility/stripe/customers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod types;

use actix_web::{web, HttpRequest, HttpResponse};
use common_utils::id_type;
use error_stack::report;
Expand Down Expand Up @@ -47,7 +48,7 @@ pub async fn customer_create(
|state, auth, req, _| {
customers::create_customer(state, auth.merchant_account, auth.key_store, req)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -81,7 +82,7 @@ pub async fn customer_retrieve(
|state, auth, req, _| {
customers::retrieve_customer(state, auth.merchant_account, auth.key_store, req)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -124,7 +125,7 @@ pub async fn customer_update(
|state, auth, req, _| {
customers::update_customer(state, auth.merchant_account, req, auth.key_store)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -158,7 +159,7 @@ pub async fn customer_delete(
|state, auth: auth::AuthenticationData, req, _| {
customers::delete_customer(state, auth.merchant_account, req, auth.key_store)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -197,7 +198,7 @@ pub async fn list_customer_payment_method_api(
Some(&customer_id),
)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down
7 changes: 4 additions & 3 deletions crates/router/src/compatibility/stripe/payment_intents.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod types;

use actix_web::{web, HttpRequest, HttpResponse};
use api_models::payments as payment_types;
use error_stack::report;
Expand Down Expand Up @@ -71,7 +72,7 @@ pub async fn payment_intents_create(
api_types::HeaderPayload::default(),
)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
locking_action,
))
.await
Expand Down Expand Up @@ -400,7 +401,7 @@ pub async fn payment_intents_capture(
api_types::HeaderPayload::default(),
)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
locking_action,
))
.await
Expand Down Expand Up @@ -498,7 +499,7 @@ pub async fn payment_intent_list(
&req,
payload,
|state, auth, req, _| payments::list_payments(state, auth.merchant_account, req),
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down
9 changes: 5 additions & 4 deletions crates/router/src/compatibility/stripe/refunds.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod types;

use actix_web::{web, HttpRequest, HttpResponse};
use error_stack::report;
use router_env::{instrument, tracing, Flow, Tag};
Expand Down Expand Up @@ -51,7 +52,7 @@ pub async fn refund_create(
|state, auth, req, _| {
refunds::refund_create_core(state, auth.merchant_account, auth.key_store, req)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -101,7 +102,7 @@ pub async fn refund_retrieve_with_gateway_creds(
refunds::refund_retrieve_core,
)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -143,7 +144,7 @@ pub async fn refund_retrieve(
refunds::refund_retrieve_core,
)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down Expand Up @@ -175,7 +176,7 @@ pub async fn refund_update(
&req,
create_refund_update_req,
|state, auth, req, _| refunds::refund_update_core(state, auth.merchant_account, req),
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down
3 changes: 2 additions & 1 deletion crates/router/src/compatibility/stripe/setup_intents.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod types;

use actix_web::{web, HttpRequest, HttpResponse};
use api_models::payments as payment_types;
use error_stack::report;
Expand Down Expand Up @@ -72,7 +73,7 @@ pub async fn setup_intents_create(
api_types::HeaderPayload::default(),
)
},
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
api_locking::LockAction::NotApplicable,
))
.await
Expand Down
7 changes: 7 additions & 0 deletions crates/router/src/configs/defaults.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8774,6 +8774,13 @@ impl Default for super::settings::ApiKeys {
// Specifies the number of days before API key expiry when email reminders should be sent
#[cfg(feature = "email")]
expiry_reminder_days: vec![7, 3, 1],

// Hex-encoded key used for calculating checksum for partial auth
#[cfg(feature = "partial-auth")]
checksum_auth_key: String::new().into(),
// context used for blake3
#[cfg(feature = "partial-auth")]
checksum_auth_context: String::new().into(),
}
}
}
14 changes: 14 additions & 0 deletions crates/router/src/configs/secrets_transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,24 @@ impl SecretsHandler for settings::ApiKeys {
#[cfg(feature = "email")]
let expiry_reminder_days = api_keys.expiry_reminder_days.clone();

#[cfg(feature = "partial-auth")]
let checksum_auth_context = secret_management_client
.get_secret(api_keys.checksum_auth_context.clone())
.await?;
#[cfg(feature = "partial-auth")]
let checksum_auth_key = secret_management_client
.get_secret(api_keys.checksum_auth_key.clone())
.await?;

Ok(value.transition_state(|_| Self {
hash_key,
#[cfg(feature = "email")]
expiry_reminder_days,

#[cfg(feature = "partial-auth")]
checksum_auth_key,
#[cfg(feature = "partial-auth")]
checksum_auth_context,
}))
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/router/src/configs/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,12 @@ pub struct ApiKeys {
// Specifies the number of days before API key expiry when email reminders should be sent
#[cfg(feature = "email")]
pub expiry_reminder_days: Vec<u8>,

#[cfg(feature = "partial-auth")]
pub checksum_auth_context: Secret<String>,

#[cfg(feature = "partial-auth")]
pub checksum_auth_key: Secret<String>,
}

#[derive(Debug, Deserialize, Clone, Default)]
Expand Down
2 changes: 1 addition & 1 deletion crates/router/src/routes/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ pub async fn toggle_connector_agnostic_mit(
json_payload.into_inner(),
|state, _, req, _| connector_agnostic_mit_toggle(state, &merchant_id, &profile_id, req),
auth::auth_type(
&auth::ApiKeyAuth,
&auth::HeaderAuth(auth::ApiKeyAuth),
&auth::JWTAuth(Permission::RoutingWrite),
req.headers(),
),
Expand Down
Loading