3

I'm using Google's Identity Services for the Signin button: https://developers.google.com/identity/gsi/web/guides/personalized-button

Now once a user logins to my website via Google I also trigger my own website's authentication mechanism (Forms login via ASP.NET). After 60 minutes of inactivity the user is automatically signed out of my application. However, the Google signin button still shows that user's email address. With a single click another user on that same machine could now relogin to my website as Google does not ask to authenticate again. Which seems like a weird design, but I'm probably missing something. How can I both automatically (in my case 60 minutes) expire the Google login and manually - when user clicks signout on my website - signout from Google?

I checked here, but that's not a solid solution it seems. I also checked here (old post) and here, but when placing the mentioned signout code example I get error

Uncaught ReferenceError: gapi is not defined

Even though I load the https://accounts.google.com/gsi/client script synchronously. Also I don't think the gapi still applies with the new Google Identity Services.

<meta name="google-signin-scope" content="profile email">
<meta name="google-signin-client_id" content="MYAPPIDPLACEHOLDER.apps.googleusercontent.com">


   function handleCredentialResponse(response) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4) {
                var result = JSON.parse(xhr.response).result;
                if (result == 'ok') {
                    window.location.href = "https://www.example.com";
                }
            }
        }
        //here I check the validity of the token
        xhr.open('POST', 'https://www.example.com/api/gtokensignin');
        xhr.setRequestHeader('Content-Type', 'application/json'); 
        xhr.send(JSON.stringify({ "idtoken": response.credential}));
    }
    
    
<div id="g_id_onload"
     data-client_id="MYAPPIDPLACEHOLDER.apps.googleusercontent.com"
     data-context="signin"
     data-ux_mode="popup"
     data-callback="handleCredentialResponse"
     data-nonce=""
     data-auto_prompt="false"
     data-auto_select="true">
</div>
    
<div class="g_id_signin"
     data-type="standard"
     data-shape="rectangular"
     data-theme="outline"
     data-text="signin_with"
     data-size="large"
     data-logo_alignment="left">
</div>  

example.svc.vb

This code successfully retrieves user details based on Google id_token

Public Function gtokensignin(ByVal str As oAuthUserSigninDetails) As Stream Implements Iexample.gtokensignin

    Dim dDateTimeNow As DateTime = DateTime.UtcNow

    Dim resultBytes As Byte()
    Dim resultText As String = "false"

    Dim WC As New WebClient
    Dim json As String

    Try
        json = WC.DownloadString("https://oauth2.googleapis.com/tokeninfo?id_token=" + str.idtoken)
    Catch ex As Exception
        Exit Function
    End Try

    Dim obj As JObject = JObject.Parse(json)

    Dim iss As String = obj.Item("iss")
    Dim azp As String = obj.Item("azp")
    Dim aud As String = obj.Item("aud")

    Dim exp As Long = Long.Parse(obj.Item("exp")) * 1000 'convert to milliseconds
    Dim expirationDate As DateTime = DateTimeOffset.FromUnixTimeMilliseconds(Long.Parse(exp)).UtcDateTime

    Dim email As String = obj.Item("email")

End Function

UPDATE 1

Ok, so I tried @Transformer's (see below) code in an incognito browser instance to make sure my Google Chrome login does not muddy the test.

Steps and questions regarding your OPTION 1:

  1. Why do you use https://apis.google.com/js/platform.js instead of https://accounts.google.com/gsi/client (as described here), platform.js is the old way of doing things.
  2. After clicking the signin button I have to enter my password. I login successfully and the Google button displays my email address
  3. I fire my signOut() function and see logged to Google Chrome console "User signed out."
  4. I refresh the page but still see my email address in the Google button and when I click it, I'm also signed in without having to enter my password again. Is this by design and if so: why would Google offer anyone the option to simply signin again without re-authenticating?

