3

I have installed the barryvdh/laravel-cors package in my Laravel 5.6 app, and added the relevant lines to my middeware groups in app\Http\Kernel.php, and published the config file as per the instructions.

I have disabled CSRF checks for my api routes in VerifyCsrfToken.php with

protected $except = [
    'api'
];

I have set the config file as below:

'supportsCredentials' => false,
'allowedOrigins' => ['https://developer.mozilla.org'],
'allowedHeaders' => ['Content-Type', 'X-Requested-With'],
'allowedMethods' => ['GET', 'POST', 'PUT',  'DELETE']
'exposedHeaders' => [],
'maxAge' => 0,

...and I have have run a test POST request in Postman using "Origin: https://developer.mozilla.org" in the header.

It's working- fine. And if I change that Origin key to anything other than https://developer.mozilla.org it throws the "Not allowed in CORS policy." error. Which is what I'd expect, as per the config- fine.

BUT if I change the config line to

'allowedMethods' => ['GET']

(ie. allow only GET requests), and run the same POST request in Postman... it still works.

Why? Why doesn't it respect the limitation imposed in the config for allowedMethods?

Inigo
  • 8,110
  • 18
  • 62
  • 110
  • Postman isn’t a browser. Cross-origin restrictions are only enforced by browsers. So for Postman it doesn’t matter whether or not the server is CORS-enabled. See the answers at https://stackoverflow.com/questions/43432743/will-cors-policy-prevent-resource-access-from-non-browser-requests/43432787#43432787 and https://stackoverflow.com/questions/45069689/cors-enabled-server-not-denying-requests/45069745#45069745 – sideshowbarker Jul 19 '18 at 22:16
  • I don't think this answers the question. This is not about whether the request comes from Postman or a Browser; I think this is a problem with the `barryvdh/laravel-cors` package – Inigo Jun 18 '19 at 13:33
  • You wrote, *“run the same POST request in Postman... it still works”*; the point is that no matter what changes your make to your laravel-cors config, you will always still be able to make any request to that API with Postman. Your laravel-cors config will have zero effect on what you can do with that API through a Postman request. Specifically, Postman will never respect any limitation imposed by the laravel-cors config for allowedMethods (nor allowedHeaders, nor anything else you set in your laravel-cors config). – sideshowbarker Jun 19 '19 at 01:38
  • Oh I see what you're getting at. Yeah, but I can just add an `Origin` parameter in the Postman header to emulate my app- which is what I'm doing- then it *does* respect the allowedHeaders. In any case, mentioning Postman was probably a red-herring here- exactly the same problem still occurs with the ajax request from my app. My question still stands. Note this issue has also been raised [here](https://github.com/barryvdh/laravel-cors/issues/260) and [here](https://github.com/barryvdh/laravel-cors/issues/339). To date, no answers have been provided... – Inigo Jun 19 '19 at 11:56
  • Yeah barryvdh answered: *“Are you testing on cross-domain? It doesn't block anything, only the browser blocks it when it's cross domain and the header are not there.”*. laravel-cors doesn’t ever make any blocking happen on the server side. Blocking is only done on the client side, by the browser. And you can’t change the value of the Origin header in a request made from frontend JS code running in a browser. So if as you say you *“change that Origin key to anything”* then you’re not actually testing a cross-origin request from frontend JS code but instead you’re testing… something else. – sideshowbarker Jun 19 '19 at 12:26
  • Please forget I ever mentioned Postman. I am testing this using an ajax request from my app with JS, which as you say, fixes the value of the `Origin` header. / *laravel-cors doesn’t ever make any blocking happen on the server side.* / Right. I guess this instead sends an `Access-Control-Allow-Methods` header, right? (Bear with me I'm learning here). [This answer](https://stackoverflow.com/a/20479141/521392) States "*this header is only used on CORS preflight requests*"... OK now we're getting somewhere.. so I guess the problem is that my app isn't sending a CORS preflight request first..? – Inigo Jun 19 '19 at 17:51
  • Yeah, if the POST request your frontend code makes isn’t one that triggers browsers to do a CORS preflight, then browsers will just send the POST directly, even if the value you’ve set for allowedMethods doesn’t include POST. In other words, the Access-Control-Allow-Methods response header is never sent nor received in that case, so the browser never consults that header’s value. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests explains what characteristics trigger a CORS preflight, but basically it amounts to whether your code adds any custom headers to the request. – sideshowbarker Jun 19 '19 at 22:22

1 Answers1

3

In the CORS protocol, servers themselves never do any blocking — instead the blocking is done by browsers, and only by browsers, and only for the case of frontend JavaScript code running in a browser (and not, e.g., when using Postman or something to send the request).

So the only effect of setting allowedMethods is to cause a server to send the Access-Control-Allow-Methods header with a certain value. It doesn’t otherwise make the server itself do blocking.

Browsers check the value of that header only when it’s in a response to a CORS preflight OPTIONS request. And so only in that case, if the value of Access-Control-Allow-Methods in the OPTIONS response doesn’t contain a match for the method your code’s trying to use, the preflight fails.

But if your frontend code’s request isn’t one that triggers a preflight, browsers send it directly, even if the value set for allowedMethods doesn’t include the request method name your code uses.

In other words, Access-Control-Allow-Methods isn’t sent nor received in a case where you have a POST request in your frontend code, but that POST has no characteristics that trigger a preflight. So the browser never consults the Access-Control-Allow-Methods header’s value in that case.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Preflighted_requests lists the characteristics that will trigger a CORS preflight, but in the case of a POST or GET request, it basically amounts to whether your code adds any custom headers to the request.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197