Adding Access-Control-Allow-Origin header response in Laravel 5.3 Passport
Asked Answered
H

17

94

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.

Hollander answered 10/9, 2016 at 18:50 Comment(1)
Does this answer your question? Laravel 5.2 CORS, GET not working with preflight OPTIONSZootomy
C
215

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');
    });
Corporate answered 13/9, 2016 at 5:24 Comment(7)
I'm trying to make this work too (see here) 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.Toothed
I am making ajax call and this solution does not work for me, any suggestion?Sorely
Very clear for my Laravel 5.6 and Angular 5 Application. Thanks!Margerymarget
Instead of the last step just add this at the end of your routes: Route::get('/url','controller@function') -> middleware('cors');Rubious
Laravel 8 already has cors middleware included. But not working for me either (dont need auth since no users are stored in db)Landslide
Trying to implement this for my Laravel 9.x, agenda is to shoot API from front end but still CORS issue exist! Any recommendation?Charr
I dont know what version you are using, but currently I am on 10, but 10 already have config for cors. is this for display? damn. and it is not working if I have to create middleware for CORSTeriteria
L
74

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.

Lobeline answered 30/7, 2018 at 7:49 Comment(7)
i think it would be something more like this: header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: *'); header('Access-Control-Allow-Headers: Origin, X-Requested-With,Authorization, Content-Type, Accept');Ramburt
Would this leave your application open to attacks as you are also allowing everyone to Post to your entire application?Glossematics
Never do this , it means any one can Post data to your application.Gadfly
for development purpose only, it works thank youElephantine
Finally something that works for Laravel 8..Connoisseur
Didn't work for me on L8.Sueannsuede
I can't understand why sophisticated laravel package can't work but this simple solution is exactly what I needed.Confirmation
N
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

Nev answered 14/9, 2016 at 11:57 Comment(2)
For now, it should \Fruitcake\Cors\HandleCors::class, instead of \Barryvdh\Cors\HandleCors::class. DocsCott
What should be the configuration in config/cors.php for Access-Control-Allow-Origin: * ? Nobody is telling that.Creolized
B
9

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,
];
Bongbongo answered 19/8, 2018 at 16:56 Comment(2)
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.Acuff
This method worked for me. If it's not working, you can try in incognito page.Anzus
M
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.

Militate answered 4/7, 2019 at 18:30 Comment(0)
L
5

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,
Liborio answered 21/3, 2020 at 12:23 Comment(1)
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.Cumings
P
4

Just add this to your code Controller

return response()->json(compact('token'))->header("Access-Control-Allow-Origin",  "*");
Psychographer answered 6/8, 2019 at 9:14 Comment(2)
Please put your answer always in content instead of simply pasting code, thanks!Forgave
can you explain why?Middleoftheroader
I
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.

Irritant answered 13/5, 2017 at 14:57 Comment(0)
S
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");
Spelldown answered 10/10, 2019 at 14:40 Comment(0)
A
2

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';
Authority answered 9/8, 2020 at 11:42 Comment(1)
First option was my solution to get assets back enabling corsNarcisanarcissism
S
1

Laravel since version ^7.0 comes out of the box with CORS enabled by default.

So you can modify Laravel's configuration instead of adding headers in custom middlewares yourself:

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, 

];
Skit answered 2/2, 2023 at 18:24 Comment(0)
A
1

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.

Aguilar answered 17/4, 2023 at 22:11 Comment(0)
I
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

Ichthyosaur answered 30/4, 2020 at 10:22 Comment(0)
B
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');
Bracing answered 9/6, 2020 at 7:19 Comment(0)
H
0

For users of newer versions of Laravel, there is a cors.php file in the config dir.

Add your URLs to a proxy array and restart the laravel artisan server:

<?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' => ['api/*', 'sanctum/csrf-cookie'],

'allowed_methods' => ['*'],

'allowed_origins' => ['*'],

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => false,

'proxies' => [
  //All your cors URLs here. Like the example below:
   'http://192.168.100.106:9000',
],

];

Heida answered 20/3 at 3:54 Comment(0)
A
-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

Alongshore answered 7/1, 2021 at 7:43 Comment(0)
S
-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: *');
Spinel answered 10/9, 2021 at 17:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.