CORS failure in with Python Falcon even with heads for Auth Pre-Flight
Asked Answered
T

3

5

Receiving these error when using the OPTIONS verb in Angular2 http.get(url, options), even though the appropriate CORS headers are set in Falcon Rest API.

XMLHttpRequest cannot load http://localhost:8000/names. Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response.

resp.set_header("Access-Control-Allow-Origin", "*")
        resp.set_header("Access-Control-Allow-Credentials", "true")
        resp.set_header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT")
        resp.set_header("Access-Control-Allow-Headers",
                       "Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers")

For non OPTIONS / normal http.get() requests this works fine.

Traditionalism answered 10/3, 2017 at 9:39 Comment(2)
Looks like these OPTIONS requests from Angular need to be appropriately handles by falcon? #6660519Traditionalism
Same issue for me. I have to set all to True for allow_origins_list , allow_all_methods, allow_all_headersScience
T
7

Resolved this using falcon_cors, specifically by setting allow_all_methods=True

pip install falcon-cors

from falcon_cors import CORS

cors = CORS(allow_origins_list=['http://localhost:3000'],
            allow_all_headers=True,
            allow_all_methods=True)

api = falcon.API(middleware=[cors.middleware])
Traditionalism answered 10/3, 2017 at 10:30 Comment(1)
+1. I used public_cors = CORS(allow_all_origins=True) as shown in github.com/lwcolton/falcon-corsHinson
S
1

I tried as guided by lwcolton on github here

And also set allow_all_headers=True, allow_all_methods=True

i.e. similar to above answer https://mcmap.net/q/1771070/-cors-failure-in-with-python-falcon-even-with-heads-for-auth-pre-flight but two more params to add

from falcon_cors import CORS

cors = CORS(
    allow_all_origins=True,
    allow_all_headers=True,
    allow_all_methods=True,
)

api = falcon.API(middleware=[cors.middleware])
Science answered 3/2, 2020 at 9:13 Comment(0)
B
1

I'll suggest to go through documentation for this.

Also, resp.set_header('Access-Control-Allow-Origin', '*') is not a good practice to follow in production. Have some whitelisted origins and methods and based on the request, if coming from whitelisted origin then you can put the same origin in here resp.set_header('Access-Control-Allow-Origin', req.headers["ORIGIN"]).

Below is the code I prefer-

whitelisted_origins = ["http://localhost:4200"]
whitelisted_methods = ["GET", "POST", "OPTIONS"]

class CORSComponent:

    def process_request(self, req, resp):
        success = False
        # validate request origin
        if ("ORIGIN" in req.headers):
            # validate request origin
            if (req.headers["ORIGIN"] in whitelisted_origins):
                # validate request method
                if (req.method in whitelisted_methods):
                    success = True
                else:
                    # you can put required resp.status and resp.media here
                    pass
            else:
                # you can put required resp.status and resp.media here
                pass
        else:
            # you can put required resp.status and resp.media here
            pass
        if success:
            resp.set_header('Access-Control-Allow-Origin', req.headers["ORIGIN"])
        else:
            # exit request
            resp.complete = True

    def process_response(self, req, resp, resource, req_succeeded):
        if (req_succeeded and
            "ORIGIN" in req.headers and
            and req.method == 'OPTIONS'
            and req.get_header('Access-Control-Request-Method')
        ):
            # NOTE: This is a CORS preflight request. Patch the response accordingly.

            allow = resp.get_header('Allow')
            resp.delete_header('Allow')

            allow_headers = req.get_header(
                'Access-Control-Request-Headers',
                default='*'
            )

            resp.set_headers((
                ('Access-Control-Allow-Methods', allow),
                ('Access-Control-Allow-Headers', allow_headers),
                ('Access-Control-Max-Age', '86400'),  # 24 hours
            ))

Once done, you can now add this to middleware like-

api = falcon.API(middleware=[
    CORSMiddleware(),
])

If you do not wish to use the above method, you can go ahead with falcon-cors.

from falcon_cors import CORS

cors = CORS(
    # allow_all_origins=False,
    allow_origins_list=whitelisted_origins,
    # allow_origins_regex=None,
    # allow_credentials_all_origins=True,
    # allow_credentials_origins_list=whitelisted_origins,
    # allow_credentials_origins_regex=None,
    allow_all_headers=True,
    # allow_headers_list=[],
    # allow_headers_regex=None,
    # expose_headers_list=[],
    # allow_all_methods=True,
    allow_methods_list=whitelisted_methods
)

api = falcon.API(middleware=[
    cors.middleware,
])

FYI, Methods supported by falcon 2.0.0 -
'CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'TRACE'

Bichromate answered 12/3, 2020 at 7:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.