This repository was archived by the owner on Jul 29, 2024. It is now read-only.
forked from jupyterhub/oauthenticator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathazuread.py
103 lines (78 loc) · 2.84 KB
/
azuread.py
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
"""
Custom Authenticator to use Azure AD with JupyterHub
"""
import os
import urllib
from distutils.version import LooseVersion as V
import jwt
from jupyterhub.auth import LocalAuthenticator
from tornado.httpclient import HTTPRequest
from traitlets import default
from traitlets import Unicode
from .oauth2 import OAuthenticator
# pyjwt 2.0 has changed its signature,
# but mwoauth pins to pyjwt 1.x
PYJWT_2 = V(jwt.__version__) >= V("2.0")
class AzureAdOAuthenticator(OAuthenticator):
login_service = Unicode(
os.environ.get('LOGIN_SERVICE', 'Azure AD'),
config=True,
help="""Azure AD domain name string, e.g. My College""",
)
tenant_id = Unicode(config=True, help="The Azure Active Directory Tenant ID")
@default('tenant_id')
def _tenant_id_default(self):
return os.environ.get('AAD_TENANT_ID', '')
username_claim = Unicode(config=True)
@default('username_claim')
def _username_claim_default(self):
return 'name'
@default("authorize_url")
def _authorize_url_default(self):
return 'https://login.microsoftonline.com/{0}/oauth2/authorize'.format(
self.tenant_id
)
@default("token_url")
def _token_url_default(self):
return 'https://login.microsoftonline.com/{0}/oauth2/token'.format(
self.tenant_id
)
async def authenticate(self, handler, data=None):
code = handler.get_argument("code")
params = dict(
client_id=self.client_id,
client_secret=self.client_secret,
grant_type='authorization_code',
code=code,
redirect_uri=self.get_callback_url(handler),
)
data = urllib.parse.urlencode(params, doseq=True, encoding='utf-8', safe='=')
url = self.token_url
headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
req = HTTPRequest(
url,
method="POST",
headers=headers,
body=data, # Body is required for a POST...
)
resp_json = await self.fetch(req)
access_token = resp_json['access_token']
id_token = resp_json['id_token']
if PYJWT_2:
decoded = jwt.decode(
id_token,
options={"verify_signature": False},
audience=self.client_id,
)
else:
# pyjwt 1.x
decoded = jwt.decode(id_token, verify=False)
userdict = {"name": decoded[self.username_claim]}
userdict["auth_state"] = auth_state = {}
auth_state['access_token'] = access_token
# results in a decoded JWT for the user data
auth_state['user'] = decoded
return userdict
class LocalAzureAdOAuthenticator(LocalAuthenticator, AzureAdOAuthenticator):
"""A version that mixes in local system user creation"""
pass