Search code examples
javascriptcorsauthorizationserverlessvercel

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.


Solution

  • I was able to bypass this issue using micro-cors.

    I checked its code and it doesn't differ that much of what I attempted to do myself by using res.setHeader manually, probably missed something I guess.

    Nevertheless I don't understand why the settings in now.json were not working correctly and I need to perform this manually in the serverless function.

    Anyways, in case someone else finds this post, I ended up with something like this:

    import micro from "micro-cors";
    
    function MyApi(req, res) {
      if (req.method === "OPTIONS") {
        return res.status(200).end();
      }
      // handling other requests normally after this
    }
    
    const cors = micro();
    
    export default cors(MyApi);
    

    I'll probably will try again with a self-written solution in order to understand better what went wrong and also because I don't want an extra dependency.

    Will update this answer if I do that.


    Edit: After checking a bit deeper I found that another issue was the library express-jwt specifically changing the res object when the jwt parse failed.

    I had a small middleware that was breaking everything by doing:

    await authValidateMiddleware(req, res);
    

    When that await failed, it broke everything down the line because express-jwt changed the res headers unknowingly (setting the error) and then I tried to set the res headers manually trying to handle the error correctly myself, therefore throwing issues about "changing the res headers more than once".