If your frontend and Laravel backend are on different domains, you’ve probably hit the dreaded CORS policy error.
This article will show you how to configure your Laravel application to allow cross-origin requests and get your API running smoothly.
The CORS issue
When building a Laravel-based backend and serving a frontend from a different domain, one common error developers encounter is the CORS (Cross-Origin Resource Sharing) policy error, which looks like this:
Access to XMLHttpRequest at 'https://my-home.test/sb-json' from origin 'https://app.storyblok.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This error occurs because modern browsers block requests from one origin (your frontend domain) to another (your Laravel backend) unless the backend explicitly allows cross-origin requests.
Understanding CORS
CORS is a security feature implemented in browsers to prevent unauthorized websites from sending HTTP requests to your server. It controls how web pages make requests across different domains. The browser will block the request if the backend doesn't send the appropriate headers.
To fix this, the server (in this case, your Laravel application) must allow requests from your frontend domain.
Scenario
Let's say you're building a frontend logic (Vue.js or React app) hosted on https://app.storyblok.com
and making API requests to your Laravel backend hosted on https://my-home.test
. Due to the cross-origin nature of these requests, your frontend is blocked from interacting with the backend unless proper CORS headers are sent.
I encountered this issue customizing a Storyblok application when adding a Multi Options field and setting the Source to External JSON. This configuration triggers an HTTP request from a page served by the
app.storyblok.com
domain to a service at a different URL (notapp.storyblok.com
). While this is a specific scenario, it’s a common issue for anyone hosting the frontend on one domain and the backend on another.
Solving the CORS Issue
There are two main ways to resolve this issue:
- Configure CORS at the Web Server Level
- Handle CORS in Laravel (Application Level)
Both approaches aim to set three key HTTP headers correctly:
-
Access-Control-Allow-Origin
: Specifies the allowed frontend domain, for example,'https://app.storyblok.com'
. -
Access-Control-Allow-Methods
: Defines the HTTP methods that are permitted, such as'GET, POST, OPTIONS'
. -
Access-Control-Allow-Headers
: Lists the additional headers allowed, for example,'Origin, Content-Type, Accept, Authorization'
.
Setting these headers correctly is essential, regardless of your backend framework or language. Whether your backend is built with Django, Express.js, or any other framework, solving CORS issues requires configuring these headers on the server.
In this article, we’ll focus on Laravel's capabilities for easily managing these headers and effectively resolving CORS issues.
So, if you use Nginx or Apache, you can set these three headers in the configuration.
Or, if you want to set these headers at the application level, you can set them via Laravel configuration, following the next steps.
Handle CORS in Laravel (Application Level)
Laravel offers built-in support for handling CORS through the HandleCors middleware. This approach is often more flexible and maintainable, especially if you're working in a shared hosting environment where you may not have access to the server configuration.
Under the hood, the Laravel Framework uses the package https://github.com/fruitcake/php-cors to manage the Cors Headers correctly.
Here’s how you can solve the CORS issue within Laravel itself: you need to change the default values of the HandleCors middleware. By default the options doens't allow HTTP call from a frontend delivered by a different domain.
To customize the options you have to "publish" the Cors configuration in your config directory so that yo can change the options.
php artisan config:publish cors
This will create the config/cors.php
file with the default values in your application.
Open the config/cors.php
file and adjust the settings.
The use case we want to set up as an example is:
- we want to allow the JavaScript frontend HTTP call from the
app.storyblok.com
hostname; - we want to allow the HTTP
GET
method; - we want to enable the access only for the
/sb-json
path. With these requirements, you can edit the value forpaths
,allowed_methods
, andallowed_origins
:
<?php
return [
/*
|--------------------------------------------------------------------------
| Cross-Origin Resource Sharing (CORS) Configuration
|--------------------------------------------------------------------------
|
| Here you may configure your settings for cross-origin resource sharing
| or "CORS". This determines what cross-origin operations may execute
| in web browsers. You are free to adjust these settings as needed.
|
| To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
|
*/
'paths' => ['sb-json'],
'allowed_methods' => ['GET'],
'allowed_origins' => ['https://app.storyblok.com'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
];
This will allow cross-origin requests from https://app.storyblok.com
to the Laravel backend. You can also modify the allowed_headers
, and other options as needed.
References
- Official Laravel Documentation for set up routes and handling CORS configuration: https://laravel.com/docs/11.x/routing#cors
- Cross-Origin Resource Sharing (CORS): https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
- PHP CORS library: https://github.com/fruitcake/php-cors
Conclusion
CORS is a crucial security feature, but it can be a challenge when your frontend and backend are served from different domains. In Laravel, you can solve this by configuring CORS either at the web server level or within the application itself. The built-in middleware makes it easy to customize CORS settings to meet your project’s needs.
By following the steps above, you’ll be able to resolve the CORS error and enable seamless communication between your frontend and Laravel backend.
Happy coding!
Top comments (1)
Good article, thanks!
To anyone still facing issues on this, make sure you don't have any trailing slashes '/' after your urls for 'allowed_origins'. Lost a lot of time and energy on that lol.