Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google-plus sign in: the code runs twice, user was logged out right after he logs in

Tags:

google-plus

this is a page built on example

<html>
<head>
  <title>Demo: Getting an email address using the Google+ Sign-in button</title>
  <style type="text/css">
  html, body { margin: 0; padding: 0; }
  .hide { display: none;}
  .show { display: block;}
  </style>
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js" ></script>
  <!--<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>-->
  <script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>
  <script type="text/javascript">
  /*
   * Triggered when the user accepts the sign in, cancels, or closes the
   * authorization dialog.
   */
  function loginFinishedCallback(authResult) {
    if (authResult) {

       console.log('authResult : ',authResult);
      if (authResult['error'] == undefined){
        gapi.auth.setToken(authResult); // Store the returned token.
        toggleElement('signin-button'); // Hide the sign-in button after successfully signing in the user.
        getEmail();                     // Trigger request to get the email address.
      } else {
        console.log('An error occurred');
      }
    } else {
      console.log('Empty authResult');  // Something went wrong
    }
  }

  /*
   * Initiates the request to the userinfo endpoint to get the user's email
   * address. This function relies on the gapi.auth.setToken containing a valid
   * OAuth access token.
   *
   * When the request completes, the getEmailCallback is triggered and passed
   * the result of the request.
   */
  function getEmail(){
    // Load the oauth2 libraries to enable the userinfo methods.
    gapi.client.load('oauth2', 'v2', function() {
          var request = gapi.client.oauth2.userinfo.get();
          request.execute(getEmailCallback);
        });
  }

  function getEmailCallback(obj){
    var el = document.getElementById('email');
    var email = '';
    console.log("OBJ = ",obj)
    if (obj['email']) {
      email = 'Email: ' + obj['email'];
    }

    //console.log(obj);   // Uncomment to inspect the full object.

    el.innerHTML = email;
    toggleElement('email');
  }

  function toggleElement(id) {
    var el = document.getElementById(id);
    if (el.getAttribute('class') == 'hide') {
      el.setAttribute('class', 'show');
    } else {
      el.setAttribute('class', 'hide');
    }
  }
  </script>
</head>
<body>
  <div id="signin-button" class="show">
     <div class="g-signin" data-callback="loginFinishedCallback"
      data-approvalprompt="auto"
      data-clientId="751931329576.apps.googleusercontent.com"
      data-scope="https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/userinfo.email"
      data-height="short"
      data-cookiepolicy="http://semicon-equip.com"
      >
    </div>
    <!-- In most cases, you don't want to use approvalprompt=force. Specified
    here to facilitate the demo.-->
  </div>

  <div id="email" class="hide"></div>
</body>
</html>

Question 1: It always fails with "Uncaught TypeError: Cannot read property 'load' of undefined",

until I use

<script src="https://apis.google.com/js/client:plusone.js" type="text/javascript"></script>

instead of the example code:

<script src="https://apis.google.com/js/plusone.js" type="text/javascript"></script>

What's the difference between plusone.js and client:plusone.js ?

enter image description here

Question 2: Why the code run twice per page loads ? enter image description here

Qestion 3: the user was logged out after he just signed in, how to fix ?

enter image description here

error demo page for the above (all the errors are in the background console).

like image 972
Ray C Lin Avatar asked Jul 07 '14 10:07

Ray C Lin


1 Answers

This is not really an answer to the question, but a step by step procedure to reproduce it.

Below the simple html page I'm using to test (similar to the example from Ray C Lin). I've made it as simple as possible to avoid interactions with other part of the code :

<html>
<head>
    <script type="text/javascript" 
            src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
</head>
<body>
    <input type="button" id="signOut" value="Sign out"></button>
    <span id="signinButton">
        <span class="g-signin"
            data-accesstype="offline"
            data-callback="signinCallback"
            data-clientid="YOUR_CLIENT_ID_HERE"
            data-cookiepolicy="single_host_origin"
            data-scope="email"
        </span>
    </span>
    <script type="text/javascript">

        $('#signOut').on('click', function() {
            gapi.auth.signOut();
        });

        function signinCallback(authResult) {
            console.log("signinCallback: ", authResult);
        }
        (function() {
            var po = document.createElement('script');
            po.type = 'text/javascript';
            po.async = true;
            po.src = 'https://apis.google.com/js/client:plusone.js';
            var s = document.getElementsByTagName('script')[0];
            s.parentNode.insertBefore(po, s);
        })();
    </script>
</body>
</html>

You will have to update data-clientid with your own google client id, and display this page from an authorized javascript origin.

Please note that this might not work from localhost, as Ian suggested in a comment to this post https://plus.google.com/102746521318753162868/posts/Z5Gkro9YXVs

First, sign in using your Google account : you will see a successful callback in the console.

If you click on Sign out, you will see a callback with 'user_signed_out' in the console.

So far so good.

Sign-in again, and wait 1 hour, until the token expires (this is awful to test, as I don't know how to reduced the token lifetime).

After one hour, click on the sign out button : no callback is called.

Click on the sign-in button again :

  • you get a successfull callback with an authorization code and access token
  • immediately after, you get a 'user_signed_out' callback.

Once a session has expired, there is no way to return to a "normal" situation, you always get this second callback with 'user_signed_out'.

Actually, there is one way to return to a "normal" situation: revoke the access to the app from the google dashboard.

This is not really an issue for me as I'm using Google+ only to sign-in the user to my app using the one time authorization code, and I'm not using the access token from the client.

But this prevent automatic login from working, as the user is immediately considered as "signed out" from a google perspective.

like image 75
Pascal LE QUANG Avatar answered Oct 03 '22 12:10

Pascal LE QUANG



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!