File: httpx.rst

package info (click to toggle)
python-authlib 1.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 3,016 kB
  • sloc: python: 26,998; makefile: 53; sh: 14
file content (223 lines) | stat: -rw-r--r-- 6,408 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
.. _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.