10

I am using Google Plus as login, which worked fine until recently. Now the user can't log out anymore. The callback works and returns that the user is signed out, however after that it immediately signs the user in again. Seems like it is not storing the logout.

There's a few older questions on this like for example this one. I tried all the proposed solutions but nothing worked.

Code in the html head

<script src="https://apis.google.com/js/client:platform.js?onload=start" async defer></script>

Button code, which is always displayed (hidden when logged in)

<div id="signinButton">
  <span class="g-signin"
    data-scope="https://www.googleapis.com/auth/gmail.readonly"
    data-clientid="{{ CLIENT_ID }}"
    data-redirecturi="postmessage"
    data-accesstype="offline"
    data-cookiepolicy="single_host_origin"
    data-callback="signInCallback">
  </span>
</div>

SignIn and SignOut function

<script>
  function signInCallback(authResult) {
    //console.log(authResult)
    if (authResult['code']) {

      var state = encodeURIComponent('{{ STATE }}');
      var code = encodeURIComponent(authResult['code']);          
      var tz = encodeURIComponent($('#timezone').val());
      var cntry = encodeURIComponent($('#country').val());
      var lan = encodeURIComponent('{{ language }}');

      // Send the code to the server
      $.ajax({
        type: 'POST',
        url: '/signup/gauth',
        contentType: 'application/octet-stream; charset=utf-8',
        success: function(result) {
          console.log(result)
          if (result == 'Success') {
            {% if not user %}window.location = "/user/home";{% else %}
            console.log('Logged in');{% endif %}
          }
        },
        processData: false,
        data: 'code='+code+'&state='+state+'&country='+cntry+'&tz='+tz+'&language='+lan
  });
    }
    else if (authResult['error']) {
      console.log('Sign-in state: ' + authResult['error']);
    }
  }

  function signOut() {
    gapi.auth.signOut();
    window.location = "/user/logout"
  }
</script>
Community
  • 1
  • 1
Vincent
  • 1,137
  • 18
  • 40
  • hey vincent, have you checked out this new and improved method i am using? edited my answer and it should solve your problem. if you solved it differently, please post your solution, i'd like to examine different approaches. Who says that i am not reinventing the wheel - square version? – tony gil Feb 21 '17 at 12:46
  • 1
    hi Tony, thanks for adding an answer. I solved it by switching to backend authorization, basically getting rid of the entire javascript implementation. I unfortunately can't confirm your solution therefore. – Vincent Feb 26 '17 at 11:01
  • that's ok @vincent , seems like a couple of people checked the solution out and approved it. Since i got no negative reviewing, i'm happy with the outcome of the bounty regardless. – tony gil Feb 28 '17 at 16:05

1 Answers1

4

EDIT: I achieve complete logout and signout using a two step approach: first i signout and then i close current page and open a logout php page which terminates the current session (i could use Ajax, but i prefer to send user to homepage after logout, so why bother?).

<head>
  <meta name="google-signin-scope" content="profile email">
  <meta name="google-signin-client_id" content="your-CLIEntID">
  <script src="https://apis.google.com/js/platform.js" async defer>   
  </script>
  <script> 
    function signOut() {
      var auth2 = gapi.auth2.getAuthInstance();
      auth2.signOut().then(function () {
        console.log('User signed out.');
      });
    }
  </script>
</head>
<body>
...
  <a href='logout.php' onclick='signOut();'>LOGOUT</a>
...

this is my signOut (production), for final version, i recommend that you remove console logging

var auth2 = gapi.auth2.getAuthInstance();
auth2.signOut();

logout.php

<?php
ob_start();
session_start(); 
$serverName = $_SERVER['SERVER_NAME'];
$tokenGoogle = $_POST['myTokenFromGoogle'];
if ($tokenId) {
    debug_to_console("inside LOGOUT has tokenGoogle [$tokenGoogle]");
    $url = "https://accounts.google.com/o/oauth2/revoke?token=$tokenGoogle";
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    $json = json_decode($response, true);
    curl_close($ch);
    header("Location: http://$serverName/pageThatConsumesdata.php?".implode("|",$json));
} else {
    debug_to_console("inside LOGOUT HAVING NO tokenGoogle");
    if(isset($PHPSESSID)) {
        $message = "time for a  change of ID? ($PHPSESSID).";
        $sessionName = session_id();
        session_regenerate_id();
        $sessionName2 = session_id();
    } else {
        $message = "There was no session to destroy!";
    }
    debug_to_console($message);
    debug_to_console("[$serverName]");
    session_destroy();   
    header("Location: http://".$serverName);
    exit;
}
function debug_to_console( $data ) {
    if ( is_array( $data ) ) {
    $output = "<script>console.log( '" . implode( ',', $data) . "' );</script>";
    } else {
    $output = "<script>console.log( '" . $data . "' );</script>";
    }
    echo $output;
}
?>

NOTE: For debugging purposes, i have included a function for printing to console from php (click SHIFT+CTRL+J to view console in firefox or in chrome). it is by no means standard practice to do so and should be removed once final code is launched.

tony gil
  • 9,424
  • 6
  • 76
  • 100