Пример #1
0
def process():
    saml_response = request.form['SAMLResponse']
    assertion_data = XMLVerifier().verify(base64.b64decode(saml_response),
                                          x509_cert=cert).signed_xml

    if assertion_data.find(
            '{urn:oasis:names:tc:SAML:2.0:assertion}LogoutRequest'
    ) is not None:
        response = make_response('You have been logged out')
        response.set_cookie('auth_session', '', expires=0)
        return response

    username = assertion_data.find('{urn:oasis:names:tc:SAML:2.0:assertion}Assertion')\
        .find('{urn:oasis:names:tc:SAML:2.0:assertion}Subject')\
        .find('{urn:oasis:names:tc:SAML:2.0:assertion}NameID').text
    key = 'secret'
    expiry = int(time.time()) + timeout
    signature = hashlib.sha256(
        f'{username}|{expiry}|{key}'.encode('UTF-8')).hexdigest()
    if 'RelayState' in request.form:
        return_path = request.form['RelayState']
        response = redirect(return_path, 302)
    else:
        response = redirect('/', 302)
    response.set_cookie('auth_session', f'{username}|{expiry}|{signature}')
    return response
Пример #2
0
def authenticate(input_xml, ca_pem_file):

    # Check signature and retrieve the XML that's guaranteed to be signed.
    signed_xml = XMLVerifier().verify(input_xml,
                                      require_x509=True,
                                      ca_pem_file=ca_pem_file).signed_xml

    # Respect expiry boundaries given in SAML.
    # Apparently the datetimes have 7 digits of microseconds when normally
    # they should be 6 when parsed. We'll leave them out by only using the
    # first 19 characters.
    conds_xml = signed_xml.find(
        './/{urn:oasis:names:tc:SAML:2.0:assertion}Conditions')
    time_limit_lower = datetime.strptime(conds_xml.attrib['NotBefore'][:19],
                                         '%Y-%m-%dT%H:%M:%S')
    time_limit_upper = datetime.strptime(conds_xml.attrib['NotOnOrAfter'][:19],
                                         '%Y-%m-%dT%H:%M:%S')
    now = datetime.now()
    if time_limit_lower > now or time_limit_upper < now:
        raise SamlException('Remote authentication expired')

    # Find the assertion ID for our records. This is not needed for
    # functionality's sake and is only kept for the hypothetical scenario
    # where a particular authentication needs to be matched with records on
    # the identity provider's side.
    assertion_id = signed_xml.find(
        './/{urn:oasis:names:tc:SAML:2.0:assertion}Assertion').attrib['ID']

    # Translate SAML attributes into a handy dictionary.
    attributes = {}
    for attribute in signed_xml.findall(
            './/{urn:oasis:names:tc:SAML:2.0:assertion}Attribute'):
        attributes[attribute.attrib['Name']] = attribute.find(
            './/{urn:oasis:names:tc:SAML:2.0:assertion}AttributeValue').text

    return assertion_id, attributes