0

I have been searching for an answer to what seems like a very basic problem. I am attempting to make a cross origin HTTP request on a local host using Axios within the React framework. The server side runs on a CodeIgniter framework and uses chriskacerguis's codeigniter-restserver. I have configured an .htaccess file to set Access-Control-Allow-Origin to '*'.

My GET requests work without any issue. The problem arises when I attempt to make a POST request. I have tried using both fetch() and Axios. I get this error message in Chrome's console:

OPTIONS http://localhost/api/login 401 (Unauthorized)
(...)
localhost/:1 Access to XMLHttpRequest at 'http://localhost/api/login' from origin
'http://localhost:3000' has been blocked by CORS policy: Response to preflight request
doesn't pass access control check: It does not have HTTP ok status.

I am confident that the server side code works since I am capable of making successful POST requests using Insomnia. Although I have read on many forums that a 401 error is not related to a CORS issue, it seems to me like it has to be CORS-related since my HTTP requests work in Insomnia.

After many attempts at changing the headers and different configuration options, here is the code I have on the client side:

axios.post(api_url+'login', {
        headers: {
            'accept': 'application/json',
            'content-type': 'application/json',
        },
        data: {
            email: this.state.email,
            password: this.state.password
        },
        crossDomain: true,
        withCredentials: true,
        auth: {
            username: 'admin',
            password: '1234'
        }
    })
    .then(res => {
        console.log(res);
    })
    .catch(err => {
        console.log(err);
    });
}

It seems to me as though the 401 is returned on the initial OPTIONS request. I do not understand why this is happening since I've come to understand that the OPTIONS request should not required authentification. I am also capable of completing an OPTIONS request in Insomnia without any issue.

This is my first attempt at building both a REST API and a React app. I have spent many hours trying to make this basic request work and I've come to the conclusion that there must be something very obvious that I'm missing... many thanks for reading and commenting.

paulchoix
  • 11
  • 1
  • 3
  • What is the error code returned by an HTTP OPTIONS call to your service? Is should be inside the "ok status" range (a 200, or a 204) – keul Nov 23 '19 at 16:27
  • Have you enabled cors on your codeigniter server for options? https://stackoverflow.com/questions/25702991/enabling-cors-in-codeigniter-restserver-by-chriskacerguis – azium Nov 23 '19 at 16:28

2 Answers2

1

The pre-flight request actually does the following:

A CORS preflight request is a CORS request that checks to see if the CORS protocol is understood and a server is aware using specific methods and headers.

Source: https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request

This has nothing to do with authentification in your case, but with the following headers received from the server:

Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: *

If OPTIONS isn't in the Allow-Methods, you'll get an error and if your frontend's host and port isn't in the Allow-Origin header, you'll get an error too. For developing, it's fine to set the Allow-Origin to a wildcard (*), but don't do this in production.

To enable CORS in codeignter, you have to modify your rest.php like follows:

//Change this to TRUE
$config['check_cors'] = TRUE;

//No change here
$config['allowed_cors_headers'] = [
  'Origin',
  'X-Requested-With',
  'Content-Type',
  'Accept',
  'Access-Control-Request-Method'
];

//No change here
$config['allowed_cors_methods'] = [
  'GET',
  'POST',
  'OPTIONS',
  'PUT',
  'PATCH',
  'DELETE'
];

//Set to TRUE to enable Cross-Origin Resource Sharing (CORS) from any source domain
$config['allow_any_cors_domain'] = TRUE;


//Used if $config['check_cors'] is set to TRUE and $config['allow_any_cors_domain'] is set to FALSE. 
//Set all the allowable domains within the array
//e.g. $config['allowed_origins'] =['http://www.example.com','https://spa.example.com']

$config['allowed_cors_origins'] = [];

Source: https://stackoverflow.com/a/41206621/4934937

maio290
  • 6,440
  • 1
  • 21
  • 38
  • I can't believe I hadn't seen the answer in your source before now. That was it! Just needed to treat the JSON input within CodeIgniter and it works perfectly now. Thanks for the quick answer!! – paulchoix Nov 23 '19 at 17:50
0

Adding OPTIONS to the allowed methods and the following "if" did the trick for me:

header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
if ( "OPTIONS" === $_SERVER['REQUEST_METHOD'] ) {
    die();
}

Full answer:: https://stackoverflow.com/a/25703960/6052406