def _get_authentication_cookie(self, security_token, federated=False): """Retrieve auth cookie from STS :type federated: bool :type security_token: str """ logger = self.logger(self._get_authentication_cookie.__name__) session = requests.session() logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session, self._sts_profile.signin_page_url, security_token) if not federated: session.post( self._sts_profile.signin_page_url, data=security_token, headers={'Content-Type': 'application/x-www-form-urlencoded'}) else: idcrl_endpoint = "https://{}/_vti_bin/idcrl.svc/".format( self._sts_profile.tenant) session.get(idcrl_endpoint, headers={ 'User-Agent': 'Office365 Python Client', 'X-IDCRL_ACCEPTED': 't', 'Authorization': 'BPOSIDCRL {0}'.format(security_token) }) logger.debug_secrets("session.cookies: %s", session.cookies) cookies = requests.utils.dict_from_cookiejar(session.cookies) logger.debug_secrets("cookies: %s", cookies) if not is_valid_auth_cookies(cookies): self.error = "An error occurred while retrieving auth cookies from {0}".format( self._sts_profile.signin_page_url) logger.error(self.error) raise ValueError(self.error) return cookies
def process_service_token_response(self, response): logger = self.logger(self.process_service_token_response.__name__) logger.debug_secrets('response: %s\nresponse.content: %s', response, response.content) xml = ElementTree.fromstring(response.content) ns_prefixes = { 'S': '{http://www.w3.org/2003/05/soap-envelope}', 'psf': '{http://schemas.microsoft.com/Passport/SoapServices/SOAPFault}', 'wst': '{http://schemas.xmlsoap.org/ws/2005/02/trust}', 'wsse': '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}' } logger.debug_secrets("ns_prefixes: %s", ns_prefixes) # check for errors if xml.find('{0}Body/{0}Fault'.format(ns_prefixes['S'])) is not None: error = xml.find( '{0}Body/{0}Fault/{0}Detail/{1}error/{1}internalerror/{1}text'. format(ns_prefixes['S'], ns_prefixes['psf'])) self.error = 'An error occurred while retrieving token: {0}'.format( error.text) logger.error(self.error) return None # extract token token = xml.find( '{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}BinarySecurityToken' .format(ns_prefixes['S'], ns_prefixes['wst'], ns_prefixes['wsse'])) logger.debug_secrets("token: %s", token) return token.text
def acquire_authentication_cookie(self, options): """Retrieve SPO auth cookie""" #logger = self.logger(self.acquire_authentication_cookie.__name__) logger.info("Executing acquire_authentication_cookie") # dwang_DEBUG # url = options['endpoint'] # url = options['msftlogin'] # session = requests.session() # logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session, url, self.token) # logger.info("session: %s\nsession.post(%s, data=%s)" % (session, url, self.token)) # session.post(url, data=self.token, headers={'Content-Type': 'application/x-www-form-urlencoded'}) # logger.debug_secrets("session.cookies: %s", session.cookies) # logger.info("session.cookies: %s" % session.cookies) # cookies = requests.utils.dict_from_cookiejar(session.cookies) # logger.debug_secrets("cookies: %s", cookies) response = self.cookieRequest.post( self.msftlogin, self.token, contentType='application/x-www-form-urlencoded') logger.info("After calling cookie request post") logger.info(str(response.getStatus())) # logger.info(str(response.getResponse())) # Unicode problems # dwang_DEBUG cookies = {} # logger.info("cookies: %s" % str(cookies)) if 'FedAuth' in cookies and 'rtFa' in cookies: self.FedAuth = cookies['FedAuth'] self.rtFa = cookies['rtFa'] return True self.error = "An error occurred while retrieving auth cookies" logger.error(self.error) return False
def acquire_service_token_from_adfs(self, adfs_url, username, password): logger = self.logger(self.acquire_service_token_from_adfs.__name__) payload = self._prepare_request_from_template( 'FederatedSAML.xml', { 'auth_url': adfs_url, 'username': username, 'password': password, 'message_id': str(uuid.uuid4()), 'created': self.__sts_profile.created, 'expires': self.__sts_profile.expires, 'issuer': self.__sts_profile.federationTokenIssuer }) response = requests.post( adfs_url, data=payload, headers={'Content-Type': 'application/soap+xml; charset=utf-8'}) try: xml = ElementTree.fromstring(response.content) # 1.find assertion assertion_node = xml.find( '{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}Assertion' .format(self.__ns_prefixes['s'], self.__ns_prefixes['wst'], self.__ns_prefixes['saml'])) if assertion_node is None: self.error = 'Cannot get security assertion for user {0} from {1}'.format( self.__username, adfs_url) logger.error(self.error) return None # 2. prepare & submit token request self.__sts_profile.signInPage = '_vti_bin/idcrl.svc' self.__sts_profile.securityTokenServicePath = 'rst2.srf' template = self._prepare_request_from_template( 'RST2.xml', { 'auth_url': self.__sts_profile.authorityUrl, 'serviceTokenUrl': self.__sts_profile.security_token_service_url }) template_xml = ElementTree.fromstring(template) security_node = template_xml.find('{0}Header/{1}Security'.format( self.__ns_prefixes['s'], self.__ns_prefixes['wsse'])) security_node.insert(1, assertion_node) payload = ElementTree.tostring(template_xml).decode() # 3. get token response = requests.post( self.__sts_profile.security_token_service_url, data=payload, headers={'Content-Type': 'application/soap+xml'}) token = self._process_service_token_response(response) logger.debug_secrets('security token: %s', token) return token except ElementTree.ParseError as e: self.error = 'An error occurred while parsing the server response: {}'.format( e) logger.error(self.error) return None
def acquire_service_token_from_adfs(self, adfs_url, username, password): logger = self.logger(self.acquire_service_token_from_adfs.__name__) now = datetime.now(tz=timezone.utc) created = now.astimezone(timezone.utc).isoformat('T')[:-9] + 'Z' expires = (now + timedelta(minutes=10)).astimezone( timezone.utc).isoformat('T')[:-9] + 'Z' payload = self._prepare_request_from_template( 'FederatedSAML.xml', { 'auth_url': adfs_url, 'message_id': str(uuid.uuid4()), 'username': username, 'password': password, 'created': created, 'expires': expires, 'issuer': self.__sts_profile.federationTokenIssuer }) response = requests.post( adfs_url, data=payload, headers={'Content-Type': 'application/soap+xml; charset=utf-8'}) dom = minidom.parseString(response.content.decode()) assertion_node = dom.getElementsByTagNameNS( "urn:oasis:names:tc:SAML:1.0:assertion", 'Assertion')[0].toxml() try: self.tenant = urlparse(self.__sts_profile.authorityUrl).netloc payload = self._prepare_request_from_template( 'RST2.xml', { 'auth_url': self.tenant, 'serviceTokenUrl': self.__sts_profile.security_token_service_url, 'assertion_node': assertion_node }) # 3. get token response = requests.post( self.__sts_profile.security_token_service_url, data=payload, headers={'Content-Type': 'application/soap+xml'}) token = self._process_service_token_response(response) logger.debug_secrets('security token: %s', token) return token except ElementTree.ParseError as e: self.error = 'An error occurred while parsing the server response: {}'.format( e) logger.error(self.error) return None
def _acquire_service_token_from_adfs(self, adfs_url): logger = self.logger(self._acquire_service_token_from_adfs.__name__) payload = self._prepare_request_from_template( 'FederatedSAML.xml', { 'auth_url': adfs_url, 'message_id': str(uuid.uuid4()), 'username': self._username, 'password': self._password, 'created': self._sts_profile.created, 'expires': self._sts_profile.expires, 'issuer': self._sts_profile.tokenIssuer }) response = requests.post( adfs_url, data=payload, headers={'Content-Type': 'application/soap+xml; charset=utf-8'}) dom = minidom.parseString(response.content.decode()) assertion_node = dom.getElementsByTagNameNS( "urn:oasis:names:tc:SAML:1.0:assertion", 'Assertion')[0].toxml() try: payload = self._prepare_request_from_template( 'RST2.xml', { 'auth_url': self._sts_profile.tenant, 'serviceTokenUrl': self._sts_profile.security_token_service_url, 'assertion_node': assertion_node }) # 3. get security token response = requests.post( self._sts_profile.security_token_service_url, data=payload, headers={'Content-Type': 'application/soap+xml'}) token = self._process_service_token_response(response) logger.debug_secrets('security token: %s', token) return token except ElementTree.ParseError as e: self.error = 'An error occurred while parsing the server response: {}'.format( e) logger.error(self.error) return None
def acquire_authentication_cookie(self, options): """Retrieve SPO auth cookie""" logger = self.logger(self.acquire_authentication_cookie.__name__) url = options['endpoint'] session = requests.session() logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session, url, self.token) session.post(url, data=self.token, headers={'Content-Type': 'application/x-www-form-urlencoded'}) logger.debug_secrets("session.cookies: %s", session.cookies) cookies = requests.utils.dict_from_cookiejar(session.cookies) logger.debug_secrets("cookies: %s", cookies) if 'FedAuth' in cookies and 'rtFa' in cookies: self.FedAuth = cookies['FedAuth'] self.rtFa = cookies['rtFa'] return True self.error = "An error occurred while retrieving auth cookies" logger.error(self.error) return False
def get_authentication_cookie(self): """Acquire authentication cookie """ logger = self.logger(self.ensure_authentication_cookie.__name__) logger.debug('get_authentication_cookie called') try: logger.debug("Acquiring Access Token..") user_realm = self._get_user_realm() if user_realm.IsFederated: token = self._acquire_service_token_from_adfs( user_realm.STSAuthUrl) else: token = self._acquire_service_token() return self._get_authentication_cookie(token, user_realm.IsFederated) except requests.exceptions.RequestException as e: logger.error(e.response.text) self.error = "Error: {}".format(e) raise ValueError(e.response.text)
def _acquire_authentication_cookie(self, security_token, federated=False): """Retrieve auth cookie from STS""" logger = self.logger(self._acquire_authentication_cookie.__name__) session = requests.session() logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session, self.__sts_profile.signin_page_url, security_token) if not federated: self._auth_cookies['FedAuth'] = None self._auth_cookies['rtFa'] = None session.post( self.__sts_profile.signin_page_url, data=security_token, headers={'Content-Type': 'application/x-www-form-urlencoded'}) else: self._auth_cookies['SPOIDCRL'] = None session.head(self.__sts_profile.signin_page_url, headers={ 'User-Agent': 'Office365 Python Client', 'X-IDCRL_ACCEPTED': 't', 'Authorization': 'BPOSIDCRL {0}'.format(security_token), 'Content-Type': 'application/x-www-form-urlencoded' }) logger.debug_secrets("session.cookies: %s", session.cookies) cookies = requests.utils.dict_from_cookiejar(session.cookies) logger.debug_secrets("cookies: %s", cookies) if not cookies: self.error = "An error occurred while retrieving auth cookies from {0}".format( self.__sts_profile.signin_page_url) logger.error(self.error) return False for name in self._auth_cookies.keys(): self._auth_cookies[name] = cookies[name] return True
def _process_service_token_response(self, response): logger = self.logger(self._process_service_token_response.__name__) logger.debug_secrets('response: %s\nresponse.content: %s', response, response.content) try: xml = ElementTree.fromstring(response.content) except ElementTree.ParseError as e: self.error = 'An error occurred while parsing the server response: {}'.format( e) logger.error(self.error) return None # check for errors if xml.find('{0}Body/{0}Fault'.format( self.__ns_prefixes['s'])) is not None: error = xml.find( '{0}Body/{0}Fault/{0}Detail/{1}error/{1}internalerror/{1}text'. format(self.__ns_prefixes['s'], self.__ns_prefixes['psf'])) if error is None: self.error = 'An error occurred while retrieving token from XML response.' else: self.error = 'An error occurred while retrieving token from XML response: {0}'.format( error.text) logger.error(self.error) return None # extract token token = xml.find( '{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}BinarySecurityToken' .format(self.__ns_prefixes['s'], self.__ns_prefixes['wst'], self.__ns_prefixes['wsse'])) if token is None: self.error = 'Cannot get binary security token for from {0}'.format( self.__sts_profile.security_token_service_url) logger.error(self.error) return None logger.debug_secrets("token: %s", token) return token.text