Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Zeit (Vercel) Now serverless authenticated requests failing because of CORS

I'm not able to correctly handle CORS issues when doing either PATCH/POST/PUT requests from the browser sending an Authorization header with a Bearer token (this works correctly outside of the browser and for GET requests) in Zeit Now serverless.

I'm using Auth0 for the authorization side if that helps.


This is my now.json headers section, I've tried a lot of combinations for these, but neither succeeded from the browser.

Headers in now.json


  1. I tried using npm cors package without success
  2. Tried to add routes in now.json
  3. Tried setting headers at the top of the serverless function using res.addHeader()
  4. Also tried handling OPTIONS request manually doing variations of this:

OPTIONS method custom handling

Finally, this is the error that I get

Access to XMLHttpRequest at 'https://api.example.org/api/users' from origin 'https://example.org' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

Not sure what I'm wrong or how to handle this properly.

like image 783
GMaiolo Avatar asked Apr 14 '20 20:04

GMaiolo


People also ask

What is CORS header?

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources.

What is cross-origin error?

Cross-Origin Resource Sharing (CORS) is a standard that allows a server to relax the same-origin policy. This is used to explicitly allow some cross-origin requests while rejecting others. For example, if a site offers an embeddable service, it may be necessary to relax certain restrictions.


1 Answers

I have pretty much similar issues with CORS and Vercel serverless function.

After lots of try → failed process I just found solutions for this.


Solutions

tldr

The simplest solution, just using micro-cors.

And having an implementation something like;

import { NowRequest, NowResponse } from '@now/node';
import microCors from 'micro-cors';

const cors = microCors();

const handler = (request: NowRequest, response: NowResponse): NowResponse => {
  if (request.method === 'OPTIONS') {
    return response.status(200).send('ok');
  }

  // handle incoming request as usual
};

export default cors(handler);

Longer version, but without any new dependency

using vercel.json to handle request headers

vercel.json

{
  "headers": [
    {
      "source": "/.*",
      "headers": [
        {
          "key": "Access-Control-Allow-Origin",
          "value": "*"
        },
        {
          "key": "Access-Control-Allow-Headers",
          "value": "X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept"
        },
        {
          "key": "Access-Control-Allow-Credentials",
          "value": "true"
        }
      ]
    }
  ]
}

After self tried, there are 2 keys important in an above setting,

  1. You must set Access-Control-Allow-Origin as what you want
  2. In Access-Control-Allow-Headers you must include Access-Control-Allow-Origin into its value.

then in serverless function, you still need to handle pre-flight request as well

/api/index.ts

const handler = (request: NowRequest, response: NowResponse): NowResponse => {
  if (request.method === 'OPTIONS') {
    return response.status(200).send('ok');
  }

  // handle incoming request as usual
};

I would suggest to read through the code in micro-cors, it's very simple code, you can understand what it'll do in under few minutes, which makes me didn't concern about adding this into my dependency.

like image 61
hamcompe Avatar answered Oct 16 '22 18:10

hamcompe