Google login for FastAPI

An example of how to implement OpenID Connect clients in FastAPI.

FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.

It is created on top of Starlette. A FastAPI app is basically a Starlette app, that is why you can just use Authlib Starlette integration to create OAuth clients for FastAPI.

We have a post on How to create a Twitter login for FastAPI, in this post we will use Google as an example.

Create OAuth client

A typical OAuth client for Starlette or FastAPI:

from authlib.integrations.starlette_client import OAuth
from starlette.config import Config

config = Config('.env')  # read config from .env file
oauth = OAuth(config)
oauth.register(
    name='google',
    server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
    client_kwargs={
        'scope': 'openid email profile'
    }
)

We don't need to add client_id and client_secret here, because they are in .env file. You are not supposed to hard code them in the code in real products.

This configuration is very different than Twitter. Since Google has an OpenID discovery endpoint, we can use this URL for server_metadata_url. Authlib will fetch this server_metadata_url to configure the OAuth client for you.

Implement login route

First, create a FastAPI application:

from fastapi import FastAPI
from starlette.middleware.sessions import SessionMiddleware

app = FastAPI()
app.add_middleware(SessionMiddleware, secret_key="secret-string")

We need this SessionMiddleware, because Authlib will use request.session to store temporary codes and states.

Next, the /login route will redirect us to Google website to grant access:

@app.route('/login')
async def login(request: Request):
    # absolute url for callback
    # we will define it below
    redirect_uri = request.url_for('auth')
    return await oauth.google.authorize_redirect(request, redirect_uri)

The above code will redirect you to Google account website.

Handle authentication callback

When you grant access from Google website, Google will redirect back to your given redirect_uri, which is request.url_for('auth'):

@app.route('/auth')
async def auth(request: Request):
    token = await oauth.google.authorize_access_token(request)
    user = await oauth.google.parse_id_token(request, token)
    return user

The above code will obtain a token which contains access_token and id_token. An id_token contains user info, we just need to parse it to get the login user's information.

Hint

You can check the full example: https://github.com/authlib/demo-oauth-client/tree/master/fastapi-google-login.