90

I'm new to Laravel and am doing some Laravel 5.3 Passport project with OAuth2.0 password grant. When I curl the API with the params it responds with token. However, in browser it needs an additional security that the endpoint should add because my request is coming from localhost while the API is located in my VM. Here's the error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 400.

I know what the issue is but I don't know where to put to include that header since this is a third party app.

Thank you in advance experts. Please help.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
user3856437
  • 2,071
  • 4
  • 22
  • 27
  • 1
    Does this answer your question? [Laravel 5.2 CORS, GET not working with preflight OPTIONS](https://stackoverflow.com/questions/34748981/laravel-5-2-cors-get-not-working-with-preflight-options) – Martin Braun Nov 02 '20 at 23:45

17 Answers17

211

The simple answer is to set the Access-Control-Allow-Origin header to localhost or *. Here's how I usually do it:

Create a simple middleware called Cors:

php artisan make:middleware Cors

Add the following code to app/Http/Middleware/Cors.php:

public function handle($request, Closure $next)
{
    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
}

You can replace the * with localhost or keep it as it is.

Next step is to load the middleware. Add the following line to the $routeMiddleware array in app/Http/Kernel.php.

'cors' => \App\Http\Middleware\Cors::class, 

And the final step is to use the middleware on the routes to which you want to set the access origin headers. Assuming you are talking about the new api routes in laravel 5.3, the place to do it is app/Providers/RouteServiceProvider.php, inside the mapApiRoutes() function (you can remove or comment the previous code of the function):

    Route::group([
        'middleware' => ['api', 'cors'],
        'namespace' => $this->namespace,
        'prefix' => 'api',
    ], function ($router) {
         //Add you routes here, for example:
         Route::apiResource('/posts','PostController');
    });
JacopoStanchi
  • 1,962
  • 5
  • 33
  • 61
haris
  • 3,775
  • 1
  • 25
  • 28
  • 9
    I'm trying to make this work too ([see here](https://stackoverflow.com/questions/46991025/access-control-allow-origin-header-response-in-laravel-5-4-not-working-for-post)) but for some reason only the GET requests work. Any idea why POST is not working with my setup? Also.. the order of the middleware seems to matter. – Stefan Falk Oct 28 '17 at 15:07
  • I am making ajax call and this solution does not work for me, any suggestion? – Rajesh Vishnani Dec 29 '17 at 14:01
  • 4
    Very clear for my Laravel 5.6 and Angular 5 Application. Thanks! – Andrew Koper Mar 20 '18 at 03:13
  • 2
    Instead of the last step just add this at the end of your routes: Route::get('/url','controller@function') -> middleware('cors'); – davefrassoni May 02 '19 at 06:49
  • Laravel 8 already has cors middleware included. But not working for me either (dont need auth since no users are stored in db) – trainoasis Dec 02 '20 at 14:50
  • Trying to implement this for my Laravel 9.x, agenda is to shoot API from front end but still CORS issue exist! Any recommendation? – Harry Feb 04 '23 at 02:47
73

The simple answer is to set the Access-Control-Allow-Origin header to localhost or *. Here's how I usually do it:

Add the following code to bootstrap/app.php:

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');

WARNING: Only do this in your developer environment.

roapp
  • 530
  • 6
  • 17
Jaydip kharvad
  • 1,064
  • 7
  • 13
25

You could also use the great laravel-cors package by barryvdh.

After you have the package installed, the easiest way to get CORS support for all your routes is to add the middleware like this in Http/Kernel.php:

protected $middleware = [
    \Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
    \Barryvdh\Cors\HandleCors::class,
];

If you dont want to have CORS support on all your routes you should make a new OPTIONS route for /oauth/token and add the cors middleware to that route only.

Edit for Laravel 8

Laravel 8 already has CORS Support built in - HandleCors middleware is defined in your global middleware stack by default and can be configured in your application's config/cors.php config file.

If you update your Laravel application be sure to change out barryvdh's package with the supplied middleware: \Fruitcake\Cors\HandleCors::class

roapp
  • 530
  • 6
  • 17
naabster
  • 1,494
  • 12
  • 14
  • For now, it should `\Fruitcake\Cors\HandleCors::class`, instead of `\Barryvdh\Cors\HandleCors::class`. [Docs](https://github.com/fruitcake/laravel-cors#global-usage) – ibnɘꟻ Feb 16 '21 at 06:51
10

For those who didn't solve the problem setting route middleware in App\Http\Kernel, try to set global middleware. In App\Http\Middleware\Cors:

public function handle($request, Closure $next)
{
    return $next($request)->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods','GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS')
        ->header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}

In App\Http\Kernel:

protected $middleware = [
    ...
    \App\Http\Middleware\Cors::class,
];
roapp
  • 530
  • 6
  • 17
Nick Synev
  • 389
  • 4
  • 11
  • This worked!!! Earlier had Cors middleware in as route middleware which didn't help in resolving OPTIONS method requests(Preflight). Setting Cors as global middleware handled all incoming requests including Preflight ones. Adding to the answer, if allow-credentials is true, setting allow-origin to * won't work. Origin will have to be specific in case of Allow-Credentials as true. The origin can be fetched from the request headers and then be added to response header. – 1nfern0 Dec 10 '21 at 07:00
  • This method worked for me. If it's not working, you can try in incognito page. – Jeyhun Rashidov Aug 26 '22 at 21:06
7

Create A Cors.php File in App/Http/Middleware and paste this in it.

<?php
    
namespace App\Http\Middleware;
    
use Closure;
    
    
class Cors 
{   
    public function handle($request, Closure $next)
    {
        header("Access-Control-Allow-Origin: *");
        //ALLOW OPTIONS METHOD
        $headers = [
            'Access-Control-Allow-Methods' => 'POST,GET,OPTIONS,PUT,DELETE',
            'Access-Control-Allow-Headers' => 'Content-Type, X-Auth-Token, Origin, Authorization',
        ];
        if ($request->getMethod() == "OPTIONS") {
            //The client-side application can set only headers allowed in Access-Control-Allow-Headers
                return response()->json('OK',200,$headers);
            }
            $response = $next($request);
            foreach ($headers as $key => $value) {
                $response->header($key, $value);
            }
            return $response;
        }
}

And Add This Line In Your Kernel.php after the "Trust Proxies::Class" Line.

\App\Http\Middleware\Cors::class,

Thats It You have Allowed All Cors Header.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Varun Pradhan
  • 587
  • 5
  • 8
4

After https://github.com/fruitcake/laravel-cors I had to change in cors.php file as below

/*
 * Sets the Access-Control-Allow-Credentials header.
 */
'supports_credentials' => true,
roapp
  • 530
  • 6
  • 17
Furquan
  • 1,542
  • 16
  • 20
  • After setting above key value 'supports_credentials' => true in config/cors.php file in laravel, Clear your config cache (php artisan config:clear), route cache (php artisan route:clear) and normal cache (php artisan cache:clear). It will work fine for the defined path in the cors.php file. – ANIL PATEL Oct 17 '20 at 11:18
3

Be careful, you can not modify the preflight. In addition, the browser (at least chrome) removes the "authorization" header ... this results in some problems that may arise according to the route design. For example, a preflight will never enter the passport route sheet since it does not have the header with the token.

In case you are designing a file with an implementation of the options method, you must define in the route file web.php one (or more than one) "trap" route so that the preflght (without header authorization) can resolve the request and Obtain the corresponding CORS headers. Because they can not return in a middleware 200 by default, they must add the headers on the original request.

2

Just add this to your code Controller

return response()->json(compact('token'))->header("Access-Control-Allow-Origin",  "*");
roapp
  • 530
  • 6
  • 17
walsia
  • 21
  • 2
2

If you've applied the CORS middleware and it's still not working, try this.

If the route for your API is:

Route::post("foo", "MyController"})->middleware("cors");

Then you need to change it to allow for the OPTIONS method:

Route::match(['post', 'options'], "foo", "MyController")->middleware("cors");
roapp
  • 530
  • 6
  • 17
1

If for some reason it's still not working. First option for Laravel The second option for any application

FIRST OPTION:

  1. As in the example above, we create middleware
php artisan make:middleware Cors
  1. Add the following code to app/Http/Middleware/Cors.php:
public function handle($request, Closure $next) 
{
    return $next($request)
        ->header('Access-Control-Allow-Origin', '*')
        ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, OPTIONS')
        ->header('Access-Control-Allow-Headers', 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'); 
}

Look closely, the amount of data in the header ->header('Access-Control-Allow-Headers',

  1. Step three, add middleware to $routeMiddleware array in app/Http/Kernel.php
protected $routeMiddleware = [
    ....
    'cors' => \App\Http\Middleware\Cors::class,
];

SECOND OPTION:

  1. Open the nginx.conf settings for your domain.
sudo nano /etc/nginx/sites-enabled/your-domain.conf
  1. Inside the server settings server { listen 80; .... } please add the following code:
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
roapp
  • 530
  • 6
  • 17
Galaxy IT
  • 696
  • 6
  • 7
0

Few steps to add Access-Control-Allow-Origin header to localhost or *.

Step 1: Create Cors middleware :

php artisan make:middleware Cors

Step 2: Set header in Cors middleware like this

public function handle($request, Closure $next)
{
    $response = $next($request);
    $response->headers->set('Access-Control-Allow-Origin' , '*');
    $response->headers->set('Access-Control-Allow-Methods', 'POST, GET, OPTIONS, PUT, DELETE');
    $response->headers->set('Access-Control-Allow-Headers', 'Content-Type, Accept, Authorization, X-Requested-With, Application');
     
    return $response;
}

Step 3: We need to add Cors class in app/Http/Kernel.php

protected $middleware = [
    ....
    \App\Http\Middleware\Cors::class,
];

Here no needed to check any middleware because we add Cors class in $middleware in app/Http/Kernel.php

roapp
  • 530
  • 6
  • 17
Nikunj Sakariya
  • 327
  • 4
  • 9
0

Working Solution

Step 1: Create Cors middleware

php artisan make:middleware Cors

Step 2: Set header in Cors middleware inside handle function

return $next($request)
    ->header('Access-Control-Allow-Origin', '*')
    ->header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

Step 3: Add Cors class in app/Http/Kernel.php

protected $routeMiddleware = [
    ....
    'cors' => \App\Http\Middleware\Cors::class,
];

Step 4: Replace mapApiRoutes in app/providers/routeServiceProvider.php

Route::prefix('api')
    ->middleware(['api', 'cors'])
    ->namespace($this->namespace)
    ->group(base_path('routes/api.php'));

Step 5: Add your routes in routes/api.php

Route::post('example', 'controllerName@functionName')->name('example');
roapp
  • 530
  • 6
  • 17
0

I know this an old question but I was running into this issue with Laravel 8. The cause of the problem was calling my api with an extra slash at the end of the url.

fetch('https://myapi.com/api/endpoint/', ...

Needed to be

fetch('https://myapi.com/api/endpoint', ...

Silly mistake but caused me some grief so I figured I'd share my solution.

crokadilekyle
  • 80
  • 1
  • 8
-1

Just add this to your view:

<?php header("Access-Control-Allow-Origin: *"); ?>
roapp
  • 530
  • 6
  • 17
davefrassoni
  • 306
  • 2
  • 5
-1

I am using Laravel 8 and just installed the fruitcake/laravel-cors and use it in app/Http/Kernel.php like blow:

protected $middleware = [
    ....
    \Fruitcake\Cors\HandleCors::class,
];

note: add it to end of array like me

roapp
  • 530
  • 6
  • 17
ahmad-mohammadi
  • 157
  • 2
  • 5
-1

You can do it easily by adding headers in bootstrap/app.php

header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: *');
header('Access-Control-Allow-Headers: *');
roapp
  • 530
  • 6
  • 17
JayLord Abueva
  • 393
  • 4
  • 6
-1

Laravel since version ^7.0 comes out of the box with CORS enabled by default. You don't need to add anything.

Below is the default configuration:

config/cors.php
'paths' => ['api/*', 'sanctum/csrf-cookie'],

'allowed_methods' => ['*'],

'allowed_origins' => ['*'], //This line means allow origin

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => false, 

];
roapp
  • 530
  • 6
  • 17