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

5.6k Views Asked by At

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?

2

There are 2 best solutions below

1
High Gravity On BEST ANSWER

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)
0
bdid On

The POST contents are described here data-login_uri with the expected actions for you to take on the back end described in Verify the Google ID token on your server side.

Generating a nonce per request and confirming the expected value on the back end are also strongly recommended to avoid replay attacks (and distinct from a CSP nonce to prevent cross-site scripting).