Disabling CSRF Protection on Specific Routes in Laravel

Disabling CSRF on Specific Routes in Laravel

Laravel provides CSRF protection out of the box on all your application routes. Sometime you may want to exclude some of the routes from CSRF protection check.

In this post, we will look at how we can disable CSRF check on some certain routes.

What is CSRF?

You might already know about CSRF, but I will define it for fresh developers.

A Cross Site Request Forgery is an attack that tricks a web browser into executing an unwanted action in an application to which a user is logged in.

CSRF is also known as XSRF, Sea Surf, and Session Riding.

A successful CSRF attack can be devastating for both the website owner and the end user. It can result in unauthorized fund transfers, password change, and personal data theft. In a CSRF attack, unauthorized commands are performed on behalf of an authenticated user.

How Laravel Handles CSRF

In Laravel, there is a middleware class Illuminate\Foundation\Http\Middleware\VerifyCsrfToken witha method handle(), which gets executed on every HTTP request.

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 *
 * @throws \Illuminate\Session\TokenMismatchException
 */
public function handle($request, Closure $next)
{
    if (
        $this->isReading($request) ||
        $this->runningUnitTests() ||
        $this->inExceptArray($request) ||
        $this->tokensMatch($request)
    ) {
        return tap($next($request), function ($response) use ($request) {
            if ($this->shouldAddXsrfTokenCookie()) {
                $this->addCookieToResponse($request, $response);
            }
        });
    }

    throw new TokenMismatchException;
}

In the VerifyCsrfToken class’s handle() method, we can see that unless $this->isReading($request) or $this->tokensMatch($request) return true, a TokenMismatchException exception will be thrown.

The isReading($request) method simply look for reading verbs like HEAD, GET and OPTIONS.

/**
 * Determine if the HTTP request uses a ‘read’ verb.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return bool
 */
protected function isReading($request)
{
    return in_array($request->method(), ['HEAD', 'GET', 'OPTIONS']);
}

If one of these being used in the request, it will skip over the CSRF check. The whole idea of using CSRF is meant to prevent other websites from submitting POST form data, so we can neglect the GET requests.

If the isReading($request) return false, it will call the tokenMatch($request) method. This does the work of actually deciding whether a token was included in the request, and if so, checks whether or not it matches the one stored in the session.

Within the same VerifyCsrfToken class, we can also find an array property called $except.

/**
 * The URIs that should be excluded from CSRF verification.
 *
 * @var array
 */
protected $except = [];

As you can see from the class comments, you can pass the URIs to this array if you want to exclude some routes from this CSRF check.

Disabling CSRF on Specific Routes

Now, if we open the App\Http\Middleware\VerifyCsrfToken class, we can see that this class simply extends the Illuminate\Foundation\Http\Middleware\VerifyCsrfToken class thus provide the access to $except property.

namespace App\Http\Middleware;

use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;

class VerifyCsrfToken extends Middleware
{
    /**
     * The URIs that should be excluded from CSRF verification.
     *
     * @var array
     */
    protected $except = [
        //
    ];
}

Simply add your routes inside that array which you want to exclude from the CSRF protection. Simple isn’t 😎

Leave a Reply

Your email address will not be published. Required fields are marked *

*

When sharing a code snippet please wrap you code with pre tag and add a class code-block to it like below.
<pre class="code-block">you code here</pre>

*
*

This site uses Akismet to reduce spam. Learn how your comment data is processed.