@@ -98,6 +98,11 @@ pub struct AuthenticationDataWithUser {
98
98
pub profile_id : id_type:: ProfileId ,
99
99
}
100
100
101
+ #[ derive( Clone , Debug ) ]
102
+ pub struct AuthenticationDataWithOrg {
103
+ pub organization_id : id_type:: OrganizationId ,
104
+ }
105
+
101
106
#[ derive( Clone ) ]
102
107
pub struct UserFromTokenWithRoleInfo {
103
108
pub user : UserFromToken ,
@@ -1330,15 +1335,16 @@ pub struct AdminApiAuthWithApiKeyFallback;
1330
1335
1331
1336
#[ cfg( feature = "v1" ) ]
1332
1337
#[ async_trait]
1333
- impl < A > AuthenticateAndFetch < ( ) , A > for AdminApiAuthWithApiKeyFallback
1338
+ impl < A > AuthenticateAndFetch < Option < AuthenticationDataWithOrg > , A >
1339
+ for AdminApiAuthWithApiKeyFallback
1334
1340
where
1335
1341
A : SessionStateInfo + Sync ,
1336
1342
{
1337
1343
async fn authenticate_and_fetch (
1338
1344
& self ,
1339
1345
request_headers : & HeaderMap ,
1340
1346
state : & A ,
1341
- ) -> RouterResult < ( ( ) , AuthenticationType ) > {
1347
+ ) -> RouterResult < ( Option < AuthenticationDataWithOrg > , AuthenticationType ) > {
1342
1348
let request_api_key =
1343
1349
get_api_key ( request_headers) . change_context ( errors:: ApiErrorResponse :: Unauthorized ) ?;
1344
1350
@@ -1347,7 +1353,7 @@ where
1347
1353
let admin_api_key = & conf. secrets . get_inner ( ) . admin_api_key ;
1348
1354
1349
1355
if request_api_key == admin_api_key. peek ( ) {
1350
- return Ok ( ( ( ) , AuthenticationType :: AdminApiKey ) ) ;
1356
+ return Ok ( ( None , AuthenticationType :: AdminApiKey ) ) ;
1351
1357
}
1352
1358
let Some ( fallback_merchant_ids) = conf. fallback_merchant_ids_api_key_auth . as_ref ( ) else {
1353
1359
return Err ( report ! ( errors:: ApiErrorResponse :: Unauthorized ) ) . attach_printable (
@@ -1377,12 +1383,37 @@ where
1377
1383
. attach_printable ( "API key has expired" ) ;
1378
1384
}
1379
1385
1386
+ let key_manager_state = & ( & state. session_state ( ) ) . into ( ) ;
1387
+
1388
+ let key_store = state
1389
+ . store ( )
1390
+ . get_merchant_key_store_by_merchant_id (
1391
+ key_manager_state,
1392
+ & stored_api_key. merchant_id ,
1393
+ & state. store ( ) . get_master_key ( ) . to_vec ( ) . into ( ) ,
1394
+ )
1395
+ . await
1396
+ . change_context ( errors:: ApiErrorResponse :: Unauthorized )
1397
+ . attach_printable ( "Failed to fetch merchant key store for the merchant id" ) ?;
1398
+
1399
+ let merchant = state
1400
+ . store ( )
1401
+ . find_merchant_account_by_merchant_id (
1402
+ key_manager_state,
1403
+ & stored_api_key. merchant_id ,
1404
+ & key_store,
1405
+ )
1406
+ . await
1407
+ . to_not_found_response ( errors:: ApiErrorResponse :: Unauthorized ) ?;
1408
+
1380
1409
if fallback_merchant_ids
1381
1410
. merchant_ids
1382
1411
. contains ( & stored_api_key. merchant_id )
1383
1412
{
1384
1413
return Ok ( (
1385
- ( ) ,
1414
+ Some ( AuthenticationDataWithOrg {
1415
+ organization_id : merchant. organization_id ,
1416
+ } ) ,
1386
1417
AuthenticationType :: ApiKey {
1387
1418
merchant_id : stored_api_key. merchant_id ,
1388
1419
key_id : stored_api_key. key_id ,
@@ -2705,6 +2736,50 @@ where
2705
2736
}
2706
2737
}
2707
2738
2739
+ #[ cfg( feature = "v1" ) ]
2740
+ #[ async_trait]
2741
+ impl < A > AuthenticateAndFetch < Option < AuthenticationDataWithOrg > , A > for JWTAuthMerchantFromHeader
2742
+ where
2743
+ A : SessionStateInfo + Sync ,
2744
+ {
2745
+ async fn authenticate_and_fetch (
2746
+ & self ,
2747
+ request_headers : & HeaderMap ,
2748
+ state : & A ,
2749
+ ) -> RouterResult < ( Option < AuthenticationDataWithOrg > , AuthenticationType ) > {
2750
+ let payload = parse_jwt_payload :: < A , AuthToken > ( request_headers, state) . await ?;
2751
+ if payload. check_in_blacklist ( state) . await ? {
2752
+ return Err ( errors:: ApiErrorResponse :: InvalidJwtToken . into ( ) ) ;
2753
+ }
2754
+ authorization:: check_tenant (
2755
+ payload. tenant_id . clone ( ) ,
2756
+ & state. session_state ( ) . tenant . tenant_id ,
2757
+ ) ?;
2758
+ let role_info = authorization:: get_role_info ( state, & payload) . await ?;
2759
+ authorization:: check_permission ( self . required_permission , & role_info) ?;
2760
+
2761
+ let merchant_id_from_header = HeaderMapStruct :: new ( request_headers)
2762
+ . get_id_type_from_header :: < id_type:: MerchantId > ( headers:: X_MERCHANT_ID ) ?;
2763
+
2764
+ // Check if token has access to MerchantId that has been requested through headers
2765
+ if payload. merchant_id != merchant_id_from_header {
2766
+ return Err ( report ! ( errors:: ApiErrorResponse :: InvalidJwtToken ) ) ;
2767
+ }
2768
+
2769
+ let auth = Some ( AuthenticationDataWithOrg {
2770
+ organization_id : payload. org_id ,
2771
+ } ) ;
2772
+
2773
+ Ok ( (
2774
+ auth,
2775
+ AuthenticationType :: MerchantJwt {
2776
+ merchant_id : payload. merchant_id ,
2777
+ user_id : Some ( payload. user_id ) ,
2778
+ } ,
2779
+ ) )
2780
+ }
2781
+ }
2782
+
2708
2783
#[ cfg( feature = "v2" ) ]
2709
2784
#[ async_trait]
2710
2785
impl < A > AuthenticateAndFetch < AuthenticationData , A > for JWTAuthMerchantFromHeader
0 commit comments