Laravel-5 REST API and CORS
September 2nd 2015Have 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
Your comments