# Flask Integration

This documentation covers OAuth 2.0 and OpenID Connect Client support for Flask. Looking for OAuth 2.0 server?

- Flask Integration

Flask OAuth client shares a similar API with Flask-OAuthlib, you can transfer your code from Flask-OAuthlib to Authlib with ease.

Create a registry with `OAuth` object:

    from authlib.integrations.flask_client import OAuth

    oauth = OAuth(app)

You can also initialize it later with `init_app()` method:

    oauth = OAuth()
    oauth.init_app(app)

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

Important

Please read Web Clients at first. Authlib has a shared API design among framework integrations, learn them from Web Clients.

## Configuration

Authlib Flask OAuth registry can load the configuration from Flask `app.config` automatically. Every key-value pair in `.register` can be omitted. They can be configured in your Flask App configuration. Config keys are formatted as `{name}_{key}` in uppercase, e.g.

TWITTER_CLIENT_ID | Twitter Consumer Key
TWITTER_CLIENT_SECRET | Twitter Consumer Secret
TWITTER_REQUEST_TOKEN_URL | URL to fetch OAuth request token

If you register your remote app as `oauth.register('example', ...)`, the config keys would look like:

EXAMPLE_CLIENT_ID | OAuth Consumer Key
EXAMPLE_CLIENT_SECRET | OAuth Consumer Secret
EXAMPLE_ACCESS_TOKEN_URL | URL to fetch OAuth access token

Here is a full list of the configuration keys:

- `{name}_CLIENT_ID`: Client key of OAuth 1, or Client ID of OAuth 2

- `{name}_CLIENT_SECRET`: Client secret of OAuth 2, or Client Secret of OAuth 2

- `{name}_REQUEST_TOKEN_URL`: Request Token endpoint for OAuth 1

- `{name}_REQUEST_TOKEN_PARAMS`: Extra parameters for Request Token endpoint

- `{name}_ACCESS_TOKEN_URL`: Access Token endpoint for OAuth 1 and OAuth 2

- `{name}_ACCESS_TOKEN_PARAMS`: Extra parameters for Access Token endpoint

- `{name}_AUTHORIZE_URL`: Endpoint for user authorization of OAuth 1 or OAuth 2

- `{name}_AUTHORIZE_PARAMS`: Extra parameters for Authorization Endpoint.

- `{name}_API_BASE_URL`: A base URL endpoint to make requests simple

- `{name}_CLIENT_KWARGS`: Extra keyword arguments for OAuth1Session or OAuth2Session

We suggest that you keep ONLY `{name}_CLIENT_ID` and `{name}_CLIENT_SECRET` in your Flask application configuration.

## Routes for Authorization

Unlike the examples in Web Clients, Flask does not pass a `request` into routes. In this case, the routes for authorization should look like:

    from flask import url_for, redirect

    @app.route('/login')
    def login():
        redirect_uri = url_for('authorize', _external=True)
        return oauth.github.authorize_redirect(redirect_uri)

    @app.route('/authorize')
    def authorize():
        token = oauth.github.authorize_access_token()
        resp = oauth.github.get('user')
        resp.raise_for_status()
        profile = resp.json()
        # do something with the token and profile
        return redirect('/')

## Accessing OAuth Resources

There is no `request` in accessing OAuth resources either. Just like above, we don’t need to pass the `request` parameter, everything is handled by Authlib automatically:

    from flask import render_template

    @app.route('/github')
    def show_github_profile():
        resp = oauth.github.get('user')
        resp.raise_for_status()
        profile = resp.json()
        return render_template('github.html', profile=profile)

In this case, our `fetch_token` could look like:

    from your_project import current_user

    def fetch_token(name):
        token = OAuth2Token.find(
            name=name,
            user=current_user,
        )
        return token.to_token()

    # initialize the OAuth registry with this fetch_token function
    oauth = OAuth(fetch_token=fetch_token)

You don’t have to pass `token`, you don’t have to pass `request`. That is the fantasy of Flask.

## Auto Update Token via Signal

Instead of defining an `update_token` method and passing it into the OAuth registry, it is also possible to use a signal to listen for token updating.

Before using the signal, make sure you have installed the blinker library:

    $ pip install blinker

Connect the `token_update` signal:

    from authlib.integrations.flask_client import token_update

    @token_update.connect_via(app)
    def on_token_update(sender, name, token, refresh_token=None, access_token=None):
        if refresh_token:
            item = OAuth2Token.find(name=name, refresh_token=refresh_token)
        elif access_token:
            item = OAuth2Token.find(name=name, access_token=access_token)
        else:
            return

        # update old token
        item.access_token = token['access_token']
        item.refresh_token = token.get('refresh_token')
        item.expires_at = token['expires_at']
        item.save()

## Flask OpenID Connect Client

An OpenID Connect client is no different than a normal OAuth 2.0 client. When registered with `openid` scope, the built-in Flask 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 = 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')
    def logout():
        # Retrieve the ID token you stored during login
        id_token = session.pop('id_token', None)
        return oauth.google.logout_redirect(
            post_logout_redirect_uri=url_for('logged_out', _external=True),
            id_token_hint=id_token,
        )

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

The `logout_redirect` method accepts:

- `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

Here are some example projects for you to learn Flask OAuth 2.0 client integrations:

1. Flask Google Login.