Skip to content

Commit

Permalink
Work around CORS issues with jsdom in auth/hub emulators. (#3224)
Browse files Browse the repository at this point in the history
* Work around CORS issues with jsdom in auth/hub emulators.

* Update CHANGELOG.md
  • Loading branch information
yuchenshi committed Mar 19, 2021
1 parent be0d2b6 commit cae8fa5
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
- Fixes an issue where `ext:dev:init` failed when Typescript was chosen.
- Add support for reading/writing mfaInfo field in Auth Emulator (#3173).
- Work around CORS issues with jsdom in Auth Emulator and Emulator Hub (#3224).
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"cli-table": "^0.3.1",
"commander": "^4.0.1",
"configstore": "^5.0.1",
"cors": "^2.8.5",
"cross-env": "^5.1.3",
"cross-spawn": "^7.0.1",
"csv-streamify": "^3.0.4",
Expand Down Expand Up @@ -146,6 +147,7 @@
"@types/cli-color": "^0.3.29",
"@types/cli-table": "^0.3.0",
"@types/configstore": "^4.0.0",
"@types/cors": "^2.8.10",
"@types/cross-spawn": "^6.0.1",
"@types/dotenv": "^6.1.0",
"@types/express": "^4.17.0",
Expand Down
18 changes: 4 additions & 14 deletions src/emulator/auth/server.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as cors from "cors";
import * as express from "express";
import * as exegesisExpress from "exegesis-express";
import { ValidationError } from "exegesis/lib/errors";
Expand Down Expand Up @@ -118,20 +119,9 @@ export async function createApp(
): Promise<express.Express> {
const app = express();
app.set("json spaces", 2);

// Allow all origins and headers for CORS requests to Auth Emulator.
// This is safe since Auth Emulator does not use cookies.
app.use((req, res, next) => {
res.set("Access-Control-Allow-Origin", "*");
res.set("Access-Control-Allow-Headers", "*");
res.set("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");
if (req.method === "OPTIONS") {
// This is a CORS preflight request. Just handle it.
res.end();
} else {
next();
}
});
// Enable CORS for all APIs, all origins (reflected), and all headers (reflected).
// This is similar to production behavior. Safe since all APIs are cookieless.
app.use(cors({ origin: true }));

app.get("/", (req, res) => {
return res.json({
Expand Down
4 changes: 4 additions & 0 deletions src/emulator/hub.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as cors from "cors";
import * as express from "express";
import * as os from "os";
import * as fs from "fs";
Expand Down Expand Up @@ -69,6 +70,9 @@ export class EmulatorHub implements EmulatorInstance {

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

this.hub.get("/", (req, res) => {
Expand Down
21 changes: 21 additions & 0 deletions src/test/emulators/auth/rest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,26 @@ describeAuthEmulator("REST API mapping", ({ authApi }) => {
});
});

it("should allow cross-origin requests", async () => {
await authApi()
.options("/")
.set("Origin", "example.com")
.set("Access-Control-Request-Headers", "Authorization,X-Client-Version,X-Whatever-Header")
.then((res) => {
expectStatusCode(204, res);

// Some clients (including older browsers and jsdom) won't accept '*' as a
// wildcard, so we need to reflect Origin and Access-Control-Request-Headers.
// https://github.com/firebase/firebase-tools/issues/3200
expect(res.header["access-control-allow-origin"]).to.eql("example.com");
expect((res.header["access-control-allow-headers"] as string).split(",")).to.have.members([
"Authorization",
"X-Client-Version",
"X-Whatever-Header",
]);
});
});

it("should handle integer values for enums", async () => {
// Proto integer value for "EMAIL_SIGNIN". Android client SDK sends this.
const requestType = 6;
Expand Down Expand Up @@ -67,6 +87,7 @@ describeAuthEmulator("authentication", ({ authApi }) => {
expect(res.body.error).to.have.property("status").equal("PERMISSION_DENIED");
});
});

it("should ignore non-Bearer Authorization headers", async () => {
await authApi()
.post("/identitytoolkit.googleapis.com/v1/accounts:signUp")
Expand Down

0 comments on commit cae8fa5

Please sign in to comment.