Diving into Cross-Origin Resource Sharing


June 21st, 2023

Diving into Cross-Origin Resource Sharing

Learn how to harness the power of Laravel CORS in this tutorial. Discover what it is and unlock its potential for seamless cross-origin resource sharing.

Laravel has supported CORS for quite a while; however, until more recent versions, it has been from third-party packages only. Let's dive into CORS in Laravel, what it is, and why it is important.

CORS stands for Cross-Origin Resource Sharing. It is a mechanism that allows you to make requests to a different domain than your own securely. It defines a set of headers the server can use to control which origins can access its resources. But what does this mean to you?

As someone who builds a lot of APIs, I am very used to CORS. It has become second nature at this point. Laravel, by default, has CORS support built in, where it will read from config/cors.php to programmatically build up the protection rules based on the values configured. Let's walk through the options in this file to see what they mean to us.


Our first option is paths, which by default has the following:

'paths' => ['api/*', 'sanctum/csrf-cookie'],

In this option we are telling the CORS middleware to match any requests listed here and allow CORS to proceed to the next check. If the incoming request does not match any pattern we add to our configuration, we will automatically block any requests from external hosts.


Our next option is the allowed methods, which by default is configured in the following way:

'allowed_methods' => ['*'],

By default Laravel will allow any method to be passed in externally, meaning that an API integration does not need any special considerations. You can be as strict or relaxed as you want here. This is entirely down to you. I usually keep the default here, as most of the APIs I typically build want complete external control in some respects. If we changed this to:

'allowed_methods' => ['GET', 'POST','PUT','PATCH'],

It would mean that we want to reject any external requests that are explicitly a DELETE request or a request not listed in the CORS configuration. If you have a public read-only API, you are more likely to configure this differently.


Next, we look at the allowed origins, which by default are configured like so:

'allowed_origins' => ['*'],

What we are saying by default is that we will allow connections or requests to come in from any origin (aka IP address or server). If we were building internal APIs, we would look to configure this to either an IP range or limit this to specific domains. This helps protect you against people making requests from locations you may not want them to. Again, if your API is public, you will likely keep this as it is. Please remember this setting should you have CORS issues when integrating with your API.

You can use an additional configuration part to be less specific and lean on regex matching more. This is the allowed origins patterns, where you can add regex to check the origin of a request to see if they are being accepted or rejected. By default, it is an empty array, as you will want to be careful here:

'allowed_origins_patterns' => [],


You can be as strict or as relaxed as you need to be with headers when it comes to CORS configuration. This part of the configuration allows you to set what headers are allowed from third-party origins when a request comes in. Let's say you want to be very specific so that external parties can only make requests in specific content types or enforce accepting particular content types. This is unlikely but a good example. In some APIs, especially a few years ago - I used to add application middleware that would check if they were accepting JSON and reject with a warning if it wasn't in place. We can do the same thing here - but for third parties only. The default in Laravel looks like the following, though:

'allowed_headers' => ['*'],

Exposing Headers

Exposing Headers is a funny one. Chances are you will not need it - but if you do, it will take ages to figure out that you need it! The default configuration looks like the following:

'exposed_headers' => [],

So to understand what to add here, if you need it, you need to understand what or who is integrating with you. Typically the CORS issues here would be related to browser rules with CORS and CORS requests, where headers are being stripped out as they are deemed unsafe. Let's say that you have headers that are non-default such as: X-VAPOR-ENCODE or X-GITHUB-ID or something to that effect, by default these will be stripped out on CORS requests, which could, in turn, could cause unintended side effects you were not aware of.

Max Age

We can configure how long clients can cache resources for using this option in the CORS configuration.

'max_age' => 0,

By default, we are configuring this so clients do not cache anything from our application. This, however, is flexible, as only integrations such as browsers will fully respect this.


Finally, we have the support credentials option. This option, by default, is set to false:

'supports_credentials' => false,

What we are configuring here is, do we want to allow authentication from third-party origins. This is something to be very considerate about because if you set this to true, people can log in and get authentication details back. If we set this to true, then you will open yourself up for potential phishing attacks on your users, which can lead to further issues. If you have to set it to true, then ensure that the other options are precise so that you can control who can do this. The last thing you want to do is allow all requests from any origin that supports credentials!

This was only a walkthrough of what can be done with the configuration and what each option means to you and your application. Always ensure you are careful when configuring CORS configuration and rules because you do not want to open yourself and, by extension, your users up to any potential attacks due to the wrong configuration.

Filed in:

Steve McDougall

Technical writer at Laravel News, Developer Advocate at Treblle. API specialist, veteran PHP/Laravel engineer. YouTube livestreamer.