1
1
import os
2
2
import uuid
3
+ from datetime import datetime , timezone
4
+ from typing import Optional
3
5
from xml .dom import minidom
4
6
from xml .etree import ElementTree
5
7
6
8
import requests
7
9
import requests .utils
8
10
9
11
import office365 .logger
12
+ from office365 .runtime .auth .auth_cookies import AuthCookies
10
13
from office365 .runtime .auth .authentication_provider import AuthenticationProvider
11
14
from office365 .runtime .auth .sts_profile import STSProfile
12
15
from office365 .runtime .auth .user_realm_info import UserRealmInfo
@@ -20,23 +23,17 @@ def resolve_base_url(url):
20
23
return parts [0 ] + "://" + host_name
21
24
22
25
23
- def xml_escape ( s_val ):
24
- s_val = s_val .replace ("&" , "&" )
25
- s_val = s_val .replace ("<" , "<" )
26
- s_val = s_val .replace (">" , ">" )
27
- s_val = s_val .replace ('"' , """ )
28
- s_val = s_val .replace ("'" , "'" )
29
- return s_val
26
+ def string_escape ( value ):
27
+ value = value .replace ("&" , "&" )
28
+ value = value .replace ("<" , "<" )
29
+ value = value .replace (">" , ">" )
30
+ value = value .replace ('"' , """ )
31
+ value = value .replace ("'" , "'" )
32
+ return value
30
33
31
34
32
- def is_valid_auth_cookies (values ):
33
- """
34
- Validates authorization cookies
35
- """
36
- return any (values ) and (
37
- values .get ("FedAuth" , None ) is not None
38
- or values .get ("SPOIDCRL" , None ) is not None
39
- )
35
+ def datetime_escape (value ):
36
+ return value .isoformat ("T" )[:- 9 ] + "Z"
40
37
41
38
42
39
class SamlTokenProvider (AuthenticationProvider , office365 .logger .LoggerContext ):
@@ -60,7 +57,7 @@ def __init__(self, url, username, password, browser_mode, environment="commercia
60
57
self .error = ""
61
58
self ._username = username
62
59
self ._password = password
63
- self ._cached_auth_cookies = None
60
+ self ._cached_auth_cookies = None # type: Optional[AuthCookies]
64
61
self .__ns_prefixes = {
65
62
"S" : "{http://www.w3.org/2003/05/soap-envelope}" ,
66
63
"s" : "{http://www.w3.org/2003/05/soap-envelope}" ,
@@ -82,24 +79,20 @@ def authenticate_request(self, request):
82
79
Authenticate request handler
83
80
"""
84
81
logger = self .logger (self .authenticate_request .__name__ )
85
- self .ensure_authentication_cookie ()
86
- logger .debug_secrets (self ._cached_auth_cookies )
87
- cookie_header_value = "; " .join (
88
- [
89
- "=" .join ([key , str (val )])
90
- for key , val in self ._cached_auth_cookies .items ()
91
- ]
92
- )
93
- request .set_header ("Cookie" , cookie_header_value )
94
82
95
- def ensure_authentication_cookie (self ):
96
- if self ._cached_auth_cookies is None :
83
+ request_time = datetime .now (timezone .utc )
84
+ if (
85
+ self ._cached_auth_cookies is None
86
+ or request_time >= self ._sts_profile .expires
87
+ ):
88
+ self ._sts_profile .reset ()
97
89
self ._cached_auth_cookies = self .get_authentication_cookie ()
98
- return True
90
+ logger .debug_secrets (self ._cached_auth_cookies )
91
+ request .set_header ("Cookie" , self ._cached_auth_cookies .cookie_header )
99
92
100
93
def get_authentication_cookie (self ):
101
94
"""Acquire authentication cookie"""
102
- logger = self .logger (self .ensure_authentication_cookie .__name__ )
95
+ logger = self .logger (self .get_authentication_cookie .__name__ )
103
96
logger .debug ("get_authentication_cookie called" )
104
97
105
98
try :
@@ -140,10 +133,10 @@ def _acquire_service_token_from_adfs(self, adfs_url):
140
133
{
141
134
"auth_url" : adfs_url ,
142
135
"message_id" : str (uuid .uuid4 ()),
143
- "username" : xml_escape (self ._username ),
144
- "password" : xml_escape (self ._password ),
145
- "created" : self ._sts_profile .created ,
146
- "expires" : self ._sts_profile .expires ,
136
+ "username" : string_escape (self ._username ),
137
+ "password" : string_escape (self ._password ),
138
+ "created" : datetime_escape ( self ._sts_profile .created ) ,
139
+ "expires" : datetime_escape ( self ._sts_profile .expires ) ,
147
140
"issuer" : self ._sts_profile .tokenIssuer ,
148
141
},
149
142
)
@@ -192,11 +185,11 @@ def _acquire_service_token(self):
192
185
"SAML.xml" ,
193
186
{
194
187
"auth_url" : self ._sts_profile .authorityUrl ,
195
- "username" : xml_escape (self ._username ),
196
- "password" : xml_escape (self ._password ),
188
+ "username" : string_escape (self ._username ),
189
+ "password" : string_escape (self ._password ),
197
190
"message_id" : str (uuid .uuid4 ()),
198
- "created" : self ._sts_profile .created ,
199
- "expires" : self ._sts_profile .expires ,
191
+ "created" : datetime_escape ( self ._sts_profile .created ) ,
192
+ "expires" : datetime_escape ( self ._sts_profile .expires ) ,
200
193
"issuer" : self ._sts_profile .tokenIssuer ,
201
194
},
202
195
)
@@ -297,9 +290,9 @@ def _get_authentication_cookie(self, security_token, federated=False):
297
290
},
298
291
)
299
292
logger .debug_secrets ("session.cookies: %s" , session .cookies )
300
- cookies = requests .utils .dict_from_cookiejar (session .cookies )
293
+ cookies = AuthCookies ( requests .utils .dict_from_cookiejar (session .cookies ) )
301
294
logger .debug_secrets ("cookies: %s" , cookies )
302
- if not is_valid_auth_cookies ( cookies ) :
295
+ if not cookies . is_valid :
303
296
self .error = (
304
297
"An error occurred while retrieving auth cookies from {0}" .format (
305
298
self ._sts_profile .signin_page_url
0 commit comments