Skip to content

Commit dbaf567

Browse files
refactor(authentication): moved cavv storing from table to temp locker (#7978)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
1 parent 3cdb9e1 commit dbaf567

File tree

21 files changed

+307
-93
lines changed

21 files changed

+307
-93
lines changed

crates/diesel_models/src/authentication.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,6 @@ pub enum AuthenticationUpdate {
129129
acquirer_country_code: Option<String>,
130130
},
131131
AuthenticationUpdate {
132-
authentication_value: Option<String>,
133132
trans_status: common_enums::TransactionStatus,
134133
authentication_type: common_enums::DecoupledAuthenticationType,
135134
acs_url: Option<String>,
@@ -143,7 +142,6 @@ pub enum AuthenticationUpdate {
143142
},
144143
PostAuthenticationUpdate {
145144
trans_status: common_enums::TransactionStatus,
146-
authentication_value: Option<String>,
147145
eci: Option<String>,
148146
authentication_status: common_enums::AuthenticationStatus,
149147
},
@@ -177,7 +175,6 @@ pub struct AuthenticationUpdateInternal {
177175
pub connector_metadata: Option<serde_json::Value>,
178176
pub maximum_supported_version: Option<common_utils::types::SemanticVersion>,
179177
pub threeds_server_transaction_id: Option<String>,
180-
pub cavv: Option<String>,
181178
pub authentication_flow_type: Option<String>,
182179
pub message_version: Option<common_utils::types::SemanticVersion>,
183180
pub eci: Option<String>,
@@ -211,7 +208,6 @@ impl Default for AuthenticationUpdateInternal {
211208
connector_metadata: Default::default(),
212209
maximum_supported_version: Default::default(),
213210
threeds_server_transaction_id: Default::default(),
214-
cavv: Default::default(),
215211
authentication_flow_type: Default::default(),
216212
message_version: Default::default(),
217213
eci: Default::default(),
@@ -247,7 +243,6 @@ impl AuthenticationUpdateInternal {
247243
connector_metadata,
248244
maximum_supported_version,
249245
threeds_server_transaction_id,
250-
cavv,
251246
authentication_flow_type,
252247
message_version,
253248
eci,
@@ -282,7 +277,6 @@ impl AuthenticationUpdateInternal {
282277
.or(source.maximum_supported_version),
283278
threeds_server_transaction_id: threeds_server_transaction_id
284279
.or(source.threeds_server_transaction_id),
285-
cavv: cavv.or(source.cavv),
286280
authentication_flow_type: authentication_flow_type.or(source.authentication_flow_type),
287281
message_version: message_version.or(source.message_version),
288282
eci: eci.or(source.eci),
@@ -369,7 +363,6 @@ impl From<AuthenticationUpdate> for AuthenticationUpdateInternal {
369363
..Default::default()
370364
},
371365
AuthenticationUpdate::AuthenticationUpdate {
372-
authentication_value,
373366
trans_status,
374367
authentication_type,
375368
acs_url,
@@ -381,7 +374,6 @@ impl From<AuthenticationUpdate> for AuthenticationUpdateInternal {
381374
authentication_status,
382375
ds_trans_id,
383376
} => Self {
384-
cavv: authentication_value,
385377
trans_status: Some(trans_status),
386378
authentication_type: Some(authentication_type),
387379
acs_url,
@@ -396,12 +388,10 @@ impl From<AuthenticationUpdate> for AuthenticationUpdateInternal {
396388
},
397389
AuthenticationUpdate::PostAuthenticationUpdate {
398390
trans_status,
399-
authentication_value,
400391
eci,
401392
authentication_status,
402393
} => Self {
403394
trans_status: Some(trans_status),
404-
cavv: authentication_value,
405395
eci,
406396
authentication_status: Some(authentication_status),
407397
..Default::default()

crates/hyperswitch_connectors/src/connectors/gpayments/gpayments_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ pub struct GpaymentsAuthenticationSuccessResponse {
196196
pub acs_url: Option<url::Url>,
197197
#[serde(rename = "acsReferenceNumber")]
198198
pub acs_reference_number: String,
199-
pub authentication_value: Option<String>,
199+
pub authentication_value: Option<Secret<String>>,
200200
}
201201

202202
#[derive(Deserialize, Debug, Clone, Serialize, PartialEq)]
@@ -230,7 +230,7 @@ impl From<AuthStatus> for common_enums::TransactionStatus {
230230
#[derive(Debug, Deserialize, Serialize)]
231231
#[serde(rename_all = "camelCase")]
232232
pub struct GpaymentsPostAuthenticationResponse {
233-
pub authentication_value: Option<String>,
233+
pub authentication_value: Option<Secret<String>>,
234234
pub trans_status: AuthStatus,
235235
pub eci: Option<String>,
236236
}

crates/hyperswitch_connectors/src/connectors/netcetera/transformers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -633,7 +633,7 @@ pub struct NetceteraAuthenticationSuccessResponse {
633633
#[serde(rename = "threeDSServerTransID")]
634634
pub three_ds_server_trans_id: String,
635635
pub trans_status: common_enums::TransactionStatus,
636-
pub authentication_value: Option<String>,
636+
pub authentication_value: Option<Secret<String>>,
637637
pub eci: Option<String>,
638638
pub acs_challenge_mandated: Option<ACSChallengeMandatedIndicator>,
639639
pub authentication_response: AuthenticationResponse,
@@ -693,7 +693,7 @@ pub struct ResultsResponseData {
693693

694694
/// Payment System-specific value provided as part of the ACS registration for each supported DS.
695695
/// Authentication Value may be used to provide proof of authentication.
696-
pub authentication_value: Option<String>,
696+
pub authentication_value: Option<Secret<String>>,
697697

698698
/// Payment System-specific value provided by the ACS to indicate the results of the attempt to authenticate
699699
/// the Cardholder.

crates/hyperswitch_domain_models/src/router_request_types/authentication.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,9 @@ pub struct AcquirerDetails {
161161
pub struct ExternalThreeDSConnectorMetadata {
162162
pub pull_mechanism_for_external_3ds_enabled: Option<bool>,
163163
}
164+
165+
#[derive(Clone, Debug)]
166+
pub struct AuthenticationStore {
167+
pub cavv: Option<String>,
168+
pub authentication: diesel_models::authentication::Authentication,
169+
}

crates/hyperswitch_domain_models/src/router_request_types/unified_authentication_service.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub struct PreAuthenticationDetails {
106106
#[derive(Debug, Clone)]
107107
pub struct AuthenticationDetails {
108108
pub authn_flow_type: super::authentication::AuthNFlowType,
109-
pub authentication_value: Option<String>,
109+
pub authentication_value: Option<Secret<String>>,
110110
pub trans_status: common_enums::TransactionStatus,
111111
pub connector_metadata: Option<serde_json::Value>,
112112
pub ds_trans_id: Option<String>,

crates/hyperswitch_domain_models/src/router_response_types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,14 +536,14 @@ pub enum AuthenticationResponseData {
536536
},
537537
AuthNResponse {
538538
authn_flow_type: AuthNFlowType,
539-
authentication_value: Option<String>,
539+
authentication_value: Option<masking::Secret<String>>,
540540
trans_status: common_enums::TransactionStatus,
541541
connector_metadata: Option<serde_json::Value>,
542542
ds_trans_id: Option<String>,
543543
},
544544
PostAuthNResponse {
545545
trans_status: common_enums::TransactionStatus,
546-
authentication_value: Option<String>,
546+
authentication_value: Option<masking::Secret<String>>,
547547
eci: Option<String>,
548548
},
549549
}

crates/hyperswitch_interfaces/src/authentication.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pub struct ExternalAuthenticationPayload {
66
/// trans_status
77
pub trans_status: common_enums::TransactionStatus,
88
/// authentication_value
9-
pub authentication_value: Option<String>,
9+
pub authentication_value: Option<masking::Secret<String>>,
1010
/// eci
1111
pub eci: Option<String>,
1212
}

crates/router/src/connector/threedsecureio/transformers.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ pub struct ThreedsecureioAuthenticationSuccessResponse {
513513
#[serde(rename = "acsSignedContent")]
514514
pub acs_signed_content: Option<String>,
515515
#[serde(rename = "authenticationValue")]
516-
pub authentication_value: Option<String>,
516+
pub authentication_value: Option<Secret<String>>,
517517
}
518518

519519
#[derive(Debug, Serialize, Deserialize)]
@@ -615,7 +615,7 @@ pub struct ThreedsecureioPostAuthenticationRequest {
615615
#[derive(Debug, Deserialize, Serialize)]
616616
#[serde(rename_all = "camelCase")]
617617
pub struct ThreedsecureioPostAuthenticationResponse {
618-
pub authentication_value: Option<String>,
618+
pub authentication_value: Option<Secret<String>>,
619619
pub trans_status: ThreedsecureioTransStatus,
620620
pub eci: Option<String>,
621621
}

crates/router/src/core/authentication.rs

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ pub async fn perform_authentication(
4242
psd2_sca_exemption_type: Option<common_enums::ScaExemptionType>,
4343
payment_id: common_utils::id_type::PaymentId,
4444
force_3ds_challenge: bool,
45+
merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
4546
) -> CustomResult<api::authentication::AuthenticationResponse, ApiErrorResponse> {
4647
let router_data = transformers::construct_authentication_router_data(
4748
state,
@@ -74,8 +75,14 @@ pub async fn perform_authentication(
7475
router_data,
7576
))
7677
.await?;
77-
let authentication =
78-
utils::update_trackers(state, response.clone(), authentication_data, None).await?;
78+
let authentication = utils::update_trackers(
79+
state,
80+
response.clone(),
81+
authentication_data,
82+
None,
83+
merchant_key_store,
84+
)
85+
.await?;
7986
response
8087
.response
8188
.map_err(|err| ApiErrorResponse::ExternalConnectorError {
@@ -94,7 +101,10 @@ pub async fn perform_post_authentication(
94101
business_profile: domain::Profile,
95102
authentication_id: String,
96103
payment_id: &common_utils::id_type::PaymentId,
97-
) -> CustomResult<storage::Authentication, ApiErrorResponse> {
104+
) -> CustomResult<
105+
hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore,
106+
ApiErrorResponse,
107+
> {
98108
let (authentication_connector, three_ds_connector_account) =
99109
utils::get_authentication_connector_data(state, key_store, &business_profile).await?;
100110
let is_pull_mechanism_enabled =
@@ -112,7 +122,11 @@ pub async fn perform_post_authentication(
112122
.await
113123
.to_not_found_response(ApiErrorResponse::InternalServerError)
114124
.attach_printable_lazy(|| format!("Error while fetching authentication record with authentication_id {authentication_id}"))?;
115-
if !authentication.authentication_status.is_terminal_status() && is_pull_mechanism_enabled {
125+
126+
let authentication_update = if !authentication.authentication_status.is_terminal_status()
127+
&& is_pull_mechanism_enabled
128+
{
129+
// trigger in case of authenticate flow
116130
let router_data = transformers::construct_post_authentication_router_data(
117131
state,
118132
authentication_connector.to_string(),
@@ -124,10 +138,28 @@ pub async fn perform_post_authentication(
124138
let router_data =
125139
utils::do_auth_connector_call(state, authentication_connector.to_string(), router_data)
126140
.await?;
127-
utils::update_trackers(state, router_data, authentication, None).await
141+
utils::update_trackers(state, router_data, authentication, None, key_store).await?
128142
} else {
129-
Ok(authentication)
130-
}
143+
// trigger in case of webhook flow
144+
authentication
145+
};
146+
147+
// getting authentication value from temp locker before moving ahead with authrisation
148+
let tokenized_data = crate::core::payment_methods::vault::get_tokenized_data(
149+
state,
150+
&authentication_id,
151+
false,
152+
key_store.key.get_inner(),
153+
)
154+
.await?;
155+
156+
let authentication_store =
157+
hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore {
158+
cavv: Some(tokenized_data.value1),
159+
authentication: authentication_update,
160+
};
161+
162+
Ok(authentication_store)
131163
}
132164

133165
#[allow(clippy::too_many_arguments)]
@@ -140,7 +172,10 @@ pub async fn perform_pre_authentication(
140172
acquirer_details: Option<types::AcquirerDetails>,
141173
payment_id: common_utils::id_type::PaymentId,
142174
organization_id: common_utils::id_type::OrganizationId,
143-
) -> CustomResult<storage::Authentication, ApiErrorResponse> {
175+
) -> CustomResult<
176+
hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore,
177+
ApiErrorResponse,
178+
> {
144179
let (authentication_connector, three_ds_connector_account) =
145180
utils::get_authentication_connector_data(state, key_store, business_profile).await?;
146181
let authentication_connector_name = authentication_connector.to_string();
@@ -176,13 +211,21 @@ pub async fn perform_pre_authentication(
176211
)
177212
.await?;
178213

179-
let updated_authentication =
180-
utils::update_trackers(state, router_data, authentication, acquirer_details.clone())
181-
.await?;
214+
let updated_authentication = utils::update_trackers(
215+
state,
216+
router_data,
217+
authentication,
218+
acquirer_details.clone(),
219+
key_store,
220+
)
221+
.await?;
182222
// from version call response, we will get to know the maximum supported 3ds version.
183223
// If the version is not greater than or equal to 3DS 2.0, We should not do the successive pre authentication call.
184224
if !updated_authentication.is_separate_authn_required() {
185-
return Ok(updated_authentication);
225+
return Ok(hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore{
226+
authentication: updated_authentication,
227+
cavv: None, // since cavv wont be present in pre_authentication step
228+
});
186229
}
187230
updated_authentication
188231
} else {
@@ -201,5 +244,19 @@ pub async fn perform_pre_authentication(
201244
let router_data =
202245
utils::do_auth_connector_call(state, authentication_connector_name, router_data).await?;
203246

204-
utils::update_trackers(state, router_data, authentication, acquirer_details).await
247+
let authentication_update = utils::update_trackers(
248+
state,
249+
router_data,
250+
authentication,
251+
acquirer_details,
252+
key_store,
253+
)
254+
.await?;
255+
256+
Ok(
257+
hyperswitch_domain_models::router_request_types::authentication::AuthenticationStore {
258+
authentication: authentication_update,
259+
cavv: None, // since cavv wont be present in pre_authentication step
260+
},
261+
)
205262
}

crates/router/src/core/authentication/utils.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
use common_utils::ext_traits::AsyncExt;
12
use error_stack::ResultExt;
23
use hyperswitch_domain_models::router_data_v2::ExternalAuthenticationFlowData;
4+
use masking::ExposeInterface;
35

46
use crate::{
57
consts,
@@ -53,6 +55,7 @@ pub async fn update_trackers<F: Clone, Req>(
5355
router_data: RouterData<F, Req, AuthenticationResponseData>,
5456
authentication: storage::Authentication,
5557
acquirer_details: Option<super::types::AcquirerDetails>,
58+
merchant_key_store: &hyperswitch_domain_models::merchant_key_store::MerchantKeyStore,
5659
) -> RouterResult<storage::Authentication> {
5760
let authentication_update = match router_data.response {
5861
Ok(response) => match response {
@@ -91,10 +94,23 @@ pub async fn update_trackers<F: Clone, Req>(
9194
connector_metadata,
9295
ds_trans_id,
9396
} => {
97+
authentication_value
98+
.async_map(|auth_val| {
99+
crate::core::payment_methods::vault::create_tokenize(
100+
state,
101+
auth_val.expose(),
102+
None,
103+
authentication.authentication_id.clone(),
104+
merchant_key_store.key.get_inner(),
105+
)
106+
})
107+
.await
108+
.transpose()?;
109+
94110
let authentication_status =
95111
common_enums::AuthenticationStatus::foreign_from(trans_status.clone());
112+
96113
storage::AuthenticationUpdate::AuthenticationUpdate {
97-
authentication_value,
98114
trans_status,
99115
acs_url: authn_flow_type.get_acs_url(),
100116
challenge_request: authn_flow_type.get_challenge_request(),
@@ -111,14 +127,27 @@ pub async fn update_trackers<F: Clone, Req>(
111127
trans_status,
112128
authentication_value,
113129
eci,
114-
} => storage::AuthenticationUpdate::PostAuthenticationUpdate {
115-
authentication_status: common_enums::AuthenticationStatus::foreign_from(
116-
trans_status.clone(),
117-
),
118-
trans_status,
119-
authentication_value,
120-
eci,
121-
},
130+
} => {
131+
authentication_value
132+
.async_map(|auth_val| {
133+
crate::core::payment_methods::vault::create_tokenize(
134+
state,
135+
auth_val.expose(),
136+
None,
137+
authentication.authentication_id.clone(),
138+
merchant_key_store.key.get_inner(),
139+
)
140+
})
141+
.await
142+
.transpose()?;
143+
storage::AuthenticationUpdate::PostAuthenticationUpdate {
144+
authentication_status: common_enums::AuthenticationStatus::foreign_from(
145+
trans_status.clone(),
146+
),
147+
trans_status,
148+
eci,
149+
}
150+
}
122151
AuthenticationResponseData::PreAuthVersionCallResponse {
123152
maximum_supported_3ds_version,
124153
} => storage::AuthenticationUpdate::PreAuthenticationVersionCallUpdate {

0 commit comments

Comments
 (0)