Skip to content

(py#fast-api, ts#trpc-api, ts#smithy-api): REST API CORS preflight OPTIONS request allows * when POST etc restricts origins with restrictCorsTo #377

@cogwirrel

Description

@cogwirrel

Current Behavior

As of #371, we have a restrictCorsTo method on REST and HTTP APIs which is designed to scope down the allowed origins to the supplied websites for requests from browsers.

For REST APIs, if restrictCorsTo is used, we manage CORS headers via an ALLOW_ORIGINS environment variables in the lambda handlers. This is due to API Gateway REST APIs deferring to the integration to return CORs headers. Additionally by default lambda handlers are registered as individual integrations for the specific method they implement, eg POST /foo, and are not registered to handle OPTIONS requests - instead we use API Gateway REST APIs CORS options which adds mock integrations for these requests.

API Gateway REST APIs appear to have a limitation where only a single CORS origin can be specified at deploy-time for the OPTIONS mock integrations registered by configuring CORS. To ensure both local website development servers and deployed websites can access the API, we therefore need to open this single origin to '*' (eg we cannot restrict to both http://localhost:4200 and https://xxxxxx.cloudfront.net).

In the case that the API is then called from an origin which is not permitted by the ALLOW_ORIGINS environment variable in the lambdas, the preflight OPTIONS request sent by the browser will succeed as it permits '*', but the actual request will then be blocked by the browser due to the origin being incorrect. This defeats the purpose of restricting the origins, since the preflight OPTIONS request is designed to prevent browsers from initiating mutative actions when they invoke APIs that are blocked by the CORS headers. The server may successfully perform the mutative action in this case and return status 200, but the browser will consider it failed due to the CORS restrictions.

Expected Behavior

restrictCorsTo method should restrict preflight OPTIONS requests to the provided origins (and local dev servers).

Steps to Reproduce

  1. Generate a trpc api, fastapi or smithy api and add some mutative operation as a POST request
  2. Generate a website or cloudfront distribution
  3. Call restrictCorsTo to restrict cors to the specific cloudfront distribution
  4. Deploy, but invoke the mutative operation from a different domain (eg in the browser console from amazon.com)
  5. Observe the preflight OPTIONS request succeeds, but the POST request is blocked.
  6. Observe the mutative operation is still performed by the backend due to the blockage being client side in the browser after the response is received from the backend

Nx Report

N/A

Failure Logs

Additional Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions