docs/client/httpx.rst
.. _httpx_client:
OAuth for HTTPX
===============
.. meta::
:description: An OAuth 1.0 and OAuth 2.0 Client implementation for a next
generation HTTP client for Python, including support for OpenID Connect
and service account, powered by Authlib.
.. module:: authlib.integrations.httpx_client
:noindex:
HTTPX is a next-generation HTTP client for Python. Authlib enables OAuth 1.0
and OAuth 2.0 for HTTPX with its async versions:
* :class:`OAuth1Client`
* :class:`OAuth2Client`
* :class:`AssertionClient`
* :class:`AsyncOAuth1Client`
* :class:`AsyncOAuth2Client`
* :class:`AsyncAssertionClient`
.. note:: HTTPX is still in its "alpha" stage, use it with caution.
HTTPX OAuth 1.0
---------------
There are three steps in OAuth 1 to obtain an access token:
1. fetch a temporary credential
2. visit the authorization page
3. exchange access token with the temporary credential
It shares a common API design with :ref:`requests_client`.
Read the common guide of :ref:`oauth_1_session` to understand the whole OAuth
1.0 flow.
HTTPX OAuth 2.0
---------------
In :ref:`oauth_2_session`, there are many grant types, including:
1. Authorization Code Flow
2. Implicit Flow
3. Password Flow
4. Client Credentials Flow
And also, Authlib supports non Standard OAuth 2.0 providers via Compliance Fix.
Read the common guide of :ref:`oauth_2_session` to understand the whole OAuth
2.0 flow.
Using ``client_secret_jwt`` in HTTPX
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is how you could register and use ``client_secret_jwt`` client
authentication method for HTTPX::
from authlib.integrations.httpx_client import AsyncOAuth2Client
from authlib.oauth2.rfc7523 import ClientSecretJWT
client = AsyncOAuth2Client(
'your-client-id', 'your-client-secret',
token_endpoint_auth_method='client_secret_jwt'
)
token_endpoint = 'https://example.com/oauth/token'
client.register_client_auth_method(ClientSecretJWT(token_endpoint))
client.fetch_token(token_endpoint)
The ``ClientSecretJWT`` is provided by :ref:`specs/rfc7523`.
Using ``private_key_jwt`` in HTTPX
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Here is how you could register and use ``private_key_jwt`` client
authentication method for HTTPX::
from authlib.integrations.httpx_client import AsyncOAuth2Client
from authlib.oauth2.rfc7523 import PrivateKeyJWT
with open('your-private-key.pem', 'rb') as f:
private_key = f.read()
client = AsyncOAuth2Client(
'your-client-id', private_key,
token_endpoint_auth_method='private_key_jwt',
)
token_endpoint = 'https://example.com/oauth/token'
client.register_client_auth_method(PrivateKeyJWT(token_endpoint))
client.fetch_token(token_endpoint)
The ``PrivateKeyJWT`` is provided by :ref:`specs/rfc7523`.
Async OAuth 1.0
---------------
The async version of :class:`AsyncOAuth1Client` works the same as
:ref:`oauth_1_session`, except that we need to add ``await`` when
required::
# fetching request token
request_token = await client.fetch_request_token(request_token_url)
# fetching access token
access_token = await client.fetch_access_token(access_token_url)
# normal requests
await client.get(...)
await client.post(...)
await client.put(...)
await client.delete(...)
Async OAuth 2.0
---------------
The async version of :class:`AsyncOAuth2Client` works the same as
:ref:`oauth_2_session`, except that we need to add ``await`` when
required::
# fetching access token
token = await client.fetch_token(token_endpoint, ...)
# normal requests
await client.get(...)
await client.post(...)
await client.put(...)
await client.delete(...)
Auto Update Token
~~~~~~~~~~~~~~~~~
The :class:`AsyncOAuth2Client` also supports ``update_token`` parameter,
the ``update_token`` can either be sync and async. For instance::
async def update_token(token, refresh_token=None, access_token=None):
if refresh_token:
item = await OAuth2Token.find(name=name, refresh_token=refresh_token)
elif access_token:
item = await 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']
await item.save()
Then pass this ``update_token`` into ``AsyncOAuth2Client``.
Async Service Account
---------------------
:class:`AsyncAssertionClient` is the async version for Assertion Framework of
OAuth 2.0 Authorization Grants. It is also know as service account. A configured
``AsyncAssertionClient`` will handle token authorization automatically,
which means you can just use it.
Take Google Service Account as an example, with the information in your
service account JSON configure file::
import json
from authlib.integrations.httpx_client import AsyncAssertionClient
with open('MyProject-1234.json') as f:
conf = json.load(f)
token_uri = conf['token_uri']
header = {'alg': 'RS256'}
key_id = conf.get('private_key_id')
if key_id:
header['kid'] = key_id
# Google puts scope in payload
claims = {'scope': scope}
async def main():
client = AsyncAssertionClient(
token_endpoint=token_uri,
issuer=conf['client_email'],
audience=token_uri,
claims=claims,
subject=None,
key=conf['private_key'],
header=header,
)
resp = await client.get(...)
resp = await client.post(...)
Close Client Hint
-----------------
Developers SHOULD **close** a HTTPX Session when the jobs are done. You
can call ``.close()`` manually, or use a ``with`` context to automatically
close the session::
client = OAuth2Client(client_id, client_secret)
client.get(url)
client.close()
with OAuth2Client(client_id, client_secret) as client:
client.get(url)
For **async** OAuth Client, use ``await client.close()``::
client = AsyncOAuth2Client(client_id, client_secret)
await client.get(url)
await client.close()
async with AsyncOAuth2Client(client_id, client_secret) as client:
await client.get(url)
Our :ref:`frameworks_clients` will close every session automatically, no need
to worry.