diff --git a/src/main/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRouteFilter.java b/src/main/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRouteFilter.java index 281bff69..aee4620d 100644 --- a/src/main/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRouteFilter.java +++ b/src/main/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRouteFilter.java @@ -11,10 +11,12 @@ @ApplicationScoped public class FirebaseAuthCorsRouteFilter { - // FirebaseAuthController (sign-in/sign-up) and SecureTokenController (token refresh). + // FirebaseAuthController (sign-in/sign-up), SecureTokenController (token refresh) and + // FirebaseAuthEmulatorController, which the Emulator UI calls from the browser. private static final String[] PATH_PREFIXES = { "/identitytoolkit.googleapis.com/*", "/securetoken.googleapis.com/*", + "/emulator/v1/*", }; // Matches expressjs/cors' defaults, which is what firebase-tools' Auth Emulator uses. @@ -35,6 +37,8 @@ void init() { } private void handle(RoutingContext ctx) { + ctx.response().putHeader("Vary", "Origin"); + String origin = ctx.request().getHeader("Origin"); if (origin == null) { ctx.next(); @@ -43,7 +47,6 @@ private void handle(RoutingContext ctx) { ctx.response().putHeader("Access-Control-Allow-Origin", origin); if (!"OPTIONS".equalsIgnoreCase(ctx.request().method().name())) { - ctx.response().putHeader("Vary", "Origin"); ctx.next(); return; } diff --git a/src/test/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRestIntegrationTest.java b/src/test/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRestIntegrationTest.java index 730b0a52..0b7b62a1 100644 --- a/src/test/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRestIntegrationTest.java +++ b/src/test/java/io/floci/gcp/services/firebaseauth/FirebaseAuthCorsRestIntegrationTest.java @@ -11,6 +11,7 @@ class FirebaseAuthCorsRestIntegrationTest { private static final String CLIENT = "/identitytoolkit.googleapis.com/v1/accounts"; + private static final String EMULATOR = "/emulator/v1"; private static final String ORIGIN = "http://127.0.0.1:59301"; @Test @@ -61,7 +62,33 @@ void preflightForSecureTokenRefreshAdvertisesTheRequestedOrigin() { } @Test - void requestWithNoOriginGetsNoCorsHeaders() { + void preflightForEmulatorDeleteAllAccountsAdvertisesTheRequestedOrigin() { + given() + .header("Origin", ORIGIN) + .header("Access-Control-Request-Method", "DELETE") + .header("Access-Control-Request-Headers", "Content-Type") + .when().options(EMULATOR + "/projects/cors-emulator-probe/accounts") + .then() + .statusCode(204) + .header("Access-Control-Allow-Origin", equalTo(ORIGIN)) + .header("Access-Control-Allow-Methods", equalTo("GET,HEAD,PUT,PATCH,POST,DELETE")) + .header("Access-Control-Allow-Headers", equalTo("Content-Type")) + .header("Vary", equalTo("Origin, Access-Control-Request-Headers")); + } + + @Test + void actualEmulatorDeleteAllAccountsResponseAdvertisesTheRequestedOrigin() { + given() + .header("Origin", ORIGIN) + .when().delete(EMULATOR + "/projects/cors-emulator-probe/accounts") + .then() + .statusCode(200) + .header("Access-Control-Allow-Origin", equalTo(ORIGIN)) + .header("Vary", equalTo("Origin")); + } + + @Test + void requestWithNoOriginStillVariesOnOrigin() { given() .urlEncodingEnabled(false) .contentType("application/json") @@ -72,6 +99,7 @@ void requestWithNoOriginGetsNoCorsHeaders() { .when().post(CLIENT + ":signUp") .then() .statusCode(200) - .header("Access-Control-Allow-Origin", nullValue()); + .header("Access-Control-Allow-Origin", nullValue()) + .header("Vary", equalTo("Origin")); } }