Handling Cross-Origin Resource Sharing (CORS) Requests in Laravel 7
Time to read: 4 minutes
By default, browsers implement a same-origin policy that prevents scripts from making HTTP requests across different domains. Cross-Origin Resource Sharing (CORS for short) provides a mechanism through which browsers and server-side applications can agree on requests that are allowed or restricted.
From version 7, the Laravel framework comes with first-party support for sending CORS headers using Middlewares.
In this tutorial, we'll be building a simple Vue.js app powered by Laravel to learn about CORS. We will take a deep-dive into the various configuration options needed by Laravel to handle CORS OPTIONS requests and see how some of these options affect our application.
Prerequisites
In order to complete this tutorial, you will need the following:
- Familiarity with the Laravel framework
- An existing project with Laravel framework version >= 7.0.
- Vue CLI installed.
Getting Started
Create a new folder to hold both the Laravel API and the Vue project, and create the Laravel project with the commands below:
The Laravel project created includes a generic CORS configuration at $APP_FOLDER/config/cors.php
which can be fine-tuned to meet your application needs. Here is a sample configuration file generated for a new Laravel application (without the comments).
To inspect the API response headers from the Vue frontend, modify the `exposed_headers` array to use the wildcard ` character as shown below:
Next, we will set up our API routes to respond to requests with fake data. Open the api routes file at `routes/api.php`, and replace its content with the code block below.
Setting up the Vue Frontend
Create a new Vue project in the laravel-cors
folder by running vue create frontend
. Select the default preset. In the created frontend folder, open the HelloWorld.vue
file (at src/components/HelloWorld.vue
) and replace its contents with the code block below:
The code above makes an HTTP request to the /items
route we created back in our Laravel application and logs all of the response headers it receives.
To try things out, serve the Laravel application by running php artisan serve
in the server folder from your terminal.
While the server is running, launch the Vue app by changing into the frontend directory and running yarn serve
.
Visit the Local URL reported by yarn serve
in your browser and open the page console.
You should see the response headers in your console as shown in the screenshot below:
Enabling CORS for a Route Prefix
The paths option lets you specify the routes or resource paths for which you want to send CORS headers. In the configuration above, CORS headers are enabled for all routes with the “api” prefix. Removing that prefix or changing it to something else (e.g 'paths' => ['endpoints/*']) disables CORS for our API endpoints and we get an error similar to the one shown below:
Paths could be exact string matches (e.g /public/img/photo.img
) or specified using the “*” wildcard (e.g /public/*
or /api/*
). Additionally, you can enable CORS for files in a given folder and all of its subfolders using the pattern: public/**/*
.
Looking up Allowed HTTP Methods
allowed_methods
specifies the HTTP request methods allowed when accessing a resource. The methods you add here are returned in the “Allowed-Methods” header when a client makes a preflight request to the Laravel application. By default, Laravel enables CORS for all HTTP methods (by using the “*” value).
For example, replacing the wildcard “*” character in the allowed_methods with “POST” will break our frontend code (since it is making “GET” requests to the server).
Restricting Allowed Hosts
The allowed_origins
dictates the “origins” that are allowed to access the resources (origin here refers to the combination of scheme, domain, and port of the URL). Like the options above, it also allows for wildcard matching (e.g *example.com will allow example.com and any of its subdomains to access the resource). It is set to allow all origins by default.
NOTE: When not using a wildcard, the origin must be specified in full (e.g http://example.com is valid, example.com is not).
Restricting Allowed Hosts with Regular Expression
Using the allowed_origins_patterns
option, you can specify your allowed origins using Regular Expression. It is useful when you want match patterns more complex than the “*” wildcard supported by allowed_origins. The values provided here must be a valid preg_match() pattern. Also, take care to avoid being accidentally inclusive. For example, /https?:\/\/example\.com/
is valid for both https://example.com and https://example.com.hackersdomain.com. A better pattern is /https?:\/\/example\.com\/?\z/
which limits it to domains ending with example.com (or with an optional slash at the end).
Configuring Allowed Headers
The allowed_headers
option defines the HTTP headers that will be allowed in the actual CORS request. It sets the Access-Control-Allow-Headers header sent as a response to preflight requests containing Access-Control-Request-Headers. The generated configuration defaults to allowing all HTTP headers as well.
Exposing Custom Headers
Using exposed_headers
, you can allow your API clients to access custom HTTP headers that are not safe-listed by CORS by default. For example, you may want to expose the X-RateLimit-Remaining
and X-RateLimit-Limit
headers set by Laravel’s throttle middleware to indicate how many more requests a client can make within the given time frame.
There are only seven HTTP headers that are safe-listed by CORS (i.e., Cache-Control, Content-Language, Content-Length, Content-Type, Expires, Last-Modified, Pragma) so you will have to include any other header your application needs to expose in the exposed_headers
array.
Caching CORS Responses
The value of the max_age
option determines how long (in seconds) a client can cache the response of a preflight request. Laravel sets it to 0 by default. Browsers will ignore the max_age
value if it is longer than their maximum limit (24 hours for Firefox, 2 hours for Chromium >= v76).
HTTP Sessions over CORS
supports_credentials
allows sending cookies and sessions (which rely on cookies also) over CORS requests. It sets the Access-Control-Allow-Credentials
and cannot be true when all origins are allowed (i.e., when allowed_origins
is the wildcard (*) character).
Conclusion
Configuring CORS can be a chore sometimes. Laravel now makes it easier with an “out-of-the-box” setup by leveraging the laravel-cors package.
If you are looking to explore CORS generally,
- This blog post dives into some of the security issues around misconfiguring CORS
- The MDN docs have an article on it with relevant HTTP headers.
Michael Okoko is a software engineer and computer science student at Obafemi Awolowo University, Nigeria. He loves open source and is mostly interested in Linux, Golang, PHP, and fantasy novels! You can reach him via:
- Email: michaelsokoko@gmail.com
- Github: https://github.com/idoqo
- Twitter: https://twitter.com/firechael
Related Posts
Related Resources
Twilio Docs
From APIs to SDKs to sample apps
API reference documentation, SDKs, helper libraries, quickstarts, and tutorials for your language and platform.
Resource Center
The latest ebooks, industry reports, and webinars
Learn from customer engagement experts to improve your own communication.
Ahoy
Twilio's developer community hub
Best practices, code samples, and inspiration to build communications and digital engagement experiences.