Repository: juspay/hyperswitch
File: crates/router/src/services/authentication.rs (Rust)

Code before:
#[cfg(feature = "v1")]
#[async_trait]
impl<A, F> AuthenticateAndFetch<AuthenticationData, A> for InternalMerchantIdProfileIdAuth<F>
where
    A: SessionStateInfo + Sync + Send,
    F: AuthenticateAndFetch<AuthenticationData, A> + Sync + Send,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        let merchant_id = HeaderMapStruct::new(request_headers)
            .get_id_type_from_header::<id_type::MerchantId>(headers::X_MERCHANT_ID)
            .ok();
        let internal_api_key = HeaderMapStruct::new(request_headers)
            .get_header_value_by_key(headers::X_INTERNAL_API_KEY)
            .map(|s| s.to_string());
        let profile_id = HeaderMapStruct::new(request_headers)
            .get_id_type_from_header::<id_type::ProfileId>(headers::X_PROFILE_ID)
            .ok();
        if let (Some(internal_api_key), Some(merchant_id), Some(profile_id)) =
            (internal_api_key, merchant_id, profile_id)
        {
            let config = state.conf();
            if internal_api_key
                != *config
                    .internal_merchant_id_profile_id_auth
                    .internal_api_key
                    .peek()
            {
                return Err(errors::ApiErrorResponse::Unauthorized)
                    .attach_printable("Internal API key authentication failed");
            }
            let key_manager_state = &(&state.session_state()).into();
            let key_store = state
                .store()
                .get_merchant_key_store_by_merchant_id(
                    key_manager_state,
                    &merchant_id,
                    &state.store().get_master_key().to_vec().into(),
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
            let _profile = state
                .store()
                .find_business_profile_by_merchant_id_profile_id(
                    key_manager_state,
                    &key_store,
                    &merchant_id,
                    &profile_id,

Review comment (security):
Continuing the above comment, we can add the check `state.conf.internal_merchant_id_profile_id_auth.enabled` here instead. This is will not bloat the route files, and correct authentication method will be chosen inside authentication module.

Code after:

#[cfg(feature = "v1")]
#[async_trait]
impl<A, F> AuthenticateAndFetch<AuthenticationData, A> for InternalMerchantIdProfileIdAuth<F>
where
    A: SessionStateInfo + Sync + Send,
    F: AuthenticateAndFetch<AuthenticationData, A> + Sync + Send,
{
    async fn authenticate_and_fetch(
        &self,
        request_headers: &HeaderMap,
        state: &A,
    ) -> RouterResult<(AuthenticationData, AuthenticationType)> {
        if !state.conf().internal_merchant_id_profile_id_auth.enabled {
            return self.0.authenticate_and_fetch(request_headers, state).await;
        }
        let merchant_id = HeaderMapStruct::new(request_headers)
            .get_id_type_from_header::<id_type::MerchantId>(headers::X_MERCHANT_ID)
            .ok();
        let internal_api_key = HeaderMapStruct::new(request_headers)
            .get_header_value_by_key(headers::X_INTERNAL_API_KEY)
            .map(|s| s.to_string());
        let profile_id = HeaderMapStruct::new(request_headers)
            .get_id_type_from_header::<id_type::ProfileId>(headers::X_PROFILE_ID)
            .ok();
        if let (Some(internal_api_key), Some(merchant_id), Some(profile_id)) =
            (internal_api_key, merchant_id, profile_id)
        {
            let config = state.conf();
            if internal_api_key
                != *config
                    .internal_merchant_id_profile_id_auth
                    .internal_api_key
                    .peek()
            {
                return Err(errors::ApiErrorResponse::Unauthorized)
                    .attach_printable("Internal API key authentication failed");
            }
            let key_manager_state = &(&state.session_state()).into();
            let key_store = state
                .store()
                .get_merchant_key_store_by_merchant_id(
                    key_manager_state,
                    &merchant_id,
                    &state.store().get_master_key().to_vec().into(),
                )
                .await
                .to_not_found_response(errors::ApiErrorResponse::Unauthorized)?;
            let _profile = state
                .store()
                .find_business_profile_by_merchant_id_profile_id(