adding google sign-in to your webapp - using the js library

intricatecloud

Danny Perez

Posted on July 23, 2019

adding google sign-in to your webapp - using the js library

In the first part of the series, we decided to use the Google Sign-In for websites library to allow you to show some info about the user using javascript. We used the default Google Sign-In workflow with their default button.

In this part, we'll be going over how to use the gapi library to configure Sign-In and then actually sign-in the user, as well as a few snippets for handling some common user scenarios.

create your own sign in button

  1. Load the api.js library instead of platform.js 🤷 (not sure why they're different)

Change https://apis.google.com/js/platform.js to https://apis.google.com/js/api.js?onload=onLibraryLoaded

Here, we configure our Sign-In client once the library has loaded using the ?onload=onLibraryLoaded callback that you can provide via the URL. api.js will add a global variable called gapi.

  1. Add a button to your index.html with a button click handler

<button onclick="onSignInClicked()">Sign in with button onClick</button>

  1. Add the following to your script tag in index.html to handle the button click
function onLibraryLoaded() {
    gapi.load('auth2', function() {
        gapi.auth2.init({
            client_id: 'YOUR_CLIENT_ID.apps.googleusercontent.com',
            scope: 'profile'
        })
    })
}

function onSignInClicked() {
    gapi.load('auth2', function() {
        gapi.auth2.signIn().then(function(googleUser) {
          console.log('user signed in')
        }, function(error) {
            console.log('user failed to sign in')
        })
    })
}
Enter fullscreen mode Exit fullscreen mode

We can then access the gapi.auth2 library and initialize it using our client_id from the Developer Console.

how to handle some common user scenarios

  • listening for when the user has signs in
  • checking if the user is logged in
  • getting the users info
  • only allow users from a particular domain to log in
  • only allow certain users to log in
  • hide content until after a user logs in
  • sending your ID token to a backend (if you have one)

listening for when user signs in

In the above example, we can only run some code after we initialize and sign in the user. But what if you have different parts of the page in different files, each showing something different depending on the user? (this might be the case if you're using components)

class UserAvatarComponent extends React.Component {
    ...
    componentDidMount() {
        gapi.load('auth2', function() {
            gapi.auth2.isSignedIn.listen(function(isSignedIn) {
                console.log('user signed in ', isSignedIn)
                this.setState({status: isSignedIn})
            })
        })
    }    
}
Enter fullscreen mode Exit fullscreen mode

checking if the user is signed in

function isUserSignedIn() {
  gapi.load('auth2', function() {
      var isSignedIn = auth2.isSignedIn.get();
      console.log('is signed in? ', isSigned In)
  })
}
Enter fullscreen mode Exit fullscreen mode

A few things to note about using this function:

  • The Sign-In library will, by default, sign you in automatically if you've already signed in.
  • If you refresh the page, even after the user has signed in, then on first laod, you'll get auth2.isSignedIn.get() === false
  • After the user is signed in automatically (usually takes a sec), then auth2.isSignedIn.get() === true
  • Depending on how you handle your login UI, your user might see that they are not logged in for a hot second. It's helpful to use the isSignedIn.listen() callback if you want to know the precise moment this happens.

getting the users info

function showCurrentUserInfo() {
  gapi.load('auth2', function() {
      var googleUser = auth2.currentUser.get()
      console.log('users info ', googleUser)
  })
}
Enter fullscreen mode Exit fullscreen mode

only allowing users from a particular domain to login

This is a little bit of a hack and is probably easy to circumvent, but you can use the getHostedDomain() method to get the G-Suite domain the user comes from. If the user does not have a G-Suite domain, then it'll be blank.

function onSignIn(googleUser) {
    if(googleUser.getHostedDomain() !== 'mysite.com') {
        // show a Not Authorized message
    } else {
        // show the users dashboard
    }
}
Enter fullscreen mode Exit fullscreen mode

only allowing certain users to login

This is even more of a hack, but seems to be the only you can do it from within javascript. You really shouldn't. Don't know why I'm including it. The brute method.

function onSignIn(googleUser) {
    var profile = googleUser.getBasicProfile()
    if(profile.getEmail() === 'admin@example.com' ||
       profile.getEmail() === 'client@example.com') {
           // show the user dashboard
    } else {
        // show a Not Authorized message
    }
}
Enter fullscreen mode Exit fullscreen mode

hiding content until after the user logs in

This is also a hack. This is easy to workaround if you fidget with the CSS in your browser, but can work if it fits your use case. The reason this is a bad idea is that in a static website, all of the information thats available in your HTML is available to the user. DO NOT USE THIS if you have actual sensitive information to hide. It is a good candidate for showing your favorite cat pictures.

<body>
...
  <div id="greeting">
    You are not authorized to view this content
  </div>
  <div id="dashboard">
    ...
  </div>
  <script>
    // hide initially
    $('#dashboard').hide()

    function onSignIn(googleUser) {
      setTimeout(function() {
        // show the content
        $('#greeting').hide()
        $('#dashboard').show()
      }, 1000);
    }
  </script>
</body>
Enter fullscreen mode Exit fullscreen mode

send the token to identify the user (not their ID)

If you're making a backend request, you'll want to send the users ID token to your backend as an Authorization header. On your backend, you'd then be able to validate and decode the ID token (see here for examples).

The benefit of the approach is that this ID token (a type of JWT token) is signed by Google, so you know the information hasn't been tampered with.

$.ajax({
  url: 'myapi/example',
  headers: {'Authorization': googleUser.getAuthResponse().id_token)},
})
Enter fullscreen mode Exit fullscreen mode

Conclusion

In this post, we've seen how you can configure the Google Sign-In library via javascript, and use it to do things like get the users info and check if they're signed in (theres some nuances to be aware of with the login flow).

Demo code is available on Github intricatecloud/google-sign-in-demo. Replace YOUR_CLIENT_ID with your client ID, and you'll be able to see the sign in buttons in action.

For the last part of this series, we'll look at some examples of how you might use google sign-in in a React and Angular application. Check it out here.


Originally published on www.intricatecloud.io

💖 💪 🙅 🚩
intricatecloud
Danny Perez

Posted on July 23, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related