Home » Laravel » How to Fix Cross Origin Request Blocked in Laravel

How to Fix Cross Origin Request Blocked in Laravel

Such an error may appear in the browser JavaScript console when the browser blocks API requests because the API is not located on the same domain as your application. If you want to access an API from a different domain, your browser uses the policy for Cross-Origin Resource Sharing (CORS) to determine whether the request is allowed or not.

In this short article, I will explain how it works, why you get the error with the message “Cross Origin Request Blocked” in Laravel, and how to fix it.


Table of Contents

What is CORS, and How Does it Work?

The browser sends the Origin header in any request to the server, which contains the domain from which the request is made along with the scheme. For example, https://haait.net. The server analyzes this header and may send several headers in the response that determine which domains can use this response. This includes the following headers:

  • Access-Control-Allow-Origin origin, which is allowed to send requests and use responses;
  • Access-Control-Request-Method – HTTP methods that are available;
  • Access-Control-Allow-Headers – Additional headers that are available;
  • Access-Control-Allow-Credentials – reflects if the cookies are enabled.

However, this error is most often caused by the Access-Control-Allow-Origin header. This is just a header, and it doesn’t prevent you from making the request manually. But the browser compares its value, and if the current origin in the browser address bar and in the header do not match, then you get an error and the request is not executed. Such protection is needed so that you, as the site owner, can prohibit other sites from embedding your API.

Of course, you can work around this locally, but when your site is opened by regular users in their browsers, requests prohibited by CORS will not be executed. You can read more about CROS here. Now let’s look at how to solve this problem.

CORS also works for other resources, such as JavaScript scripts and images. However, in my tests, CORS rules were not applied to images or scripts unless the crossorigin=”anonymous” attribute was set for them. Therefore, it is advisable to use other methods to protect images.

Next, let’s look at an example. Let’s say we have an app.local host that hosts the authorization API. We want to make the request http://app.local/api/login from the origin http://app1.local. When making such a request, you may get the following error:

There are three possible reasons for the error above:

  • The Access-Control-Allow-Origin header was sent neither by the web server nor Laravel.
  • Laravel sends the Access-Control-Allow-Origin header with the value of app.local which means that the request is allowed only for app.local.
  • The web server and Laravel send the Access-Control-Allow-Origin headers, and they conflict with each other.

How to Fix Cross Origin Request Blocked in Laravel

1. CORS in Laravel

Let’s look at the first possible reason. You can check which headers were sent by the server using curl. For example:

curl -I -H "Origin: http://app1.local"  http://app.local/api/login

Here, using -I we specify that we want to receive only response headers, and using -H we send the Origin header, which is sent by the browser to identify the host from which the request is made. In this case, requests are only allowed from app.local:

Everything you need to provide CORS headers is installed and configured in Laravel 10 by default. The fruitcake/laravel-cors package is used to send headers, and the \Illuminate\Http\Middleware\HandleCors Middleware is globally enabled by default for both API and regular requests in the app/Http/Kernel.php file.

app/Http/Kernel.php    protected $middleware = [         // \App\Http\Middleware\TrustHosts::class,         \App\Http\Middleware\TrustProxies::class,         \Illuminate\Http\Middleware\HandleCors::class,         \App\Http\Middleware\PreventRequestsDuringMaintenance::class,         \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,         \App\Http\Middleware\TrimStrings::class,         \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,     ];

The CORS configuration is located in the config/cors.php file. Here, all origins are allowed by default:

config/cors.phpreturn [     "paths" => ["api/*", "sanctum/csrf-cookie"],     "allowed_methods" => ["*"],     "allowed_origins" => ["*"],     "allowed_origins_patterns" => [],     //... ];

But in the case shown in this example, the settings are changed and requests are allowed only from the http://app.local origin.

You can put * in the value of the allowed_origins parameter to allow requests from all domains. You can also list the list of domains from which you can make API requests here. For example, let’s allow access for app.local and app1.local:

config/cors.php'allowed_origins' => ['http://app.local', 'http://app1.local'],

In addition,  you can specify a regular expression, which will be used to check whether the current domain is allowed in the allowed_origins_patterns field. After making changes, you should clear the configuration cache:

php artisan config:clear

Note, that only one header with the name Access-Control-Allow-Origin can be sent, and it must contain only one origin. So the middleware has to analyze whether the origin from which the request is made is in the list of allowed domains and, if so, send it in the header. You can verify this by running the following curl commands after making the changes shown above:

curl -I -H "Origin: http://app.local"  http://app.local/api/login
curl -I -H "Origin: http://app1.local"  http://app.local/api/login

Here is the code for adding the Access-Control-Allow-Origin header, which is located in the vendor/fruitcake/php-cors/src/CorsService.php file:

2. CORS in Nginx

If your web server sends CORS headers and Laravel sends them, then a situation may arise when the browser will receive two identical headers. Let’s say that sending CORS headers to Laravel is configured, and the Nginx configuration looks like this:

/etc/nginx/conf.d/laravel.confadd_header Access-Control-Allow-Origin "*"; add_header Access-Control-Request-Method "POST, GET, OPTIONS";

The configuration above allows requests from all origins. But you will receive a CORS error even if both headers or one of the headers allow requests from the current origin. For example:

curl -I -H "Origin: http://app1.local"  http://app.local/api/login

You should disable the sending of CORS headers either in Laravel or in Nginx to fix this. To disable sending to Laravel, just comment out \Illuminate\Http\Middleware\HandleCors Middleware in app/Http/Kernel.php:

app/Http/Kernel.php//\Illuminate\Http\Middleware\HandleCors::class,

To disable sending headers to Nginx, find in the configuration of your virtual host in the PHP processing block or globally the lines that start with add_header Access-Control- and comment them out. For example:

/etc/nginx/conf.d/laravel.conf#    add_header Access-Control-Allow-Origin "*"; #    add_header Access-Control-Request-Method "POST, GET, OPTIONS";

However, the add_header directive only works for requests with 2xx and 3xx status codes. For requests that return 5xx, headers will not be sent even if they are configured. Read more about the add_header directive here. So it is better to handle CORS for APIs in Laravel. After making changes, Nginx must be restarted:

sudo systemctl restart nginx

Regardless of the method you choose, you can check again which headers are received using curl:

curl -I -H "Origin: http://app1.local"  http://app.local/api/login

And also make sure that there are no errors in the browser as well:

Wrapping Up

In this short article, I’ve shown you how to fix the cross-origin request blocked error in Laravel. This is a rather complicated topic; it may depend more on the web server than on Laravel. But now you know where to look to find its cause.

Leave a Comment