Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Laravel and Dropbox WebAuth: "Missing CSRF token in session"

I'm using Laravel 5.0 and trying to Authorize with Dropbox. I'm loosely following this example: http://dropbox.github.io/dropbox-sdk-php/api-docs/v1.1.x/class-Dropbox.WebAuth.html

When I go to /start. I get redirected to Dropbox and click "Allow", but when I get redirected back to /finish, I keep getting Missing CSRF token in session. Does anyone have any ideas? I have read that $_SESSION doesn't work in Laravel but I'm not sure how else to go about it.

Here is the code I am working with:

public function start()
{   
    $authorizeUrl = $this->getWebAuth()->start();

    return redirect()->away($authorizeUrl);
}

public function finish()
{       
    $test = $this->getWebAuth()->finish($_GET);

    dd($test);
}

private function getWebAuth()
{   
    $appKey = 'key';
    $appSecret = 'secret';
    $appName = 'name';
    $appRedirect = 'http://example.com/finish';

    $appInfo = new Dropbox\AppInfo($appKey, $appSecret);
    $csrfTokenStore = new Dropbox\ArrayEntryStore($_SESSION, 'dropbox-auth-csrf-token');
    $webAuth = new Dropbox\WebAuth($appInfo, $appName, $appRedirect, $csrfTokenStore);

    return $webAuth;
}

Update 1:

Okay so I tried getting it working with Laravel Socialite and the Dropbox Socialite provider. I changed my code to what is below, but I get an error when I hit /start. Driver [dropbox] not supported. I got really confused on step 3 of the instructions, so maybe I did something wrong there.

composer.json

"require": {
    "laravel/framework": "5.0.*",
    "dropbox/dropbox-sdk": "1.1.*",
    "laravel/socialite": "~2.0",
    "socialiteproviders/dropbox": "~1.0"
},

Controller

use Socialite;

class ExampleController extends Controller {

    public function start()
    {   
        return Socialite::with('dropbox')->redirect();
    }

    public function finish()
    {       
        $user = Socialite::with('dropbox')->user();

        dd($user->token);
    }
}

config/app.php

'providers' => [
    //'Laravel\Socialite\SocialiteServiceProvider',
    'SocialiteProviders\Manager\ServiceProvider',
],

'aliases' => [
    'Socialite' => 'Laravel\Socialite\Facades\Socialite',
],

app/Providers/EventServiceProvider.php

protected $listen = [
    'SocialiteProviders\Manager\SocialiteWasCalled' => [],
];

Update 2:

I figured it out, I added this and it worked.

app/Providers/EventServiceProvider.php

protected $listen = [
    'SocialiteProviders\Manager\SocialiteWasCalled' => [
        'SocialiteProviders\Dropbox\DropboxExtendSocialite@handle',
    ],
];
like image 906
Staysee Avatar asked Sep 29 '22 11:09

Staysee


2 Answers

Why reinvent the wheel, if you have a wrapper that can do this for you:

https://github.com/GrahamCampbell/Laravel-Dropbox

The reason is that the POST routes are protected with CSRF. If you do not want to use a wrapper, you need to disable this security layer, but nobody would recommend that.

Even better is using Laravel Socialite. Only the fact is here that Dropbox is not natively supported in it, but this package will solve that.

Credits to ceejayoz for helping with this!

like image 164
Blaatpraat Avatar answered Oct 03 '22 00:10

Blaatpraat


Note: Using a Dropbox package as in @Blaatpraat's answer is generally a better idea than this. If you're dead-set on using your own logic, though:

Laravel 5 POST routes (Dropbox is posting back to you at the end of the process) are protected by default by the CSRF protection middleware. Because Dropbox doesn't know your Laravel app's CSRF token (nor does it know to send one), the _token parameter is missing and fails the middleware.

You'll need to modify app/Http/Middleware/VerifyCsrfToken.php to exempt this route. Where it says:

return parent::handle($request, $next);

You'll want something like this to bypass the CSRF check on certain routes:

if(\Request::is('finish') { return $next($request); }
return parent::handle($request, $next);
like image 22
ceejayoz Avatar answered Oct 03 '22 02:10

ceejayoz