diff --git a/src/handlers/update_apns.rs b/src/handlers/update_apns.rs index b891e83a..2735055d 100644 --- a/src/handlers/update_apns.rs +++ b/src/handlers/update_apns.rs @@ -1,18 +1,21 @@ use { crate::{ error::{Error, Error::InvalidMultipartBody}, + handlers::validate_tenant_request, increment_counter, + request_id::get_req_id, state::AppState, stores::tenant::{TenantApnsUpdateAuth, TenantApnsUpdateParams}, }, axum::{ extract::{Multipart, Path, State}, + http::HeaderMap, Json, }, base64::Engine, serde::{Deserialize, Serialize}, std::{io::BufReader, sync::Arc}, - tracing::warn, + tracing::{error, warn}, }; #[derive(Deserialize)] @@ -117,11 +120,37 @@ pub struct UpdateTenantApnsResponse { pub async fn handler( State(state): State>, Path(id): Path, + headers: HeaderMap, mut form_body: Multipart, ) -> Result, Error> { // Ensure tenant real let _existing_tenant = state.tenant_store.get_tenant(&id).await?; + // JWT verification + let req_id = get_req_id(&headers); + #[cfg(feature = "cloud")] + let jwt_verification_result = validate_tenant_request( + &state.registry_client, + &state.gotrue_client, + &headers, + id.clone(), + None, + ) + .await; + + #[cfg(not(feature = "cloud"))] + let jwt_verification_result = validate_tenant_request(&state.gotrue_client, &headers); + + if let Err(e) = jwt_verification_result { + error!( + request_id = %req_id, + tenant_id = %id, + err = ?e, + "JWT verification failed" + ); + return Err(e); + } + // ---- retrieve body from form let mut body = ApnsUpdateBody { apns_topic: None, diff --git a/src/handlers/update_fcm.rs b/src/handlers/update_fcm.rs index 9b2d1d2b..c8dfded0 100644 --- a/src/handlers/update_fcm.rs +++ b/src/handlers/update_fcm.rs @@ -4,17 +4,21 @@ use { Error, Error::{BadFcmApiKey, InvalidMultipartBody}, }, + handlers::validate_tenant_request, increment_counter, + request_id::get_req_id, state::AppState, stores::tenant::TenantFcmUpdateParams, }, axum::{ extract::{Multipart, Path, State}, + http::HeaderMap, Json, }, fcm::FcmError, serde::Serialize, std::sync::Arc, + tracing::error, }; pub struct FcmUpdateBody { @@ -31,11 +35,37 @@ pub struct UpdateTenantFcmResponse { pub async fn handler( State(state): State>, Path(id): Path, + headers: HeaderMap, mut form_body: Multipart, ) -> Result, Error> { // -- check if tenant is real let _existing_tenant = state.tenant_store.get_tenant(&id).await?; + // JWT token verification + let req_id = get_req_id(&headers); + #[cfg(feature = "cloud")] + let jwt_verification_result = validate_tenant_request( + &state.registry_client, + &state.gotrue_client, + &headers, + id.clone(), + None, + ) + .await; + + #[cfg(not(feature = "cloud"))] + let jwt_verification_result = validate_tenant_request(&state.gotrue_client, &headers); + + if let Err(e) = jwt_verification_result { + error!( + request_id = %req_id, + tenant_id = %id, + err = ?e, + "JWT verification failed" + ); + return Err(e); + } + // ---- retrieve body from form let mut body = FcmUpdateBody { api_key: Default::default(), diff --git a/tests/functional/multitenant/apns.rs b/tests/functional/multitenant/apns.rs index 47ace1e2..0c301dff 100644 --- a/tests/functional/multitenant/apns.rs +++ b/tests/functional/multitenant/apns.rs @@ -61,6 +61,7 @@ async fn tenant_update_apns_valid_token(ctx: &mut EchoServerContext) { "http://{}/tenants/{}/apns", ctx.server.public_addr, &tenant_id )) + .header("AUTHORIZATION", jwt_token.clone()) .multipart(form) .send() .await