Starlette is a lightweight ASGI framework/toolkit, which is ideal for building high performance asyncio services.
This documentation covers OAuth 1.0, 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 OAuth 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.
Starlette can load configuration from environment; Authlib implementation for Starlette client can use this configuration. Here is an example of how to do it:
from starlette.config import Config
config = Config('.env')
oauth = OAuth(config)
Authlib will load client_id
and client_secret
from the configuration,
take google as an example:
oauth.register(name='google', ...)
It will load GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET from the environment.
oauth.register
is the same as Web OAuth Clients:
oauth.register(
'google',
client_id='...',
client_secret='...',
...
)
However, unlike Flask/Django, Starlette OAuth registry is using HTTPX
AsyncOAuth1Client
and
AsyncOAuth2Client
as the OAuth
backends. While Flask and Django are using the Requests version of
OAuth1Session
and
OAuth2Session
.
With OAuth 1.0, we need to use a temporary credential to exchange for an access token. This temporary credential is created before redirecting to the provider (Twitter), and needs to be saved somewhere in order to use it later.
With OAuth 1, the Starlette client will save the request token in sessions. To
enable this, we need to add the SessionMiddleware
middleware to the
application, which requires the installation of the itsdangerous
package:
from starlette.applications import Starlette
from starlette.middleware.sessions import SessionMiddleware
app = Starlette()
app.add_middleware(SessionMiddleware, secret_key="some-random-string")
However, using the SessionMiddleware
will store the temporary credential as
a secure cookie which will expose your request token to the client.
Just like the examples in Web OAuth Clients, but Starlette is async, the routes for authorization should look like:
@app.route('/login')
async def login(request):
google = oauth.create_client('google')
redirect_uri = request.url_for('authorize')
return await google.authorize_redirect(request, redirect_uri)
@app.route('/auth')
async def authorize(request):
google = oauth.create_client('google')
token = await google.authorize_access_token(request)
user = await google.parse_id_token(request, token)
# do something with the token and profile
return '...'
An OpenID Connect client is no different than a normal OAuth 2.0 client, just add
openid
scope when .register
. In the above example, in authorize
:
user = await google.parse_id_token(request, token)
There is a id_token
in the response token
. We can parse userinfo from this
id_token
.
Here is how you can add openid
scope in .register
:
oauth.register(
'google',
...
server_metadata_url='https://accounts.google.com/.well-known/openid-configuration',
client_kwargs={'scope': 'openid profile email'}
)
We have Starlette demos at https://github.com/authlib/demo-oauth-client