11import os
22import uuid
3+ from datetime import datetime , timezone
4+ from typing import Optional
35from xml .dom import minidom
46from xml .etree import ElementTree
57
68import requests
79import requests .utils
810
911import office365 .logger
12+ from office365 .runtime .auth .auth_cookies import AuthCookies
1013from office365 .runtime .auth .authentication_provider import AuthenticationProvider
1114from office365 .runtime .auth .sts_profile import STSProfile
1215from office365 .runtime .auth .user_realm_info import UserRealmInfo
@@ -20,23 +23,17 @@ def resolve_base_url(url):
2023 return parts [0 ] + "://" + host_name
2124
2225
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
3033
3134
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"
4037
4138
4239class SamlTokenProvider (AuthenticationProvider , office365 .logger .LoggerContext ):
@@ -60,7 +57,7 @@ def __init__(self, url, username, password, browser_mode, environment="commercia
6057 self .error = ""
6158 self ._username = username
6259 self ._password = password
63- self ._cached_auth_cookies = None
60+ self ._cached_auth_cookies = None # type: Optional[AuthCookies]
6461 self .__ns_prefixes = {
6562 "S" : "{http://www.w3.org/2003/05/soap-envelope}" ,
6663 "s" : "{http://www.w3.org/2003/05/soap-envelope}" ,
@@ -82,24 +79,20 @@ def authenticate_request(self, request):
8279 Authenticate request handler
8380 """
8481 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 )
9482
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 ()
9789 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 )
9992
10093 def get_authentication_cookie (self ):
10194 """Acquire authentication cookie"""
102- logger = self .logger (self .ensure_authentication_cookie .__name__ )
95+ logger = self .logger (self .get_authentication_cookie .__name__ )
10396 logger .debug ("get_authentication_cookie called" )
10497
10598 try :
@@ -140,10 +133,10 @@ def _acquire_service_token_from_adfs(self, adfs_url):
140133 {
141134 "auth_url" : adfs_url ,
142135 "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 ) ,
147140 "issuer" : self ._sts_profile .tokenIssuer ,
148141 },
149142 )
@@ -192,11 +185,11 @@ def _acquire_service_token(self):
192185 "SAML.xml" ,
193186 {
194187 "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 ),
197190 "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 ) ,
200193 "issuer" : self ._sts_profile .tokenIssuer ,
201194 },
202195 )
@@ -297,9 +290,9 @@ def _get_authentication_cookie(self, security_token, federated=False):
297290 },
298291 )
299292 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 ) )
301294 logger .debug_secrets ("cookies: %s" , cookies )
302- if not is_valid_auth_cookies ( cookies ) :
295+ if not cookies . is_valid :
303296 self .error = (
304297 "An error occurred while retrieving auth cookies from {0}" .format (
305298 self ._sts_profile .signin_page_url
0 commit comments