1

I was previously using a custom cors middleware in order to handle Allow Origin based on my environment. But after upgrading to 5.5, I had an issue with preflight OPTIONS cors so I switched to laravel-cors library. But now I don't know how I can handle different cases just by a config file. I'm wondering if anyone has experienced a similar issue. This is my previous custom cors middleware:

public function handle($request, Closure $next)
{

    $origin = \Config::get('app.url', "https://mysite.ca");

    // Set origin for localhost developing, else just use the staging server
    if( isset( $_SERVER['HTTP_ORIGIN'] ) && $_SERVER['HTTP_ORIGIN'] === 'http://app.localhost:3333' ) {
        $origin = 'http://app.localhost:3333';
    }


    $response = $next($request);


    $response->headers->set('Access-Control-Allow-Origin', $origin);
    $response->headers->set('Access-Control-Expose-Headers','Authorization');
    $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');
    $response->headers->set('Access-Control-Allow-Credentials','true');

    return $response;
}
Hirad Roshandel
  • 2,175
  • 5
  • 40
  • 63

1 Answers1

2

laravel-cors already by default automatically does the equivalent of what the custom code in the question is doing — that is, laravel-cors sets the Access-Control-Allow-Origin value conditionally based what the value of the Origin header is and if you’ve allowed it in your config.

However, as far as what the code in the question does, it’s not clear why you want to ever send an Access-Control-Allow-Origin response header with its value set to the app.url value.

What I mean is, app.url’s value is the URL for the same server you’ve installed laravel-cors at, right? That is, it’s the application to which you want to allow cross-origin requests from particular origins. If that’s the case, then you don’t need to explicitly allow requests from app.url, because those aren’t cross-origin requests so they’re allowed already without you needing to do anything.

Another point is that app.url isn’t an origin — instead it’s a URL, potentially with a path. But origins don’t have paths. So you don’t actually want to be setting the value of $origin to app.url unless you’re certain that your app.url has no path (not even a trailing slash).

All that said, if you really want to get the exact behavior of the custom code in the question, you can set your $origin variable as a global variable and then set the allowedOrigins array like this:

return [
     /*
     |--------------------------------------------------------------------------
     | Laravel CORS
     |--------------------------------------------------------------------------
     |
     | allowedOrigins, allowedHeaders and allowedMethods can be set to array('*')
     | to accept any value.
     |
     */
    'supportsCredentials' => true,
    'allowedOrigins' => [$origin, 'http://app.localhost:3333'],
    'allowedHeaders' => ['Content-Type', 'Accept', 'Authorization', 'X-Requested-With', 'Application'],
    'allowedMethods' => ['POST', 'GET', 'OPTIONS', 'PUT', 'DELETE'],
    'exposedHeaders' => ['Authorization'],
    'maxAge' => 0,
]

Those are the complete config settings for doing the equivalent of the custom code in the question.

Given the allowedOrigins value above, the conditional logic laravel-cors follows is this:

  • if the Origin request-header value matches the value of $origin, then send back the response header Access-Control-Allow-Origin with its value set to the $origin value
  • else if the Origin request-header value is http://app.localhost:3333, then send back the response header Access-Control-Allow-Origin: http://app.localhost:3333
  • else don’t send back any Access-Control-Allow-Origin response header

That’s what you need if you want to allow cross-origin requests from either the value of $origin or http://app.localhost:3333 but not from any other origins.

It’s true that does something a bit different from what the custom code in the question does — in that the code in the question causes an Access-Control-Allow-Origin response header with the $origin value to be sent back even to origins that are not allowed.

But you don’t want to be doing that anyway. In the case of a request coming from an origin that’s not allowed, there’s no point in sending back any Access-Control-Allow-Origin header at all — because the absence of the Access-Control-Allow-Origin response header tells the browser “don’t allow frontend JavaScript code running at this origin to access responses from our server”.

Beyond that there’s no point in publicly leaking information about what any of the the allowed origins are — which is what you’d be doing if you sent a default Access-Control-Allow-Origin response header set to $origin, as the custom code in the question does.

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
  • app.url is my frontend application url not the laravel api but I get what you mean. Similar to what you suggested I ended up adding more than 1 value to that array and it worked – Hirad Roshandel Oct 04 '17 at 20:46