/var/www

Laravel-5 REST API and CORS

September 2nd 2015

Have been building a REST API using Laravel 5 as the backend and Backbone as Frontend. One thing that made me stuck is to get the CORS (Cross-Origin Resource Sharing) working right. I couldn’t find a clear way to achieve this. I did my research and came to some conclusions. While it’s not so hard to implement CORS, finding the ways to implement it may be hard, atleast for me. I will try to explain how I achieved CORS support in my Laravel application.

Create a new middleware \app\http\middleware\Cors.php in Laravel by giving the following command

[email protected]:~$ php artisan make:middleware Cors

Add the following code to the newly created middleware.

The Cors middleware should be placed beforeverifyCsrfToken middleware.

Update app\http\kernel.php to include the new middleware. Add \App\Http\Middleware\Cors::class to the $middleware array as shown below.

Wildcard * will not work in Access-Control-Allow-Origin header if Access-Control-Allow-Credentials header is set to 'true'

Last, inorder for your CORS to work, you need to add header(‘Access-Control-Allow-Origin: http://yourclientaddress.com’) at the top of your routes.php file. Ofcourse replace http://yourclientaddress.com with whatever is the client address. If you want to allow multiple clients, add it as comma separated values.

Inorder for Laravel CSRF token to work, cookies need to be enabled. By default cookies are disabled in CORS. Cookies can be enabled by setting Access-Control-Allow-Credentials header to ‘true’.

You also need to set Access-Control-Allow-Credentials header to ‘true’ for allowing Cookies to be set in the client. (The value ‘true’ always should be inside quotes, else it will return a value 1 and will be invalidated by the browser).

Laravel will automatically set CSRF token as a cookie in XSRF-TOKEN variable. This token needs to be send as X-XSRF-TOKEN header (and don't confuse it with X-CSRF-TOKEN header). Actually XSRF-TOKEN is the encrypted form of CSRF token. For some libraries like Angular, this is managed for you automatically.

The Frontend code to manage ajax request will looks like this. You can use the JsCookies plugin to manage cookies. This will automatically send CSRF token on every ajax request to the server (except GET).

Final Thoughts:

One downside of CORS is multiple requests to the server. For any request, there will be an Preflight request in the form of OPTIONS request asking permission from remote server at first. Once the permission is accepted by returning suitable headers, the original request will be send.

For every CORS request, there will be an additional OPTIONS request asking for suitable permissions from server. This is a big set back while considering performance.

There are several options to bypass this, but most of them will affect the ‘REST'ful nature of the application. One thing that can be done to reduce the number of requests is to cache preflight request. I believe w3c will come up with more and better options to handle this scenario, as CORS is still a work in progress!

Preflight request can be cached by setting Access-Control-Max-Age header. The value of this header allows the preflight response to be cached for a specified number of seconds.

Although preflight requests can be cached to redue the number of requests, the time it can be cached varies on each browsers. This doesn’t eliminate the issue completely, but helps in reducing the impact on performance by using CORS.

If you have a better & clean way to handle CORS in Laravel, please let me know. Cheers!

[Note: I have tried https://github.com/barryvdh/laravel-cors. Unfortunately this didn’t work for me.]

Further readings:

http://www.html5rocks.com/en/tutorials/cors/

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

https://remysharp.com/2011/04/21/getting-cors-working

Your comments