authenticationgoogle-signingoogle-authenticationgoogle-accountgoogle-client-login

What to use for "Sign in with Google" button's data-login_uri attribute?


I'm trying to implement a "Sign in with Google" button, as documented here: https://developers.google.com/identity/gsi/web/guides/display-button

I'm confused by what it expects for data-login_uri as illustrated below (taken from the documentation linked above):

<div id="g_id_onload"
     data-client_id="YOUR_GOOGLE_CLIENT_ID"
     data-login_uri="https://your.domain/your_login_endpoint"
     data-auto_prompt="false">
</div>

I have my app's client ID properly configured, and I can make it through most of the sign-in/auth flow provided by Google's pop-up window. However, once the pop-up window closes, it tries to POST to whatever URI I specify as the data-login_uri.

This leads me to believe that we need a back-end endpoint to do... something... but I can't track down any documentation regarding how this endpoint is supposed to behave, and as such I'm not sure what requirements to communicate to my back-end devs.

What did I miss?


Solution

  • TL;DR You need a backend process (scripted in PHP, Python, Node, etc.) on your server which can relay a token_id (received from the div you quoted) to Google for validation.

    Why?

    Google's documentation says:

    Warning: Do not accept plain user IDs, such as those you can get with the GoogleUser.getId() method, on your backend server. A modified client application can send arbitrary user IDs to your server to impersonate users, so you must instead use verifiable ID tokens to securely get the user IDs of signed-in users on the server side.

    Details

    The value of the data-auto_prompt parameter should point to an endpoint of an API or an executable CGI process in the back end.

    Let's say your domain name is 'example.com'. There needs to be an endpoint, or executable cgi script at that endpoint that is capable of capturing a POST request, with application/x-www-form-urlencoded encoding. It might be something like this: https://www.example.com/login.

    At this endpoint, a script / route should be capable of extracting the 'tokenid'

    Google's documentation describes what the back end must do in two places:

    Verify the Google ID token on your server side:

    1. Verify the Cross-Site Request Forgery (CSRF) token and
    2. Verify the integrity of the ID token

    Here's a python code fragment for a 'login' route, using the Flask framework: (A virtual environment is recommended and a pip install of two google api's are required.)

    At the command line: pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib

    # Required imports from google API
    from google.oauth2 import id_token
    from google.auth.transport import requests
    
    @bp.route('/login', methods=['POST'])
    def login():
    
        # Supplied by g_id_onload
        tokenid = request.form['credential']
    
        # Hardcoded client ID. Substitute yours.
        clientid = XXXXX
    
        # Display the encrypted credential
        current_app.logger.debug(f"Token = {tokenid}")
       
        try:
            idinfo = id_token.verify_oauth2_token(tokenid, 
                    requests.Request(), clientid)
    
            # Display the verified user information
            current_app.logger.debug(f"idinfo = {idinfo}")
        
            # jsonify returns a response object
            user_data = jsonify({
                    'username': idinfo['email'],
                    'name': idinfo['name'],
                    'id': idinfo['sub']
                })
            return  user_data
    
        except:
            return Response(status=404)