Adventures in OAuth with Laravel 4.1


3 minutes


I’ve been playing with Laravel 4.1 recently for a project and I wanted to allow people to login using their various social media accounts (I’ve opted on the “big 3”, Twitter, Google and Facebook). As it turned out, it’s been a bit of a chore due to a lack of clear documentation and examples, but I’ve managed to figure it all out and thought I’d share with the rest of the class.

In order to do the oauth, I used the artdarek/oauth-4-laravel package. However, the latest version of this package at the time of writing uses an older version of the lusitanian/oauth package. This is a problem because Google are currently changing how their scopes work and this new methodology is only supported in the newer versions of the package. In order to make sure I was using a package with the correct version of lusitanian/oauth, I used this fork from github: https://github.com/ciaranmaher/oauth-4-laravel

In order to use this, I needed to set a custom repository in my composer.json so it would use the fork in preference to the mainline version:

"repositories": [
    {
        "type": "vcs",
        "url": "https://github.com/ciaranmaher/oauth-4-laravel"
    }
]

From this point, it’s relatively simple to use the oauth-4-laravel package. You just need to sign up to the various places to get your OAuth client keys and secrets. For twitter, that’s https://apps.twitter.com/, for Facebook it’s https://developers.facebook.com/ and creating an app (once you’ve done that, you can get your app ID and secret). For Google, go to the developer console and create an app.

The basic usage instructions for oath-4-laravel are more or less fine, but I found the Google auth failed for me unless I made some changes:

// Make sure to add this access type to the auth uri request so you can actually do server-side calls. 
$google->getAuthorizationUri(array("access_type" => "offline"));

// This is the updated endpoint for userinfo according to google's oauth playground
$result = json_decode( $google->request( "https://www.googleapis.com/userinfo/v2/me" ), true );

// With the new oauth dependency in the fork of oauth-4-laravel I'm using
// You'll want to use different scopes in the config
'Google' => array(
    'client_id'     => 'my app id',
    'client_secret' => 'my secret',
    'scope'         => array('email','profile'),
),

For a decent twitter example, you can look at the tickets on the oauth-4-laravel github. This one is quite helpful: https://github.com/artdarek/oauth-4-laravel/issues/7#issuecomment-40059229

Finally, nothing tells you how to handle errors or the user cancelling an authorisation request. By default, the examples end up redirecting back to the same URL that started the request, making it look like you app want take no for an answer. Sadly, not all the services respond to cancellations/errors in the same way, but here is what I did for the ones I used:

// Facebook

$error = Input::get('error');

if($error) {
    $message = "An error occurred logging you in with Facebook.";
    if($error == "access_denied")
    {
        $message = "The access request on Facebook was denied.";
    }
    return Redirect::route('login')->with("error", $message);
}

// Google

$error = Input::get('error');

if($error) {
    $message = "An error occurred logging you in with Google.";
    if($error == "access_denied")
    {
        $message = "The access request on Google was denied.";
    }
    return Redirect::route('login')->with("error", $message);
}

// Twitter

$denied = Input::get('denied');

if($denied) {
    $message = "The access request on Twitter was denied.";
    return Redirect::route('login')->with("error", $message);
}

Put the relevant code in the same place where you first grab the auth code (i.e. the call to Input::get(“code”)) and now you can handle cancelled auths.

Hopefully that’s enough to help kickstart your work with OAuth in Laravel. I wish these things were clear when I started on it!

comments powered by Disqus