75

I've a payment system, where data is submitted to 3rd party site and than hauled back...

When data returns it hits specific url lets say /ok route. $_REQUEST['transaction'].

But because of laravel middleware I'm getting token mismatch. There is no way 3rd party payment API can generate token, so how I disable it? only for this route?

or is there a better option?

Route::get('/payment/ok',   'TransactionsController@Ok');
Route::get('/payment/fail', 'TransactionsController@Fail');

public function Ok( Request $request )
{
    $transId = $request->get('trans_id');

    if ( isset( $transId ) )
    {

        return $transId;

    }

}
jedrzej.kurylo
  • 39,591
  • 9
  • 98
  • 107
  • 3
    http://laravel.com/docs/master/routing#csrf-excluding-uris – Rashi Jul 30 '15 at 16:43
  • What version of Laravel are you using? If 5.1, see the answer below. If some older, let me know and I'll update the answer, as there are ways to do that for older versions, just a bit more complicated. – jedrzej.kurylo Jul 30 '15 at 17:20
  • 1
    @jedrzej.kurylo May I know how to disable CSRF token in Laravel 5.0. – Cataclysm Jun 03 '19 at 05:37

3 Answers3

157

Since version 5.1 Laravel's VerifyCsrfToken middleware allows to specify routes, that are excluded from CSRF validation. In order to achieve that, you need to add the routes to $except array in your App\Http\Middleware\VerifyCsrfToken.php class:

<?php namespace App\Http\Middleware;

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

class VerifyCsrfToken extends BaseVerifier
{
  protected $except = [
    'payment/*',
  ];
}

See the docs for more information.

jedrzej.kurylo
  • 39,591
  • 9
  • 98
  • 107
  • Hi Jedrzej, Above method I've used it but it not works with laravel 5.2.I need know to how disable CSRF token for API routes for above similar solution for laravel 5.2 version. – sankar muniyappa Aug 08 '16 at 13:14
  • 1
    Excluding URIs in 5.2 works the same way - see the docs here https://laravel.com/docs/5.2/routing#csrf-excluding-uris – jedrzej.kurylo Aug 08 '16 at 14:55
40

Since Laravel 7.7 you can use method withoutMiddleware eg:

Route::get('/payment/ok',   'TransactionsController@Ok')
    ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);

Route::get('/payment/fail', 'TransactionsController@Fail')
    ->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);
GetoX
  • 4,225
  • 2
  • 33
  • 30
  • 1
    you should add csrf field to app/Http/Kernel.php $routeMiddleware array like this 'csrf' => VerifyCsrfToken::class – Ozal Zarbaliyev Jan 27 '21 at 08:24
  • As @ozal-zarbaliyev mentioned, there is no Middleware with name `csrf` . Just use `\App\Http\Middleware\VerifyCsrfToken::class` in `withoutMiddleware` function. – Sadegh PM Jan 31 '21 at 09:21
6

The technique described by @jedrzej.kurylo works well for excluding one or two pages.

Here's a different technique if you need to exclude lots of pages from CSRF validation, with more future-proofing.

You can segment your routes, and apply different middleware to each. So you can put your payment routes into a separate route groups, and not apply VerifyCsrfToken to them. Here's how.

1. Create a routes file

You'll notice in your routes directory, you have the following tree:

  • routes/
  • routes/api.php
  • routes/web.php

Create a new file here, routes/payment.php, and add your routes above to it:

<?php
use Illuminate\Support\Facades\Route;

Route::get('/payment/ok',   'TransactionsController@Ok');
Route::get('/payment/fail', 'TransactionsController@Fail');

2. Process the route with the RouteServiceProvider

In Laravel, Routes are processed by app\Providers\RouteServiceProvider.php. You'll notice these functions: map() and mapWebRoutes(). Add to this file accordingly (I've excluded the stock comments for brevity).

    public function map()
    {
        $this->mapApiRoutes();
        $this->mapWebRoutes();
        $this->mapPaymentRoutes(); // <---- add this line
    }

    protected function mapWebRoutes()
    {
        Route::middleware('web')
             ->namespace($this->namespace)
             ->group(base_path('routes/web.php'));
    }

    protected function mapPaymentRoutes()  // <--- Add this method
    {
        Route::middleware('payment')       // <--- this line is important
             ->namespace($this->namespace)
             ->group(base_path('routes/payment.php'));
    }

Notice we've added a new middleware layer. This is important for the next step.

3. Add a new middleware layer

Your middleware for your route groups are defined in App\Http\Kernel.php.

Update the $middlewareGroups property, and add a middle entry for 'payment'. It can be exactly the same as web, but without the VerifyCsrfToken line.

    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\NoClickjack::class,
            \App\Http\Middleware\SecureReferrerPolicy::class,
            \App\Http\Middleware\NoXssScripting::class,
        ],

        // ********** Add this *******************
        'payment' => [
            \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,

// This is the line you want to comment-out / remove
//            \App\Http\Middleware\VerifyCsrfToken::class,     

            \Illuminate\Routing\Middleware\SubstituteBindings::class,
            \App\Http\Middleware\NoClickjack::class,
            \App\Http\Middleware\SecureReferrerPolicy::class,
            \App\Http\Middleware\NoXssScripting::class,
        ],

        'api' => [
            'throttle:60,1',
            'bindings',
        ],
    ];

Now whenever you add new routes that need to be excluded from the CSRF Token check, add them to the routes/payment.php file.

haz
  • 1,549
  • 15
  • 20