Question

I'm trying to use google oauth2 api for my login system. It's almost working, users give access to my web application, I read infos and connect users. Issue is, once they leave or change browser, get back on my website they're asked again to give access.

I don't need offline access as I'm not using any API calls other than checking in the user. Anyway I'm stuck and need some help there !

I'm using google php library (https://code.google.com/p/google-api-php-client/wiki/OAuth2) and I even set ApprovalPrompt to auto. Still no luck.

my code:

public function googleLogin()
{
    $this->set('connect', "Google login");
    $client = new apiClient();
    $client->setApprovalPrompt('auto');
    $client->setApplicationName("Authentication");
    $client->setClientId(G_OAUTH2_APP_ID);
    $client->setClientSecret(G_OAUTH2_SECRET);
    $client->setRedirectUri(G_REDIRECT_URI);
    $client->setDeveloperKey(G_DEV_KEY);
    $oauth2 = new apiOauth2Service($client);

    if (isset($_GET['code'])) {
        $client->authenticate();
        $_SESSION['token'] = $client->getAccessToken();
        $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
        header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));

    }

    if (isset($_SESSION['token'])) {
        $client->setAccessToken($_SESSION['token']);
    }

    if (isset($_REQUEST['logout'])) {
        unset($_SESSION['token']);
        $client->revokeToken();
    }
    //print_r($client->getAccessToken()); exit;

    if ($client->getAccessToken()) {
        $user = $oauth2->Guserinfo->get();


        // These fields are currently filtered through the PHP sanitize filters.
        // See http://www.php.net/manual/en/filter.filters.sanitize.php
        //$email = filter_var($user['email'], FILTER_SANITIZE_EMAIL);
        //$img = filter_var($user['picture'], FILTER_VALIDATE_URL);

        // The access token may have been updated lazily.
        $_SESSION['token'] = $client->getAccessToken();

        //do stuff with user data
        $data = $this->linkUser($user, "google");
        if ($data['state']=="createUser") {
            $this->set("data",$data);
        }

    } else {
        $authUrl = $client->createAuthUrl();
        header("Location: " . $authUrl);
    }
}

EDIT: I added the line $client->setAccessType("online"); I don't know yet if this is the only thing I had to do to make it work or if I have a bug between browsers/OS: Last time I tried on lion/chrome it didn't work but it's okay on w7/firefox. Well this or I'm simply loosing my mind :p

No correct solution

OTHER TIPS

On another question here: Google API - forces to Grant Permission Every time

Someone pointed out you can do this:

$client->setApprovalPrompt('auto');

I had a similar problem that seems to be solved eliminating $client->revokeToken(), moving the logout stuff before the login.

I don't know if avoiding to invalidate the token is a valid idea or not, but it seems to work.

Try with this one:

public function googleLogin()
{
    $this->set('connect', "Google login");
    $client = new apiClient();
    $client->setApprovalPrompt('auto');
    $client->setApplicationName("Authentication");
    $client->setClientId(G_OAUTH2_APP_ID);
    $client->setClientSecret(G_OAUTH2_SECRET);
    $client->setRedirectUri(G_REDIRECT_URI);
    $client->setDeveloperKey(G_DEV_KEY);
    $oauth2 = new apiOauth2Service($client);

    // I moved the logout stuff here, without invalidating the token
    if (isset($_REQUEST['logout'])) {
        unset($_SESSION['token']);            
    }

    if (isset($_GET['code'])) {
        $client->authenticate();
        $_SESSION['token'] = $client->getAccessToken();
        $redirect = 'http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'];
        header('Location: ' . filter_var($redirect, FILTER_SANITIZE_URL));

    }

    if (isset($_SESSION['token'])) {
        $client->setAccessToken($_SESSION['token']);
    }

    /* // I solved getting this stuf commented
    if (isset($_REQUEST['logout'])) {
        unset($_SESSION['token']);
        $client->revokeToken();
    }*/
    //print_r($client->getAccessToken()); exit;

    if ($client->getAccessToken()) {
        $user = $oauth2->Guserinfo->get();


        // These fields are currently filtered through the PHP sanitize filters.
        // See http://www.php.net/manual/en/filter.filters.sanitize.php
        //$email = filter_var($user['email'], FILTER_SANITIZE_EMAIL);
        //$img = filter_var($user['picture'], FILTER_VALIDATE_URL);

        // The access token may have been updated lazily.
        $_SESSION['token'] = $client->getAccessToken();

        //do stuff with user data
        $data = $this->linkUser($user, "google");
        if ($data['state']=="createUser") {
            $this->set("data",$data);
        }

    } else {
        $authUrl = $client->createAuthUrl();
        header("Location: " . $authUrl);
    }
}

You have to save the refresh token you get the first time the user grants access to your app in a database and reuse it for future requests.

The Google Drive SDK documentation includes a sample PHP application that implements that flow and that you can use as reference:

https://developers.google.com/drive/examples/php

I believe your problem is that you aren't storing any cookies on the users computer. Sessions only store information for the duration that the user is on the website.

This is a good simple explanation on cookies. Hope it helps.

http://www.tizag.com/phpT/phpcookies.php

Set Offline access. store initial token and refresh token for each user that authenticates then no matter where the user logs into your app from they will always be connected to their Google account, even if they aren't directly logged into google itself, they will be logged into Google through your app.

Like above, this is covered in the documentation.

It would be pointless having API's if users could never do this. Also, it's nothing to do with cookies and sessions. Add the server IP to the Google developer console and you'll be fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top