Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 56767fd

Browse files
authored
Merge pull request auth0#465 from auth0/v4
2 parents 5eeb93d + c2183c4 commit 56767fd

File tree

121 files changed

+1050
-1220
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

121 files changed

+1050
-1220
lines changed

.circleci/config.yml

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,34 @@ orbs:
55
ship: auth0/[email protected]
66
codecov: codecov/codecov@3
77

8-
executors:
9-
python_3_10:
10-
docker:
11-
- image: cimg/python:3.10
12-
python_2_7:
13-
docker:
14-
- image: cimg/python:2.7
15-
168
jobs:
17-
python_3:
18-
executor: python_3_10
9+
build_and_test:
10+
parameters:
11+
py_version:
12+
type: string
13+
default: "3.10"
14+
docker:
15+
- image: cimg/python:<< parameters.py_version >>
1916
steps:
2017
- checkout
2118
- python/install-packages:
2219
pkg-manager: pip
2320
- run: pre-commit run --all-files
2421
- run: coverage run -m unittest
2522
- run: bash <(curl -s https://codecov.io/bash)
26-
- run: make -C docs html
27-
28-
python_2:
29-
executor: python_2_7
30-
steps:
31-
- checkout
32-
- python/install-packages:
33-
pkg-manager: pip-dist
34-
path-args: ".[test]"
35-
- run: coverage run -m unittest discover -s auth0/v3/test -t .
36-
- codecov/upload
23+
- when:
24+
condition:
25+
equal: [ "3.10", << parameters.py_version >> ]
26+
steps:
27+
- run: make -C docs html
3728

3829
workflows:
3930
main:
4031
jobs:
41-
- python_3
42-
- python_2
32+
- build_and_test:
33+
matrix:
34+
parameters:
35+
py_version: [ "3.7", "3.8", "3.9", "3.10", "3.11" ]
4336
- ship/python-publish:
4437
prefix-tag: false
4538
context:
@@ -50,5 +43,4 @@ workflows:
5043
only:
5144
- master
5245
requires:
53-
- python_3
54-
- python_2
46+
- build_and_test

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ bin/
2626
*.egg
2727
.pypirc
2828
pyvenv.cfg
29+
.python-version
2930

3031
# Installer logs
3132
pip-log.txt

EXAMPLES.md

Lines changed: 25 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
- [Authentication SDK](#authentication-sdk)
44
- [ID token validation](#id-token-validation)
5-
- [Organizations](#organizations)
5+
- [Authenticating with a application configured to use `private_key_jwt` token endpoint auth method](#authenticating-with-a-application-configured-to-use-private-key-jwt-token-endpoint-auth-method)
66
- [Management SDK](#management-sdk)
77
- [Connections](#connections)
88
- [Error handling](#error-handling)
@@ -32,7 +32,7 @@ For symmetric algorithms like HS256, use the `SymmetricSignatureVerifier` class,
3232
The following example demonstrates the verification of an ID token signed with the RS256 signing algorithm:
3333

3434
```python
35-
from auth0.v3.authentication.token_verifier import TokenVerifier, AsymmetricSignatureVerifier
35+
from auth0.authentication import TokenVerifier, AsymmetricSignatureVerifier
3636

3737
domain = 'myaccount.auth0.com'
3838
client_id = 'exampleid'
@@ -50,102 +50,26 @@ tv.verify(id_token)
5050

5151
If the token verification fails, a `TokenValidationError` will be raised. In that scenario, the ID token should be deemed invalid and its contents should not be trusted.
5252

53-
54-
55-
### Organizations
56-
57-
[Organizations](https://auth0.com/docs/organizations) is a set of features that provide better support for developers who build and maintain SaaS and Business-to-Business (B2B) applications.
58-
59-
Note that Organizations is currently only available to customers on our Enterprise and Startup subscription plans.
60-
61-
62-
#### Log in to an organization
63-
64-
Log in to an organization by specifying the ``organization`` property when calling ``authorize()``:
65-
66-
```python
67-
from auth0.v3.authentication.authorize_client import AuthorizeClient
68-
69-
client = AuthorizeClient('my.domain.com')
70-
71-
client.authorize(client_id='client_id',
72-
redirect_uri='http://localhost',
73-
organization="org_abc")
74-
```
75-
76-
When logging into an organization, it is important to ensure the `org_id` claim of the ID Token matches the expected organization value. The `TokenVerifier` can be be used to ensure the ID Token contains the expected `org_id` claim value:
53+
### Authenticating with a application configured to use `private_key_jwt` token endpoint auth method
7754

7855
```python
79-
from auth0.v3.authentication.token_verifier import TokenVerifier, AsymmetricSignatureVerifier
80-
81-
domain = 'myaccount.auth0.com'
82-
client_id = 'exampleid'
83-
84-
# After authenticating
85-
id_token = auth_result['id_token']
86-
87-
jwks_url = 'https://{}/.well-known/jwks.json'.format(domain)
88-
issuer = 'https://{}/'.format(domain)
89-
90-
sv = AsymmetricSignatureVerifier(jwks_url) # Reusable instance
91-
tv = TokenVerifier(signature_verifier=sv, issuer=issuer, audience=client_id)
92-
93-
# pass the expected organization the user logged in to:
94-
tv.verify(id_token, organization='org_abc')
95-
96-
```
97-
98-
#### Accept user invitations
99-
100-
Accept a user invitation by specifying the `invitation` property when calling `authorize()`. Note that you must also specify the ``organization`` if providing an ``invitation``.
101-
The ID of the invitation and organization are available as query parameters on the invitation URL, e.g., ``https://your-domain.auth0.com/login?invitation=invitation_id&organization=org_id&organization_name=org_name``
102-
103-
```python
104-
from auth0.v3.authentication.authorize_client import AuthorizeClient
105-
106-
client = AuthorizeClient('my.domain.com')
107-
108-
client.authorize(client_id='client_id',
109-
redirect_uri='http://localhost',
110-
organization='org_abc',
111-
invitation="invitation_123")
112-
```
113-
114-
#### Authorizing users from an Organization
115-
116-
If an `org_id` claim is present in the Access Token, then the claim should be validated by the API to ensure that the value received is expected or known.
117-
118-
In particular:
119-
120-
- The issuer (`iss`) claim should be checked to ensure the token was issued by Auth0
121-
- The organization ID (`org_id`) claim should be checked to ensure it is a value that is already known to the application. This could be validated against a known list of organization IDs, or perhaps checked in conjunction with the current request URL. e.g. the sub-domain may hint at what organization should be used to validate the Access Token.
122-
123-
Normally, validating the issuer would be enough to ensure that the token was issued by Auth0. In the case of organizations, additional checks should be made so that the organization within an Auth0 tenant is expected.
124-
125-
If the claim cannot be validated, then the application should deem the token invalid.
126-
127-
The snippet below attempts to illustrate how this verification could look like using the external [PyJWT](https://pyjwt.readthedocs.io/en/latest/usage.html#encoding-decoding-tokens-with-rs256-rsa) library. This dependency will take care of pulling the RS256 Public Key that was used by the server to sign the Access Token. It will also validate its signature, expiration, and the audience value. After the basic verification, get the `org_id` claim and check it against the expected value. The code assumes your application is configured to sign tokens using the RS256 algorithm. Check the [Validate JSON Web Tokens](https://auth0.com/docs/tokens/json-web-tokens/validate-json-web-tokens) article to learn more about this verification.
128-
129-
```python
130-
import jwt # PyJWT
131-
from jwt import PyJWKClient
132-
133-
access_token = # access token from the request
134-
url = 'https://{YOUR AUTH0 DOMAIN}/.well-known/jwks.json'
135-
jwks_client = PyJWKClient(url)
136-
signing_key = jwks_client.get_signing_key_from_jwt(access_token)
137-
data = jwt.decode(
138-
access_token,
139-
signing_key.key,
140-
algorithms=['RS256'],
141-
audience='{YOUR API AUDIENCE}'
56+
from auth0.authentication import GetToken
57+
58+
private_key = """-----BEGIN RSA PRIVATE KEY-----
59+
MIIJKQIBAAKCAgEAwfUb0nUC0aKB3WiytFhnCIg455BYC+dR3MUGadWpIg7S6lbi
60+
...
61+
2tjIvH4GN9ZkIGwzxIOP61wkUGwGaIzacOTIWOvqRI0OaYr9U18Ep1trvgGR
62+
-----END RSA PRIVATE KEY-----
63+
"""
64+
65+
get_token = GetToken(
66+
"my-domain.us.auth0.com",
67+
"my-client-id",
68+
client_assertion_signing_key=private_key,
69+
)
70+
token = get_token.client_credentials(
71+
"https://my-domain.us.auth0.com/api/v2/"
14272
)
143-
144-
organization = # expected organization ID
145-
if data['org_id'] != organization:
146-
raise Exception('Organization (org_id) claim mismatch')
147-
148-
# if this line is reached, validation is successful
14973
```
15074

15175
## Management SDK
@@ -221,29 +145,29 @@ resets is exposed in the `reset_at` property. When the header is unset, this val
221145

222146
### Asynchronous environments
223147

224-
This SDK provides async methods built on top of [asyncio](https://docs.python.org/3/library/asyncio.html). To make them available you must have Python >=3.6 and the [aiohttp](https://docs.aiohttp.org/en/stable/) module installed.
148+
This SDK provides async methods built on top of [asyncio](https://docs.python.org/3/library/asyncio.html). To make them available you must have the [aiohttp](https://docs.aiohttp.org/en/stable/) module installed.
225149

226150
Then additional methods with the `_async` suffix will be added to modules created by the `management.Auth0` class or to classes that are passed to the `asyncify` method. For example:
227151

228152
```python
229153
import asyncio
230154
import aiohttp
231-
from auth0.v3.asyncify import asyncify
232-
from auth0.v3.management import Auth0, Users, Connections
233-
from auth0.v3.authentication import Users as AuthUsers
155+
from auth0.asyncify import asyncify
156+
from auth0.management import Auth0, Users, Connections
157+
from auth0.authentication import Users as AuthUsers
234158

235159
auth0 = Auth0('domain', 'mgmt_api_token')
236160

161+
237162
async def main():
238163
# users = auth0.users.all() <= sync
239-
users = await auth0.users.all_async() # <= async
164+
users = await auth0.users.all_async() # <= async
240165

241166
# To share a session amongst multiple calls to the same service
242167
async with auth0.users as users:
243168
data = await users.get_async(id)
244169
users.update_async(id, data)
245170

246-
247171
# To share a session amongst multiple calls to multiple services
248172
async with Auth0('domain', 'mgmt_api_token') as auth0:
249173
user = await auth0.users.get_async(user_id)

README.md

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ You can install the auth0 Python SDK using the following command.
2222
pip install auth0-python
2323
```
2424

25-
For python3, use the following command
26-
```
27-
pip3 install auth0-python
28-
```
29-
Python 3.2 and 3.3 have reached [EOL](https://en.wikipedia.org/wiki/CPython#Version_history) and support will be removed in the near future.
25+
> Requires Python 3.7 or higher.
3026
3127
### Usage
3228

@@ -36,53 +32,52 @@ The Authentication SDK is organized into components that mirror the structure of
3632
For example:
3733

3834
```python
39-
from auth0.v3.authentication import Social
35+
from auth0.authentication import Social
4036

41-
social = Social('myaccount.auth0.com')
37+
social = Social('my-domain.us.auth0.com', 'my-client-id')
4238

43-
social.login(client_id='...', access_token='...', connection='facebook')
39+
social.login(access_token='...', connection='facebook')
4440
```
4541

4642
If you need to sign up a user using their email and password, you can use the Database object.
4743

4844
```python
49-
from auth0.v3.authentication import Database
45+
from auth0.authentication import Database
5046

51-
database = Database('myaccount.auth0.com'')
47+
database = Database('my-domain.us.auth0.com', 'my-client-id')
5248

53-
database.signup(client_id='...', email='[email protected]', password='secr3t', connection='Username-Password-Authentication')
49+
database.signup(email='[email protected]', password='secr3t', connection='Username-Password-Authentication')
5450
```
5551

5652
If you need to authenticate a user using their email and password, you can use the `GetToken` object, which enables making requests to the `/oauth/token` endpoint.
5753

5854
```python
59-
from auth0.v3.authentication import GetToken
55+
from auth0.authentication import GetToken
6056

61-
token = GetToken('myaccount.auth0.com')
57+
token = GetToken('my-domain.us.auth0.com', 'my-client-id', client_secret='my-client-secret')
6258

63-
token.login(client_id='...', client_secret='...', username='[email protected]', password='secr3t', realm='Username-Password-Authentication')
59+
token.login(username='[email protected]', password='secr3t', realm='Username-Password-Authentication')
6460
```
6561

6662
#### Management SDK
6763
To use the management library you will need to instantiate an Auth0 object with a domain and a [Management API v2 token](https://auth0.com/docs/api/management/v2/tokens). Please note that these token last 24 hours, so if you need it constantly you should ask for it programmatically using the client credentials grant with a [non interactive client](https://auth0.com/docs/api/management/v2/tokens#1-create-and-authorize-a-client) authorized to access the API. For example:
6864

6965
```python
70-
from auth0.v3.authentication import GetToken
66+
from auth0.authentication import GetToken
7167

7268
domain = 'myaccount.auth0.com'
7369
non_interactive_client_id = 'exampleid'
7470
non_interactive_client_secret = 'examplesecret'
7571

76-
get_token = GetToken(domain)
77-
token = get_token.client_credentials(non_interactive_client_id,
78-
non_interactive_client_secret, 'https://{}/api/v2/'.format(domain))
72+
get_token = GetToken(domain, non_interactive_client_id, client_secret=non_interactive_client_secret)
73+
token = get_token.client_credentials('https://{}/api/v2/'.format(domain))
7974
mgmt_api_token = token['access_token']
8075
```
8176

8277
Then use the token you've obtained as follows:
8378

8479
```python
85-
from auth0.v3.management import Auth0
80+
from auth0.management import Auth0
8681

8782
domain = 'myaccount.auth0.com'
8883
mgmt_api_token = 'MGMT_API_TOKEN'
@@ -98,7 +93,6 @@ For more code samples on how to integrate the auth0-python SDK in your Python ap
9893

9994
### Authentication Endpoints
10095

101-
- API Authorization - Authorization Code Grant (`authentication.AuthorizeClient`)
10296
- Database ( `authentication.Database` )
10397
- Delegated ( `authentication.Delegated` )
10498
- Enterprise ( `authentication.Enterprise` )
@@ -115,6 +109,7 @@ For more code samples on how to integrate the auth0-python SDK in your Python ap
115109
- AttackProtection() (`Auth0().attack_protection`)
116110
- Blacklists() ( `Auth0().blacklists` )
117111
- Branding() ( `Auth0().branding` )
112+
- ClientCredentials() ( `Auth0().client_credentials` )
118113
- ClientGrants() ( `Auth0().client_grants` )
119114
- Clients() ( `Auth0().clients` )
120115
- Connections() ( `Auth0().connections` )
@@ -140,6 +135,33 @@ For more code samples on how to integrate the auth0-python SDK in your Python ap
140135
- UserBlocks() (`Auth0().user_blocks` )
141136
- UsersByEmail() ( `Auth0().users_by_email` )
142137
- Users() ( `Auth0().users` )
138+
139+
## Support Policy
140+
141+
Our support lifecycle policy mirrors the [Python support schedule](https://devguide.python.org/versions/). We do not support running the SDK on unsupported versions of Python that have ceased to receive security updates. Please ensure your environment remains up to date and running the latest Python version possible.
142+
143+
| SDK Version | Python Version | Support Ends |
144+
|-------------| -------------- | ------------ |
145+
| 4.x | 3.11 | Oct 2027 |
146+
| | 3.10 | Oct 2026 |
147+
| | 3.9 | Oct 2025 |
148+
| | 3.8 | Oct 2024 |
149+
| | 3.7 | Oct 2023 |
150+
151+
> As `pip` [reliably avoids](https://packaging.python.org/en/latest/tutorials/packaging-projects/#configuring-metadata) installing package updates that target incompatible Python versions, we may opt to remove support for [end-of-life](https://en.wikipedia.org/wiki/CPython#Version_history) Python versions during minor SDK updates. These are not considered breaking changes by this SDK.
152+
153+
The following is a list of unsupported Python versions, and the last SDK version supporting them:
154+
155+
| Python Version | Last SDK Version Supporting |
156+
| -------------- |-----------------------------|
157+
| >= 2.0, <= 3.6 | 3.x |
158+
159+
You can determine what version of Python you have installed by running:
160+
161+
```
162+
python --version
163+
```
164+
143165
## Feedback
144166

145167
### Contributing

0 commit comments

Comments
 (0)