fruitcake / laravel-cors

Adds CORS (Cross-Origin Resource Sharing) headers support in your Laravel application
MIT License
6.27k stars 614 forks source link

The 'Access-Control-Allow-Origin' header contains multiple values '*, http://localhost:3000', but only one is allowed. #440

Closed AbdullahGhanem closed 4 years ago

AbdullahGhanem commented 4 years ago

first I did all the instructions that I set before I created this issue in nuxt project, I get this error.

Screen Shot 2020-04-02 at 2 58 27 AM

this OPTIONS method request:

Screen Shot 2020-04-02 at 2 55 47 AM

my Kernel.php

<?php

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

class Kernel extends HttpKernel
{
    /**
     * The application's global HTTP middleware stack.
     *
     * These middleware are run during every request to your application.
     *
     * @var array
     */
    protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,    
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
    ];

    /**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\App::class,
            // \App\Http\Middleware\Permissions::class,
            \App\Http\Middleware\RestrictIp::class,
        ],

        'api' => [
            'throttle:200,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            'localization',
        ],
    ];

    /**
     * The application's route middleware.
     *
     * These middleware may be assigned to groups or used individually.
     *
     * @var array
     */
    protected $routeMiddleware = [
        'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
        'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
        'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
        'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
        'can' => \Illuminate\Auth\Middleware\Authorize::class,
        'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
        'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
        'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
        'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,

        'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
        'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
        'localization' => \App\Http\Middleware\localization::class,
    ];
}

my config/cors.php

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Laravel CORS Options
    |--------------------------------------------------------------------------
    |
    | The allowed_methods and allowed_headers options are case-insensitive.
    |
    | You don't need to provide both allowed_origins and allowed_origins_patterns.
    | If one of the strings passed matches, it is considered a valid origin.
    |
    | If array('*') is provided to allowed_methods, allowed_origins or allowed_headers
    | all methods / origins / headers are allowed.
    |
    */

    /*
     * You can enable CORS for 1 or multiple paths.
     * Example: ['api/*']
     */
    'paths' => ['api/*'],

    /*
    * Matches the request method. `[*]` allows all methods.
    */
    'allowed_methods' => ['*'],

    /*
     * Matches the request origin. `[*]` allows all origins.
     */
    'allowed_origins' => ['*'],

    /*
     * Matches the request origin with, similar to `Request::is()`
     */
    'allowed_origins_patterns' => [],

    /*
     * Sets the Access-Control-Allow-Headers response header. `[*]` allows all headers.
     */
    'allowed_headers' => ['*'],

    /*
     * Sets the Access-Control-Expose-Headers response header with these headers.
     */
    'exposed_headers' => [],

    /*
     * Sets the Access-Control-Max-Age response header when > 0.
     */
    'max_age' => 0,

    /*
     * Sets the Access-Control-Allow-Credentials header.
     */
    'supports_credentials' => false,
];

this error when use all methods get, post, patch ..

barryvdh commented 4 years ago

Are you also adding headers with php or nginx directly?

AbdullahGhanem commented 4 years ago

no, I just use laravel valet. and laravel 7.

AbdullahGhanem commented 4 years ago

@barryvdh plz can help me?

enzolarosa commented 4 years ago

Hi @barryvdh I have the same issue

enzolarosa commented 4 years ago

Hi @barryvdh @AbdullahGhanem, my issue was with the paths array.

I setted the full url instead of set just the paths

CesarGomezTissini commented 4 years ago

Hi @barryvdh @AbdullahGhanem, my issue was with the paths array.

I setted the full url instead of set just the paths

Could you provide an example for this?

pedrosantosdev commented 4 years ago

Hi, a have passed to the same problems when update my laravel to 5.8 to 6.*, using v1.0.5 from laravel-cors. add to config/app.php providers => [ ... \Fruitcake\Cors\CorsServiceProvider::class ]

enzolarosa commented 4 years ago

Hi @CesarGomezTissini I was not using the api/ prefix for the api but I was using the full domain api.site.ext/.

The paths array was setted with api.site.local/ and this is wrong, I updated with'*' it's the path with out the domain and now works fine.

