Skip to content

Commit cae8fa5

Browse files
authored
Work around CORS issues with jsdom in auth/hub emulators. (#3224)
* Work around CORS issues with jsdom in auth/hub emulators. * Update CHANGELOG.md
1 parent be0d2b6 commit cae8fa5

File tree

6 files changed

+38
-15
lines changed

6 files changed

+38
-15
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
- Fixes an issue where `ext:dev:init` failed when Typescript was chosen.
22
- Add support for reading/writing mfaInfo field in Auth Emulator (#3173).
3+
- Work around CORS issues with jsdom in Auth Emulator and Emulator Hub (#3224).

package-lock.json

+6-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
"cli-table": "^0.3.1",
9393
"commander": "^4.0.1",
9494
"configstore": "^5.0.1",
95+
"cors": "^2.8.5",
9596
"cross-env": "^5.1.3",
9697
"cross-spawn": "^7.0.1",
9798
"csv-streamify": "^3.0.4",
@@ -146,6 +147,7 @@
146147
"@types/cli-color": "^0.3.29",
147148
"@types/cli-table": "^0.3.0",
148149
"@types/configstore": "^4.0.0",
150+
"@types/cors": "^2.8.10",
149151
"@types/cross-spawn": "^6.0.1",
150152
"@types/dotenv": "^6.1.0",
151153
"@types/express": "^4.17.0",

src/emulator/auth/server.ts

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as cors from "cors";
12
import * as express from "express";
23
import * as exegesisExpress from "exegesis-express";
34
import { ValidationError } from "exegesis/lib/errors";
@@ -118,20 +119,9 @@ export async function createApp(
118119
): Promise<express.Express> {
119120
const app = express();
120121
app.set("json spaces", 2);
121-
122-
// Allow all origins and headers for CORS requests to Auth Emulator.
123-
// This is safe since Auth Emulator does not use cookies.
124-
app.use((req, res, next) => {
125-
res.set("Access-Control-Allow-Origin", "*");
126-
res.set("Access-Control-Allow-Headers", "*");
127-
res.set("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
128-
if (req.method === "OPTIONS") {
129-
// This is a CORS preflight request. Just handle it.
130-
res.end();
131-
} else {
132-
next();
133-
}
134-
});
122+
// Enable CORS for all APIs, all origins (reflected), and all headers (reflected).
123+
// This is similar to production behavior. Safe since all APIs are cookieless.
124+
app.use(cors({ origin: true }));
135125

136126
app.get("/", (req, res) => {
137127
return res.json({

src/emulator/hub.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as cors from "cors";
12
import * as express from "express";
23
import * as os from "os";
34
import * as fs from "fs";
@@ -69,6 +70,9 @@ export class EmulatorHub implements EmulatorInstance {
6970

7071
constructor(private args: EmulatorHubArgs) {
7172
this.hub = express();
73+
// Enable CORS for all APIs, all origins (reflected), and all headers (reflected).
74+
// Safe since all Hub APIs are cookieless.
75+
this.hub.use(cors({ origin: true }));
7276
this.hub.use(bodyParser.json());
7377

7478
this.hub.get("/", (req, res) => {

src/test/emulators/auth/rest.spec.ts

+21
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,26 @@ describeAuthEmulator("REST API mapping", ({ authApi }) => {
1212
});
1313
});
1414

15+
it("should allow cross-origin requests", async () => {
16+
await authApi()
17+
.options("/")
18+
.set("Origin", "example.com")
19+
.set("Access-Control-Request-Headers", "Authorization,X-Client-Version,X-Whatever-Header")
20+
.then((res) => {
21+
expectStatusCode(204, res);
22+
23+
// Some clients (including older browsers and jsdom) won't accept '*' as a
24+
// wildcard, so we need to reflect Origin and Access-Control-Request-Headers.
25+
// https://github.com/firebase/firebase-tools/issues/3200
26+
expect(res.header["access-control-allow-origin"]).to.eql("example.com");
27+
expect((res.header["access-control-allow-headers"] as string).split(",")).to.have.members([
28+
"Authorization",
29+
"X-Client-Version",
30+
"X-Whatever-Header",
31+
]);
32+
});
33+
});
34+
1535
it("should handle integer values for enums", async () => {
1636
// Proto integer value for "EMAIL_SIGNIN". Android client SDK sends this.
1737
const requestType = 6;
@@ -67,6 +87,7 @@ describeAuthEmulator("authentication", ({ authApi }) => {
6787
expect(res.body.error).to.have.property("status").equal("PERMISSION_DENIED");
6888
});
6989
});
90+
7091
it("should ignore non-Bearer Authorization headers", async () => {
7192
await authApi()
7293
.post("/identitytoolkit.googleapis.com/v1/accounts:signUp")

0 commit comments

Comments
 (0)