# Starlette Integration

Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services.

This documentation covers OAuth 2.0 and OpenID Connect Client support for Starlette. Because all the frameworks integrations share the same API, it is best to:

Read Web Clients at first.

The difference between Starlette and Flask/Django integrations is Starlette is async. We will use `await` for the functions we need to call. But first, let’s create an `OAuth` instance:

    from authlib.integrations.starlette_client import OAuth

    oauth = OAuth()

The common use case for OAuth is authentication, e.g. let your users log in with Twitter, GitHub, Google etc.

## Register Remote Apps

`oauth.register` is the same as Web Clients:

    oauth.register(
        'google',
        client_id='...',
        client_secret='...',
        ...
    )

However, unlike Flask/Django, Starlette OAuth registry uses HTTPX `AsyncOAuth2Client` as the OAuth 2.0 backend. While Flask and Django are using the Requests version of `OAuth2Session`.

## Routes for Authorization

Just like the examples in Web Clients, but Starlette is async, the routes for authorization should look like:

    @app.route('/login/google')
    async def login_via_google(request):
        google = oauth.create_client('google')
        redirect_uri = request.url_for('authorize_google')
        return await google.authorize_redirect(request, redirect_uri)

    @app.route('/auth/google')
    async def authorize_google(request):
        google = oauth.create_client('google')
        token = await google.authorize_access_token(request)
        # do something with the token and userinfo
        return '...'

## Starlette OpenID Connect

An OpenID Connect client is no different than a normal OAuth 2.0 client, just add `openid` scope when `.register`. The built-in Starlette OAuth client will handle everything automatically:

    oauth.register(
        'google',
        ...
        server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
        client_kwargs={'scope': 'openid profile email'}
    )

When we get the returned token:

    token = await oauth.google.authorize_access_token()

There should be a `id_token` in the response. Authlib has called .parse_id_token automatically, we can get `userinfo` in the `token`:

    userinfo = token['userinfo']

## RP-Initiated Logout

To implement OpenID Connect RP-Initiated Logout, use the `logout_redirect` method to redirect users to the provider’s end session endpoint:

    @app.route('/logout')
    async def logout(request):
        # Retrieve the ID token you stored during login
        id_token = request.session.pop('id_token', None)
        redirect_uri = request.url_for('logged_out')
        return await oauth.google.logout_redirect(
            request,
            post_logout_redirect_uri=str(redirect_uri),
            id_token_hint=id_token,
        )

    @app.route('/logged-out')
    async def logged_out(request):
        state_data = await oauth.google.validate_logout_response(request)
        return PlainTextResponse('You have been logged out.')

The `logout_redirect` method accepts:

- `request`: The Starlette request object (required)

- `post_logout_redirect_uri`: Where to redirect after logout (must be registered with the provider)

- `id_token_hint`: The ID token previously issued (recommended)

- `state`: Opaque value for CSRF protection (auto-generated if not provided)

- `client_id`: OAuth 2.0 Client Identifier (optional)

- `logout_hint`: Hint about the user logging out (optional)

- `ui_locales`: Preferred languages for the logout UI (optional)

Note

You must store the `id_token` during login to use it later for logout. The `id_token` is available in `token['id_token']` after calling `authorize_access_token()`.

## Examples

We have Starlette demos at https://github.com/authlib/demo-oauth-client

1. Starlette Google login