The newest version of Google Identity Toolkit has been released as Firebase Authentication. It includes upgraded client SDKs, open source UI libraries, session management and integrated email sending service for forgotten password flows.

New projects should use Firebase Authentication. To migrate an existing project from Identity Toolkit to Firebase Authentication, see the migration guide.

Access User Data with Secure Tokens

If you use Identity Toolkit for sign-in and your backend makes your users' data available through an API that requires user authorization, you can securely access your API by using the Secure Token service to exchange a user's ID token for an access token, and then including the access token in your API call. Your API backend can use the access token to verify that the user authorized the API call.

To securely access user data through an authorized API:

  1. Sign in the user using Identity Toolkit. See the developer guides for Android, iOS, and websites.

  2. Get the ID token for the signed-in user.

    • On Android, the ID token is a parameter of the onSignIn callback that you implement.
    • On iOS, the ID token is a parameter of the didFinishSignInWithToken callback that you implement.
    • On websites, the ID token is returned to your sign-in success endpoint as a cookie called gtoken.
  3. Exchange the ID token for a refresh token using the Secure Token API.

    POST /v1/token HTTP/1.1
    Host: securetoken.googleapis.com
    Content-Type: application/x-www-form-urlencoded
     
    code=id_token&grant_type=authorization_code
    

    The Secure Token service validates the ID token and returns an access token, a refresh token, and the time left before the access token expires. For example:

    {
      "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3Mi",
      "expires_in": "3600",
      "token_type": "Bearer",
      "refresh_token": "4sa7yaofbfotcannciLadttp",
    }

    Store the access token, refresh token, and expiration time in your app's local storage.

  4. Whenever you call an API that requires authorization, check if you have an access token or if the access token has expired; if you don't have a valid access token, exchange the refresh token for a new access token using the Secure Token API.

    POST /v1/token HTTP/1.1
    Host: securetoken.googleapis.com
    Content-Type: application/x-www-form-urlencoded
     
    refresh_token=refresh_token&grant_type=refresh_token
    
    The Secure Token service validates the refresh token and once again returns an access token, a refresh token. and the time left before the access token expires. Store these values on your app's backend if it uses one.

  5. Call the API that requires authorization with the access token. For example:

    GET /example_endpoint HTTP/1.1
    Authorization: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3Mi
    Host: apis.example.com

  6. On your API's backend server, decode the access token, verify its integrity, and get the user's ID; then return the requested data.

    An access token, when decoded, is a JSON object like the following:

    {
      "iss": "https://securetoken.google.com",
      "sub": "user_id"
      "aud": "project_id",
      "iat": issued_at,
      "exp": seconds_to_expiration,
      "email": "user_email"
    }

    You can use any JWT library to decode the access token and verify some of its claims.

    To verify the token, you must verify its signature, and then confirm that the iss claim is https://securetoken.google.com, that the aud claim is your project's Developers Console ID, and that the token hasn't expired.

    For example, in Python, using Flask and PyJWT:

    @app.route("/example_endpoint")
    def example_endpoint():
        access_token = flask.headers["Authorization"]
        try:
            user_data = jwt.decode(access_token,
                                   issuer="https://securetoken.google.com",
                                   audience="exemplary-example-123456")
        except jwt.InvalidTokenError:
            return 401  # Invalid token
        except jwt.ExpiredSignatureError:
            return 401  # Token has expired
        except jwt.InvalidIssuerError:
            return 401  # Token is not issued by Google
        except jwt.InvalidAudienceError:
            return 401  # Token is not valid for this endpoint
        user_id = user_data["sub"]
        data = get_some_data_by_user_id(user_id)
        return json.dumps(data)
    

    If the access token is valid, use the value of the sub claim to look up and return the requested data.