Repository: juspay/hyperswitch
File: crates/router/src/core/payments/access_token.rs (Rust)

Code before:
    router_data: &types::RouterData<F, Req, Res>,
    creds_identifier: Option<&str>,
) -> RouterResult<types::AddAccessTokenResult> {
    if connector
        .connector_name
        .supports_access_token(router_data.payment_method)
    {
        let merchant_id = &router_data.merchant_id;
        let store = &*state.store;

        // `merchant_connector_id` may not be present in the below cases
        // - when straight through routing is used without passing the `merchant_connector_id`
        // - when creds identifier is passed
        //
        // In these cases fallback to `connector_name`.
        // We cannot use multiple merchant connector account in these cases
        let merchant_connector_id_or_connector_name = connector
            .merchant_connector_id
            .clone()
            .map(|mca_id| mca_id.get_string_repr().to_string())
            .or(creds_identifier.map(|id| id.to_string()))
            .unwrap_or(connector.connector_name.to_string());

        let pmt_suffix = connector
            .connector_name
            .is_different_access_token_required_per_payment_method_type()
            .then(|| {
                router_data
                    .payment_method_type
                    .as_ref()
                    .map(|pmt| pmt.to_string())
            })
            .flatten();

        let old_access_token = store
            .get_access_token(
                merchant_id,
                &merchant_connector_id_or_connector_name,
                pmt_suffix.clone(),
            )
            .await
            .change_context(errors::ApiErrorResponse::InternalServerError)
            .attach_printable("DB error when accessing the access token")?;

        let res = match old_access_token {
            Some(access_token) => {
                router_env::logger::debug!(
                    "Access token found in redis for merchant_id: {:?}, payment_id: {:?}, connector: {} which has expiry of: {} seconds",
                    merchant_id,
                    router_data.payment_id,
                    connector.connector_name,

Review comment (security):
This approach is not scalable, if we need it to vary with more parameters like auth_type etc. We should give this flexibility to connector flows, we can use some Connector specification trait approach to achieve this

Code after:
                1,
                router_env::metric_attributes!(("connector", connector.connector_name.to_string())),
            );
            Ok(Some(access_token))
        } else {
            router_env::logger::info!(
                "No cached access token found for UCS flow - UCS will generate internally - merchant_id: {:?}, connector: {}",
                platform.get_processor().get_account().get_id(),
                connector.connector_name
            );
            metrics::ACCESS_TOKEN_CACHE_MISS.add(
                1,
                router_env::metric_attributes!(("connector", connector.connector_name.to_string())),
            );
            Ok(None)
        }
    } else {
        Ok(None)
    }
}

/// After we get the access token, check if there was an error and if the flow should proceed further
/// Returns bool
/// true - Everything is well, continue with the flow
/// false - There was an error, cannot proceed further
pub fn update_router_data_with_access_token_result<F, Req, Res>(
    add_access_token_result: &types::AddAccessTokenResult,
    router_data: &mut types::RouterData<F, Req, Res>,
    call_connector_action: &payments::CallConnectorAction,
) -> bool {
    // Update router data with access token or error only if it will be calling connector
    let should_update_router_data = matches!(
        (
            add_access_token_result.connector_supports_access_token,
            call_connector_action
        ),
        (true, payments::CallConnectorAction::Trigger)
    );

    if should_update_router_data {
        match add_access_token_result.access_token_result.as_ref() {
            Ok(access_token) => {
                router_data.access_token.clone_from(access_token);
                true
            }
            Err(connector_error) => {
                router_data.response = Err(connector_error.clone());
                false
            }
        }
    } else {