Source code for khoros.saml
# -*- coding: utf-8 -*-
"""
:Module: khoros.objects.saml
:Synopsis: This module includes functions that relate to SAML SSO.
:Usage: ``from khoros import saml``
:Example: ``assertion = saml.import_assertion(file_path)``
:Created By: Jeff Shurtliff
:Last Modified: Jeff Shurtliff
:Modified Date: 23 May 2022
"""
from . import api, errors
from .utils import log_utils, core_utils
# Initialize the logger for this module
logger = log_utils.initialize_logging(__name__)
[docs]
def send_assertion(khoros_object, assertion=None, file_path=None, base64_encode=True, url_encode=True):
"""This function sends a SAML assertion as a POST request in order to provision a new user.
.. versionadded:: 4.3.0
:param khoros_object: The core :py:class:`khoros.Khoros` object
:type khoros_object: class[khoros.Khoros]
:param assertion: The SAML assertion in string format and optionally base64- and/or URL-encoded
:type assertion: str, None
:param file_path: The file path to the XML file to import that contains the SAML assertion
:type file_path: str, None
:param base64_encode: Determines if the assertion should be base64-encoded (``True`` by default)
:type base64_encode: bool
:param url_encode: Determines if the assertion should be URL-encoded (``True`` by default)
:type url_encode: bool
:returns: The API response from the POST request
:raises: :py:exc:`khoros.errors.exceptions.MissingRequiredDataError`
"""
if not any((assertion, file_path)):
error_msg = "A SAML assertion string or file path must be provided"
raise errors.exceptions.MissingRequiredDataError(error_msg)
if assertion:
if _is_decoded(assertion) and base64_encode:
assertion = core_utils.encode_base64(assertion, url_encode_object=url_encode)
elif not _is_decoded(assertion) and '=' in assertion and url_encode:
assertion = core_utils.url_encode(assertion)
else:
assertion = import_assertion(file_path, base64_encode, url_encode)
uri = _get_api_uri(khoros_object)
response = api.post_request_with_retries(uri, url_encoded_payload=assertion, return_json=False,
khoros_object=khoros_object)
return response
[docs]
def import_assertion(file_path, base64_encode=True, url_encode=True):
"""This function imports an XML SAML assertion as a string and optionally base64- and/or URL-encodes it.
.. versionadded:: 4.3.0
:param file_path: The file path to the XML file to import
:type file_path: str
:param base64_encode: Determines if the assertion should be base64-encoded (``True`` by default)
:type base64_encode: bool
:param url_encode: Determines if the assertion should be URL-encoded (``True`` by default)
:type url_encode: bool
:returns: The SAML assertion string
:raises: :py:exc:`FileNotFoundError`
"""
with open(file_path, 'r') as file:
assertion = file.read()
if base64_encode:
assertion = core_utils.encode_base64(assertion)
if url_encode:
assertion = core_utils.url_encode(assertion)
return assertion
def _is_decoded(_assertion):
"""This function checks to see if a SAML assertion is base64- or url-encoded.
.. versionadded:: 4.3.0
:param _assertion: The SAML assertion string to be examined
:type _assertion: str
:returns: Boolean value indicating whether the SAML assertion string is encoded
:raises: :py:exc:`TypeError`
"""
return True if '<saml' in _assertion else False
def _get_api_uri(_khoros_object):
"""This function retrieves the API URI to call in the POST request.
.. versionadded:: 4.3.0
:param _khoros_object: The core :py:class:`khoros.Khoros` object
:type _khoros_object: class[khoros.Khoros]
:returns: The absolute URI to be used in the POST request
"""
_base_url = _khoros_object.core.get('base_url')
_base_url = _base_url[:-1] if _base_url.endswith('/') else _base_url
return _base_url + '/auth/saml/login?SAMLResponse'