The paths should contains the prefix of your api route group. The default api route group prefix is api, so the default path config contains only api/*.

This is my cors.php file:

<?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' => ['*'],

    'allowed_methods' => ['*'],

    'allowed_origins' => [
        'https://site.local',
    ],

    'allowed_origins_patterns' => [],

    'allowed_headers' => [
        '*',
    ],

    'exposed_headers' => [
        '*',
    ],

    'max_age' => 0,

    'supports_credentials' => true,
];
sKuD51 commented 4 years ago

Hi,

same problem. Ok if I put my url it works fine, but the of "*" is that works for all domain. Is it a bug from last Laravel version ?

barryvdh commented 4 years ago

What do you mean? ['*'] doesn't work? Do you need the credentials? Do you get any headers back?

barryvdh commented 4 years ago

If so, please update to v2 and create a new issue with all details.

bramchi commented 4 years ago

The suggestion of @dhavaldav fixed this issue for me. This is not a bug of the laravel-cors package, but more of a misunderstanding of how to configure it properly. Looks like some (or all?) requests to the laravel backend use multiple headers which are not allowed by the default laravel-cors configuration 'allowed_origins' => ['*'], so you have to update that to allowed_origins => ['*,*'] to allow that.

msyrl commented 4 years ago

it is work for me, with multiple *,* on allowed_origins At config/cors.php

    'allowed_origins' => ['*,*'],

This solution work for me, thanks.

gabriel-kaam commented 3 years ago

Hi guys,

TL;DR; Check your .htaccess, you might already have added the CORS headers in it .

@dhavaldav solutions works; but not for the reasons mentioned here (I think) ; let me explain,

I was facing the same issue on my app hosted on Heroku, When I was curling my app on Heroku ; I saw 2 headers (curl -vI https://)

HTTP/1.1 200 OK
Connection: keep-alive
Date: Tue, 01 Dec 2020 15:11:44 GMT
Server: Apache
Cache-Control: no-cache, private
X-Ratelimit-Limit: 60
X-Ratelimit-Remaining: 59
Access-Control-Allow-Origin: *  # here
Access-Control-Allow-Origin: *  # and here
Access-Control-Allow-Methods: *
Access-Control-Allow-Headers: *
Content-Type: application/json
Via: 1.1 vegur

That was causing the "header contains multiple values" error message.

But on local, I only had one header

curl -I http://localhost:8000/api/finders/5f64b539e623250dc5473762
HTTP/1.1 200 OK
Host: localhost:8000
Date: Tue, 01 Dec 2020 15:12:27 GMT
Connection: close
X-Powered-By: PHP/7.4.11
Cache-Control: no-cache, private
Date: Tue, 01 Dec 2020 15:12:27 GMT
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
Access-Control-Allow-Origin: *

That's because Apache 2 is the server running on Heroku ; but on local it's only the php artisan server

The issue is : I had this in my .htaccess (.htaccess is a configuration file used by Apache)

Header add Access-Control-Allow-Origin: "*"
Header add Access-Control-Allow-Methods: "*"
Header add Access-Control-Allow-Headers: "*"

So basically, the issue is that the header Access-Control-Allow-Origin is added twice . First by the .htaccess (parsed by Apache) Then Again by the Laravel/cors something feature.

Adding 'allowed_origins' => ['*,*'], is actually an error of syntax, which causes the Laravel package to skip that configuration line, and ends up not adding the header to the request.

Want to test ? Try another incorrect value, like '*,' or '*,*,*' . The result will (should) be the same .

So basically, what we're doing, is making the Laravel package skips the allowed_origins configuration ; so .htaccess is the only one who adds the Header . Result : we only have 1 header, et voilà !

Now, a nicer way to achieve the same result, is to leave the array empty 'allowed_origins' => [], (Careful ; I tried with false as a value ; but some other headers disappears as well ; so I wouldn't recommend it)

That's what solved the issue for me ! Let me if that works for you

Versions laravel/framework : v6.18.38 barryvdh/laravel-cors: v2.0.1

ultrono commented 3 years ago

Yep, just lost ~20 minutes myself. A previous developer added the following to the API htaccess file:

// try to sort cors issues
Header set Access-Control-Allow-Origin "*"
# Header set Access-Control-Allow-Origin "all"
# Header set Access-Control-Allow-Origin ""

Removing tall that of course solved the issue :+1: