0

I'm running into a weird error with cors when doing a request from a react page to my back end that uses arc.codes framework to run. This is the complete error:

Access to fetch at 'http://localhost:3333/api/endpoint' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

My front-end code that made the request is the following:

const options = {
        method: 'GET',
        headers: {
            'Authorization':'Bearer token'
        },
    };
const response = yield call( fetchJSON, `${process.env.REACT_APP_BACKEND_URL}/contractormonths`, options );

Back end code that processes the requests:

.arc manifest file:

@app
my-app

@http
get /api/contractormonths

index.js file at /get-api-contractormonths

const arc = require('@architect/functions');
const { authorization } = require('@architect/shared/oauth');

async function route(request){
  return {
      cors: true,
      json: {'message':'Hello world!'}
  };
}

exports.handler = arc.http.async(authorization, route);

Authorization function also returns an object with a property cors: true

What I've already tried and learned:

  • I think the request doesn't get to the GET handler function in the back
  • When I removed the auth middleware (In the back) and the auth header (In the front) it works!
  • This is probably related to the preflight request made by the browser (When it's a simple GET with no Headers it doesn't send the preflight request but it does when using the auth header)
  • The preflight request is sending an OPTIONS request to my backend, I can confirm this because adding the OPTIONS request handler in my backend gets the requests instead of the GET handler

What can I do to handle these preflights requests in my back-end? Do I have to write an OPTIONS request handler to all of my current endpoints? Is there a way to disable the preflight request? Is it OK to disable the preflight request? Am I missing another important thing and overcomplicating this?

David Núñez
  • 51
  • 1
  • 4

1 Answers1

0

It's hard to tell without seeing the code for your authorization function but that is where the root of the problem lies. You mentioned in your question that:

Authorization function also returns an object with a property cors: true

but you don't actually want to return an object from this function unless you are failing the authentication step.

An example authorization method could look like this:

module.exports = async function auth (req, res, next) {
  // Do the OAuth Dance
  const oauth = oauthDance()
  if (!oauth.authenticated) {
    return {
      status: 401,
        json: { errors: [ 'authorization_failed' ] }
    }
  } else {
    // Oauth succeeded so let's add the token to the request
    // for the next function in the chain
    req.token = oauth.token
    next()
  }
}

That's some pretty contrived pseudo code but my suspicion is the return from your authorization method is short circuiting the chain and that's why the preflight check fails. Using next() to continue on to the next function in the chain should fix your issue.

Simon MacDonald
  • 23,253
  • 5
  • 58
  • 74
  • You're right, the problem was in the authorization function, what I was trying to say with "Authorization function also returns an object with a property cors: true" is that when the authorization middleware fails I also return an object with cors: true. But in the end some unhandled exception was occurring in the authorization function so the "next" function was never called. – David Núñez Dec 20 '22 at 20:01