1

I help understanding why the CORS wildcard doesn't work with the prefix chrome-extension. This example will illustrate the problem.

When using this CORS configuration with wildcard, I am getting blocked by CORS when calling FastAPI from chrome-extension background.js.

origins = [
    "chrome-extension://*",
    "http://localhost:*",
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    # allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

But, when fully specifying the Chrome extension with its ID, I don't get the CORS policy error.

origins = [
    "chrome-extension://dpcnaflfhdkdeijjglelioklbghepbig",
    "http://localhost:*",
]

When I set origins to ["*"] it also works.

Can someone explain to me, what I am doing wrong?

Chris
  • 18,724
  • 6
  • 46
  • 80
eboraks
  • 167
  • 1
  • 9

1 Answers1

2

Problem Overview

The reason is simply because chrome-extension:// represents just the scheme (protocol)—similar to http://, https://, etc.—not a complete origin (which includes the domain and port as well) to be used in the CORS mechanism.

Solution 1

Hence, as you already figured out, you would need to define the origin of your chrome extension similar to the one below. If you would like to maintain the unique ID of an extension during development, instead of having random chrome extension IDs and needing to change the origin in the server side each time, please have a look at the relevant chrome extensions documentation on keeping a consistent extension ID.

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

origins = [
    "chrome-extension://dpcnaflfhdkdeijjglelioklbghepbig"
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Related answers around this topic can be found here, as well as here and here.

Solution 2

As described in this answer, instead of using the allow_origins argument of the CORSMiddleware (the implementation of the CORSMiddleware class can be found in Starlette's source code here and the relevant Starlette documentation here), you could use the allow_origin_regex argument, which allows you to define a regex pattern to match against origins that should be permitted to make cross-origin requests. Example:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origin_regex="chrome-extension://.*",
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Beware that using this solution with the regex provided above would allow any chrome extension to communicate with your FastAPI server (using cross-origin requests). Hence, if that's something that you wouldn't want to, especially in production (not during development), you may choose to use Solution 1 instead.

Chris
  • 18,724
  • 6
  • 46
  • 80
  • Thank you, Chris, for the detailed answer. This seems to be a problem with Chrome Extension because the ID is auto-generated by Chrome. I found that the only way to make the extension ID always the same is with a security key: https://developer.chrome.com/docs/extensions/mv3/manifest/key/. – eboraks Jul 26 '23 at 11:58
  • Thank you Chris, the allow_origin_regex solved the problem. – eboraks Jul 27 '23 at 12:28