Flask Integration¶
This documentation covers OAuth 2.0 and OpenID Connect Client support for Flask. Looking for OAuth 2.0 server?
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.
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: