1
1
import json
2
+ import msal
2
3
import time
3
4
import pprint
4
5
import urllib
12
13
from typing import Union
13
14
14
15
from ms_graph .users import Users
16
+ from ms_graph .drives import Drives
17
+ from ms_graph .groups import Groups
15
18
from ms_graph .session import GraphSession
16
19
17
20
from urllib .parse import urlencode , urlparse , quote_plus
@@ -72,12 +75,20 @@ def __init__(self, client_id: str, client_secret: str, redirect_uri: str, scope:
72
75
self .access_token = None
73
76
self .refresh_token = None
74
77
self .graph_session = None
78
+ self .id_token = None
75
79
76
80
self .base_url = self .RESOURCE + self .api_version + '/'
77
81
self .office_url = self .OFFICE365_AUTHORITY_URL + self .OFFICE365_AUTH_ENDPOINT
78
82
self .graph_url = self .AUTHORITY_URL + self .account_type + self .AUTH_ENDPOINT
79
83
self .office365 = office365
80
84
85
+ # Initialize the Credential App.
86
+ self .client_app = msal .ConfidentialClientApplication (
87
+ client_id = self .client_id ,
88
+ authority = self .AUTHORITY_URL + self .account_type ,
89
+ client_credential = self .client_secret
90
+ )
91
+
81
92
def _state (self , action : str , token_dict : dict = None ) -> bool :
82
93
"""Sets the session state for the Client Library.
83
94
@@ -113,6 +124,7 @@ def _state(self, action: str, token_dict: dict = None) -> bool:
113
124
114
125
self .refresh_token = credentials ['refresh_token' ]
115
126
self .access_token = credentials ['access_token' ]
127
+ self .id_token = credentials ['id_token' ]
116
128
self .token_dict = credentials
117
129
118
130
return True
@@ -126,6 +138,9 @@ def _state(self, action: str, token_dict: dict = None) -> bool:
126
138
token_dict ['expires_in' ] = time .time () + int (token_dict ['expires_in' ])
127
139
token_dict ['ext_expires_in' ] = time .time () + int (token_dict ['ext_expires_in' ])
128
140
141
+ self .refresh_token = token_dict ['refresh_token' ]
142
+ self .access_token = token_dict ['access_token' ]
143
+ self .id_token = token_dict ['id_token' ]
129
144
self .token_dict = token_dict
130
145
131
146
with open (file = self .credentials , mode = 'w+' ) as state_file :
@@ -195,16 +210,12 @@ def _silent_sso(self) -> bool:
195
210
-------
196
211
(bool)
197
212
`True` if it was successful and `False` if it failed.
198
- """
213
+ """
199
214
200
215
# if the current access token is not expired then we are still authenticated.
201
216
if self ._token_seconds (token_type = 'access_token' ) > 0 :
202
217
return True
203
218
204
- # if the refresh token is expired then you have to do a full login.
205
- elif self ._token_seconds (token_type = 'refresh_token' ) <= 0 :
206
- return False
207
-
208
219
# if the current access token is expired then try and refresh access token.
209
220
elif self .refresh_token and self .grab_refresh_token ():
210
221
return True
@@ -213,7 +224,7 @@ def _silent_sso(self) -> bool:
213
224
return False
214
225
215
226
def login (self ) -> None :
216
- """Logs the user into the session."""
227
+ """Logs the user into the session."""
217
228
218
229
# Load the State.
219
230
self ._state (action = 'load' )
@@ -223,8 +234,9 @@ def login(self) -> None:
223
234
224
235
# Set the Session.
225
236
self .graph_session = GraphSession (client = self )
237
+
226
238
return True
227
-
239
+
228
240
else :
229
241
230
242
# Build the URL.
@@ -253,21 +265,14 @@ def authorization_url(self):
253
265
A string.
254
266
"""
255
267
256
- params = {
257
- 'client_id' : self .client_id ,
258
- 'redirect_uri' : self .redirect_uri ,
259
- 'scope' : ' ' .join (self .scope ),
260
- 'response_type' : 'code' ,
261
- 'response_mode' : 'query' ,
262
- 'state' : self .state
263
- }
264
-
265
- if self .office365 :
266
- response = self .office_url + urlencode (params ).replace ("+" ,"%20" )
267
- else :
268
- response = self .graph_url + urlencode (params ).replace ("+" ,"%20" )
268
+ # Build the Auth URL.
269
+ auth_url = self .client_app .get_authorization_request_url (
270
+ scopes = self .scope ,
271
+ state = self .state ,
272
+ redirect_uri = self .redirect_uri
273
+ )
269
274
270
- return response
275
+ return auth_url
271
276
272
277
def grab_access_token (self ) -> Dict :
273
278
"""Exchanges a code for an Access Token.
@@ -283,31 +288,12 @@ def grab_access_token(self) -> Dict:
283
288
# Grab the Code.
284
289
code = query_dict [self .redirect_uri + "?code" ]
285
290
286
- # Define the Arguments.
287
- data = {
288
- 'client_id' : self .client_id ,
289
- 'redirect_uri' : self .redirect_uri ,
290
- 'client_secret' : self .client_secret ,
291
- 'code' : code ,
292
- 'grant_type' : 'authorization_code' ,
293
- }
294
-
295
- # If we are doing a 365 request then change the endpoint.
296
- if self .office365 :
297
-
298
- response = requests .post (
299
- self .OFFICE365_AUTHORITY_URL + self .OFFICE365_TOKEN_ENDPOINT ,
300
- data = data
301
- )
302
-
303
- else :
304
-
305
- response = requests .post (
306
- self .AUTHORITY_URL + self .account_type + self .TOKEN_ENDPOINT ,
307
- data = data
308
- )
309
-
310
- token_dict = response .json ()
291
+ # Grab the Token.
292
+ token_dict = self .client_app .acquire_token_by_authorization_code (
293
+ code = code ,
294
+ scopes = self .scope ,
295
+ redirect_uri = self .redirect_uri
296
+ )
311
297
312
298
# Save the token dict.
313
299
self ._state (
@@ -326,30 +312,13 @@ def grab_refresh_token(self) -> Dict:
326
312
A token dictionary with a new access token.
327
313
"""
328
314
329
- data = {
330
- 'client_id' : self .client_id ,
331
- 'redirect_uri' : self .redirect_uri ,
332
- 'client_secret' : self .client_secret ,
333
- 'refresh_token' : self .refresh_token ,
334
- 'grant_type' : 'refresh_token' ,
335
- }
336
-
337
- if self .office365 :
338
-
339
- response = requests .post (
340
- self .OFFICE365_AUTHORITY_URL + self .OFFICE365_TOKEN_ENDPOINT ,
341
- data = data
342
- )
343
-
344
- else :
345
-
346
- response = requests .post (
347
- self .AUTHORITY_URL + self .account_type + self .TOKEN_ENDPOINT ,
348
- data = data
349
- )
350
-
351
- token_dict = response .json ()
315
+ # Grab a new token using our refresh token.
316
+ token_dict = self .client_app .acquire_token_by_refresh_token (
317
+ refresh_token = self .refresh_token ,
318
+ scopes = self .scope
319
+ )
352
320
321
+ # Save the Token.
353
322
self ._state (
354
323
action = 'save' ,
355
324
token_dict = token_dict
@@ -358,7 +327,43 @@ def grab_refresh_token(self) -> Dict:
358
327
return token_dict
359
328
360
329
def users (self ) -> Users :
330
+ """Used to access the User Services and metadata.
331
+
332
+ ### Returns
333
+ ---
334
+ Users:
335
+ The `Users` services Object.
336
+ """
337
+
338
+ # Grab the Users Object for the session.
339
+ users_object : Users = Users (session = self .graph_session )
340
+
341
+ return users_object
342
+
343
+ def drives (self ) -> Drives :
344
+ """Used to access the Drives Services and metadata.
345
+
346
+ ### Returns
347
+ ---
348
+ Drives:
349
+ The `Drives` services Object.
350
+ """
351
+
352
+ # Grab the Drives Object for the session.
353
+ drives_object : Drives = Drives (session = self .graph_session )
354
+
355
+ return drives_object
356
+
357
+ def groups (self ) -> Groups :
358
+ """Used to access the Groups Services and metadata.
359
+
360
+ ### Returns
361
+ ---
362
+ Groups:
363
+ The `Groups` services Object.
364
+ """
361
365
362
- user_object : Users = Users (session = self .graph_session )
366
+ # Grab the `Groups` Object for the session.
367
+ groups_object : Groups = Groups (session = self .graph_session )
363
368
364
- return user_object
369
+ return groups_object
0 commit comments