Example #1
0
def saml_auth():
    """
    SAML Authentication Endpoint. Authenticate user through SAML.
    If error, set message in session so that frontend can get the message through /session call
    """
    if not current_app.config.get('SAML_LOGIN_ENABLED'):
        abort(
            403,
            title="Not Logged In",
            message=
            "Please use a valid way to log in. You are not able to use CWL login based on the current settings."
        )

    url = "/app/#/lti" if sess.get('LTI') else "/"
    error_message = None
    auth = get_saml_auth_response(request)
    errors = auth.get_errors()

    if len(errors) > 0:
        current_app.logger.debug("SAML IdP returned errors: %s" % (errors))
        error_message = "Login Failed."
    elif not auth.is_authenticated():
        current_app.logger.debug("SAML IdP not logged in")
        error_message = "Login Failed."
    else:
        attributes = auth.get_attributes()
        unique_identifier = attributes.get(
            current_app.config.get('SAML_UNIQUE_IDENTIFIER'))
        current_app.logger.debug("SAML IdP responded with attributes:%s" %
                                 (attributes))

        if not unique_identifier or (isinstance(unique_identifier, list)
                                     and len(unique_identifier) == 0):
            current_app.logger.error(
                "SAML idP did not return the unique_identifier " +
                current_app.config.get('SAML_UNIQUE_IDENTIFIER') +
                " within its attributes")
            error_message = "Login Failed. Expecting " + current_app.config.get(
                'SAML_UNIQUE_IDENTIFIER') + " to be set."
        else:
            # set unique_identifier to first item in list if unique_identifier is an array
            if isinstance(unique_identifier, list):
                unique_identifier = unique_identifier[0]

            thirdpartyuser = ThirdPartyUser.query. \
                filter_by(
                    unique_identifier=unique_identifier,
                    third_party_type=ThirdPartyType.saml
                ) \
                .one_or_none()

            sess['SAML_NAME_ID'] = auth.get_nameid()
            sess['SAML_SESSION_INDEX'] = auth.get_session_index()

            if not thirdpartyuser:
                thirdpartyuser = ThirdPartyUser(
                    unique_identifier=unique_identifier,
                    third_party_type=ThirdPartyType.saml,
                    params=attributes)
                thirdpartyuser.generate_or_link_user_account()
                db.session.add(thirdpartyuser)
                db.session.commit()
            elif not thirdpartyuser.user:
                thirdpartyuser.generate_or_link_user_account()
                db.session.commit()

            authenticate(thirdpartyuser.user,
                         login_method=thirdpartyuser.third_party_type.value)
            thirdpartyuser.params = attributes

            if sess.get('LTI') and sess.get('lti_create_user_link'):
                lti_user = LTIUser.query.get_or_404(sess['lti_user'])
                lti_user.compair_user_id = thirdpartyuser.user_id
                lti_user.upgrade_system_role()
                lti_user.update_user_profile()
                sess.pop('lti_create_user_link')
            else:
                thirdpartyuser.upgrade_system_role()
                thirdpartyuser.update_user_profile()

            if sess.get('LTI') and sess.get('lti_context') and sess.get(
                    'lti_user_resource_link'):
                lti_context = LTIContext.query.get_or_404(sess['lti_context'])
                lti_user_resource_link = LTIUserResourceLink.query.get_or_404(
                    sess['lti_user_resource_link'])
                lti_context.update_enrolment(
                    thirdpartyuser.user_id, lti_user_resource_link.course_role)

            db.session.commit()
            sess['SAML_LOGIN'] = True

    if error_message is not None:
        sess['THIRD_PARTY_AUTH_ERROR_TYPE'] = 'SAML'
        sess['THIRD_PARTY_AUTH_ERROR_MSG'] = error_message

    return redirect(url)
Example #2
0
def cas_auth():
    """
    CAS Authentication Endpoint. Authenticate user through CAS.
    If error, set message in session so that frontend can get the message through /session call
    """
    if not current_app.config.get('CAS_LOGIN_ENABLED'):
        abort(
            403,
            title="Log In Failed",
            message=
            "Please try an alternate way of logging in. The CWL login has been disabled by your system administrator."
        )

    url = "/app/#/lti" if sess.get('LTI') else "/"
    error_message = None
    ticket = request.args.get("ticket")

    # check if token isn't present
    if not ticket:
        error_message = "No token in request"
    else:
        validation_response = validate_cas_ticket(ticket)

        if not validation_response.success:
            current_app.logger.debug(
                "CAS Server did NOT validate ticket:%s and included this response:%s"
                % (ticket, validation_response.response))
            error_message = "Login Failed. CAS ticket was invalid."
        elif not validation_response.user:
            current_app.logger.debug(
                "CAS Server responded with valid ticket but no user")
            error_message = "Login Failed. Expecting CAS username to be set."
        else:
            current_app.logger.debug(
                "CAS Server responded with user:%s and attributes:%s" %
                (validation_response.user, validation_response.attributes))
            username = validation_response.user

            thirdpartyuser = ThirdPartyUser.query. \
                filter_by(
                    unique_identifier=username,
                    third_party_type=ThirdPartyType.cas
                ) \
                .one_or_none()

            if not thirdpartyuser:
                thirdpartyuser = ThirdPartyUser(
                    unique_identifier=username,
                    third_party_type=ThirdPartyType.cas,
                    params=validation_response.attributes)
                thirdpartyuser.generate_or_link_user_account()
                db.session.add(thirdpartyuser)
                db.session.commit()
            elif not thirdpartyuser.user:
                thirdpartyuser.generate_or_link_user_account()
                db.session.commit()

            authenticate(thirdpartyuser.user,
                         login_method=thirdpartyuser.third_party_type.value)
            thirdpartyuser.params = validation_response.attributes

            if sess.get('LTI') and sess.get('lti_create_user_link'):
                lti_user = LTIUser.query.get_or_404(sess['lti_user'])
                lti_user.compair_user_id = thirdpartyuser.user_id
                lti_user.upgrade_system_role()
                lti_user.update_user_profile()
                sess.pop('lti_create_user_link')
            else:
                thirdpartyuser.upgrade_system_role()
                thirdpartyuser.update_user_profile()

            if sess.get('LTI') and sess.get('lti_context') and sess.get(
                    'lti_user_resource_link'):
                lti_context = LTIContext.query.get_or_404(sess['lti_context'])
                lti_user_resource_link = LTIUserResourceLink.query.get_or_404(
                    sess['lti_user_resource_link'])
                lti_context.update_enrolment(
                    thirdpartyuser.user_id, lti_user_resource_link.course_role)

            db.session.commit()
            sess['CAS_LOGIN'] = True

    if error_message is not None:
        sess['THIRD_PARTY_AUTH_ERROR_TYPE'] = 'CAS'
        sess['THIRD_PARTY_AUTH_ERROR_MSG'] = error_message

    return redirect(url)