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

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.


Solution 1:

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');
    });

Solution 2:

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.

Solution 3:

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

Solution 4:

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,
];