Steps and questions regarding your OPTION 2:

  1. I logout via my own link "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=https://www.example.com?signout=yes" 2a. IF I'm in an incognito browser window I get a Google redirect screen "the page is trying to redirect you to example.com", if I do so, I'm successfully logged out. Is there a way to NOT show that redirect screen? 2b. IF I'm in a regular Chrome browser window, I'm redirected to my employer's SSO provider login page and NOT back to my personal website example.com. I presume because we also use Google accounts internally, how to control that?

IMPORTANT NOTE: I also get signed out of my Gmail account, where I just want to logout the Google session with my website and require user to re-authenticate upon logging in again. I'm not sure if this is the way Google intended this feature though.

Adam
  • 6,041
  • 36
  • 120
  • 208
  • Are you handling the cookie creation, or is the Google api doing that? When I created a google login app, I had to store the authentication token in a cookie for that user. If you want to log them out, all you need to do is delete that cookie (or overwrite the cookie with a blank value and an expiration date in the past). – Stevish Sep 02 '21 at 19:00
  • @Stevish I added my code, google is handling cookie settings as I think you can see from this – Adam Sep 03 '21 at 11:41
  • Dang, sorry. That's a completely different implementation than what I have experience with. Hope you find your answer! – Stevish Sep 03 '21 at 18:12
  • Please see my code for option 1, after `signOut` please call `auth2.disconnect()` – Transformer Sep 12 '21 at 22:41
  • @Transformer thanks, I have your function implemented like that, not sure if you changed anything? – Adam Sep 13 '21 at 06:46

1 Answers1

0

Your Question: How can I both automatically (in my case 60 minutes) expire the Google login and manually - when user clicks signout on my website - sign out from Google?...

Google uses Auth2 for Identity Services, get your getAuthInstance() and then manage the session. You get the tokens needed from there, just follow the documentation samples. Below is the code which will sign out the user.

Google Auth2 ASP.Net Java Ruby Sign in SignOut

Look here on github, you can adopt the code below into your js code to force a complete sign-out, There are two steps to ensure complete sign-out. auth2.signOut().then(function () { auth2.disconnect(); });

Option 1. Get the Auth2 instance, then call auth2.disconnect() after auth2.signOut() succeeds.


<script type="text/javascript">

    // get your auth2 initializtion
    function onLoad() {
        gapi.load('auth2', function() {
            gapi.auth2.init();
        });
    }

    // On sign-out ,  auth2.disconnect();
    function signOut() {
        var auth2 = gapi.auth2.getAuthInstance();
        auth2.signOut().then(function () {
        // **** this is required to complete the sign-out 
         console.log('User signed out.');   
         auth2.disconnect();  
        });

        // Debugging, uncomment below if the above does not work to troubleshoot
        // auth2.disconnect();  
    }

</script>



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

Option 2: Redirect 'ASP Logout Action' to Google App Engine Logout like below

Swap out the domain name instead of http://localhost/application-name/logoutUser , add your domain name, in you asp Logout action redirect to this logout page.

document.location.href = "https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://localhost/application-name/logoutUser";
Transformer
  • 6,963
  • 2
  • 26
  • 52
  • Thanks, I added update 1, could you have another look please? – Adam Sep 12 '21 at 07:08
  • Hello Flo, can you please share `why are you doing it in the incognito mode`. I am having _a hard time following what you are trying to do_. I am able to do this fine with the ASP backend, can you also post the ASP Code, `Actions/Controllers` and your startup code. – Transformer Sep 12 '21 at 22:37
  • 1
    Thanks. See my svc code added. Nevermind my comment about incognito mode, I was just testing different scenarios. An important question from me: why are you using the old Google script `https://apis.google.com/js/platform.js` and not the recommended new one `https://accounts.google.com/gsi/client`? – Adam Sep 13 '21 at 06:50
  • from my understanding, the older `Platform.js` is a _superset_ of `GSI client` at least till they finish adding the other stuff into GSI, and currently GSI only has authentication published as of [august 2021](https://stackoverflow.com/a/68944261/6085193). The above code is what I have used in the past, but it was C#, I dont know VB. – Transformer Sep 13 '21 at 14:31