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

Skip to content

Commit 9ef681a

Browse files
committed
Add support for private_key_jwt
1 parent cd950b0 commit 9ef681a

27 files changed

+349
-417
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ If you need to sign up a user using their email and password, you can use the Da
4848
```python
4949
from auth0.v3.authentication import Database
5050

51-
database = Database('myaccount.auth0.com'')
51+
database = Database('myaccount.auth0.com')
5252

5353
database.signup(client_id='...', email='[email protected]', password='secr3t', connection='Username-Password-Authentication')
5454
```
@@ -140,6 +140,7 @@ For more code samples on how to integrate the auth0-python SDK in your Python ap
140140
- UserBlocks() (`Auth0().user_blocks` )
141141
- UsersByEmail() ( `Auth0().users_by_email` )
142142
- Users() ( `Auth0().users` )
143+
143144
## Feedback
144145

145146
### Contributing

V4_MIGRATION_GUIDE.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# V4 Migration Guide
2+
3+
Guide to migrating from `3.x` to `4.x`
4+
5+
- [Python <3.6 is no longer supported](#python-36-is-no-longer-supported)
6+
- [Client ID and Client Secret are now specified in the constructor for Authentication Clients](#client-id-and-client-secret-are-now-specified-in-the-constructor-for-authentication-clients)
7+
8+
## Python <3.6 is no longer supported
9+
10+
Python 3.5 and Python 2 are EOL and are no longer supported.
11+
12+
## Client ID and Client Secret are now specified in the constructor for Authentication Clients
13+
14+
### Before
15+
16+
```py
17+
from auth0.v3.authentication import GetToken
18+
19+
get_token = GetToken('myaccount.auth0.com')
20+
21+
get_token.client_credentials('my-client-id', 'my-client-secret', 'my-api')
22+
```
23+
24+
### After
25+
26+
```py
27+
from auth0.v3.authentication import GetToken
28+
29+
# `client_secret` is optional (you can now use `client_assertion_signing_key` as an alternative)
30+
get_token = GetToken('myaccount.auth0.com', 'my-client-id', client_secret='my-client-secret')
31+
32+
get_token.client_credentials('my-api')
33+
```

auth0/v3/authentication/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
from .authorize_client import AuthorizeClient
21
from .database import Database
32
from .delegated import Delegated
43
from .enterprise import Enterprise
54
from .get_token import GetToken
6-
from .logout import Logout
75
from .passwordless import Passwordless
86
from .revoke_token import RevokeToken
97
from .social import Social

auth0/v3/authentication/authorize_client.py

Lines changed: 0 additions & 40 deletions
This file was deleted.

auth0/v3/authentication/base.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from auth0.v3.rest import RestClient, RestClientOptions
99

1010
from ..exceptions import Auth0Error, RateLimitError
11+
from .client_authentication import add_client_authentication
1112

1213
UNKNOWN_ERROR = "a0.sdk.internal.unknown"
1314

@@ -16,24 +17,60 @@ class AuthenticationBase(object):
1617
"""Base authentication object providing simple REST methods.
1718
1819
Args:
20+
domain (str): The domain of your auth0 tenant
21+
client_id (str): your application's client Id
22+
client_secret (str, optional): your application's client Secret
23+
client_assertion_signing_key (str, optional): Private key used to sign the client assertion JWT.
24+
client_assertion_signing_alg (str, optional): Algorithm used to sign the client assertion JWT (Default RS256).
1925
telemetry (bool, optional): Enable or disable Telemetry
2026
(defaults to True)
2127
timeout (float or tuple, optional): Change the requests
2228
connect and read timeout. Pass a tuple to specify
2329
both values separately or a float to set both to it.
2430
(defaults to 5.0 for both)
31+
protocol (str, optional): Useful for testing.
32+
(defaults to 'https')
2533
"""
2634

27-
def __init__(self, domain, telemetry=True, timeout=5.0, protocol="https"):
35+
def __init__(
36+
self,
37+
domain,
38+
client_id,
39+
client_secret=None,
40+
client_assertion_signing_key=None,
41+
client_assertion_signing_alg=None,
42+
telemetry=True,
43+
timeout=5.0,
44+
protocol="https",
45+
):
2846
self.domain = domain
47+
self.client_id = client_id
48+
self.client_secret = client_secret
49+
self.client_assertion_signing_key = client_assertion_signing_key
50+
self.client_assertion_signing_alg = client_assertion_signing_alg
2951
self.protocol = protocol
3052
self.client = RestClient(
3153
None,
3254
options=RestClientOptions(telemetry=telemetry, timeout=timeout, retries=0),
3355
)
3456

57+
def _add_client_authentication(self, payload):
58+
return add_client_authentication(
59+
payload,
60+
self.domain,
61+
self.client_id,
62+
self.client_secret,
63+
self.client_assertion_signing_key,
64+
self.client_assertion_signing_alg,
65+
)
66+
3567
def post(self, url, data=None, headers=None):
36-
return self.client.post(url, data, headers)
68+
return self.client.post(url, data=data, headers=headers)
69+
70+
def authenticated_post(self, url, data=None, headers=None):
71+
return self.client.post(
72+
url, data=self._add_client_authentication(data), headers=headers
73+
)
3774

3875
def get(self, url, params=None, headers=None):
3976
return self.client.get(url, params, headers)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import datetime
2+
import uuid
3+
4+
import jwt
5+
6+
7+
def create_client_assertion_jwt(
8+
domain, client_id, client_assertion_signing_key, client_assertion_signing_alg
9+
):
10+
client_assertion_signing_alg = client_assertion_signing_alg or "RS256"
11+
now = datetime.datetime.utcnow()
12+
return jwt.encode(
13+
{
14+
"iss": client_id,
15+
"sub": client_id,
16+
"aud": "https://{}/".format(domain),
17+
"iat": now,
18+
"exp": now + datetime.timedelta(seconds=180),
19+
"jti": str(uuid.uuid4()),
20+
},
21+
client_assertion_signing_key,
22+
client_assertion_signing_alg,
23+
)
24+
25+
26+
def add_client_authentication(
27+
payload,
28+
domain,
29+
client_id,
30+
client_secret,
31+
client_assertion_signing_key,
32+
client_assertion_signing_alg,
33+
):
34+
authenticated_payload = payload.copy()
35+
if client_assertion_signing_key:
36+
authenticated_payload["client_assertion"] = create_client_assertion_jwt(
37+
domain,
38+
client_id,
39+
client_assertion_signing_key,
40+
client_assertion_signing_alg,
41+
)
42+
authenticated_payload[
43+
"client_assertion_type"
44+
] = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
45+
elif client_secret:
46+
authenticated_payload["client_secret"] = client_secret
47+
return authenticated_payload

auth0/v3/authentication/database.py

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class Database(AuthenticationBase):
1212

1313
def login(
1414
self,
15-
client_id,
1615
username,
1716
password,
1817
connection,
@@ -34,7 +33,7 @@ def login(
3433
)
3534

3635
body = {
37-
"client_id": client_id,
36+
"client_id": self.client_id,
3837
"username": username,
3938
"password": password,
4039
"connection": connection,
@@ -51,7 +50,6 @@ def login(
5150

5251
def signup(
5352
self,
54-
client_id,
5553
email,
5654
password,
5755
connection,
@@ -66,8 +64,6 @@ def signup(
6664
"""Signup using email and password.
6765
6866
Args:
69-
client_id (str): ID of the application to use.
70-
7167
email (str): The user's email address.
7268
7369
password (str): The user's desired password.
@@ -93,7 +89,7 @@ def signup(
9389
See: https://auth0.com/docs/api/authentication#signup
9490
"""
9591
body = {
96-
"client_id": client_id,
92+
"client_id": self.client_id,
9793
"email": email,
9894
"password": password,
9995
"connection": connection,
@@ -117,17 +113,15 @@ def signup(
117113
"{}://{}/dbconnections/signup".format(self.protocol, self.domain), data=body
118114
)
119115

120-
def change_password(self, client_id, email, connection, password=None):
116+
def change_password(self, email, connection, password=None):
121117
"""Asks to change a password for a given user.
122118
123-
client_id (str): ID of the application to use.
124-
125119
email (str): The user's email address.
126120
127121
connection (str): The name of the database connection where this user should be created.
128122
"""
129123
body = {
130-
"client_id": client_id,
124+
"client_id": self.client_id,
131125
"email": email,
132126
"connection": connection,
133127
}

auth0/v3/authentication/delegated.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ class Delegated(AuthenticationBase):
1010

1111
def get_token(
1212
self,
13-
client_id,
1413
target,
1514
api_type,
1615
grant_type,
@@ -25,7 +24,7 @@ def get_token(
2524
raise ValueError("Only one of id_token or refresh_token can be None")
2625

2726
data = {
28-
"client_id": client_id,
27+
"client_id": self.client_id,
2928
"grant_type": grant_type,
3029
"target": target,
3130
"scope": scope,

auth0/v3/authentication/enterprise.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,12 @@ class Enterprise(AuthenticationBase):
99
domain (str): Your auth0 domain (e.g: username.auth0.com)
1010
"""
1111

12-
def saml_metadata(self, client_id):
13-
"""Get SAML2.0 Metadata.
14-
15-
Args:
16-
client_id (str): Client Id of the application to get the SAML metadata for.
17-
"""
12+
def saml_metadata(self):
13+
"""Get SAML2.0 Metadata."""
1814

1915
return self.get(
2016
url="{}://{}/samlp/metadata/{}".format(
21-
self.protocol, self.domain, client_id
17+
self.protocol, self.domain, self.client_id
2218
)
2319
)
2420

0 commit comments

Comments
 (0)