Commit f371d2c2 authored by Grant's avatar Grant
Browse files

remove SAML login as lxml was causing multiple issues

parent 94c3b2dc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@ verify_ssl = true
name = "pypi"

[packages]
common-package = {editable = true, path = "./src", extras=["postgres"]}
common-package = {editable = true, path = "./src", extras=["postgres", "auth"]}

[dev-packages]
pytest = "*"
+135 −3
Original line number Diff line number Diff line
{
    "_meta": {
        "hash": {
            "sha256": "60a6ef5959e2629d74698e56684b1b0c2b112e18139d87434d9b2880fffa6e8c"
            "sha256": "922232563aac6a98fd205d2e8d58fe224641137d160bedd3c171f4d0f4b78b40"
        },
        "pipfile-spec": 6,
        "requires": {
@@ -16,6 +16,22 @@
        ]
    },
    "default": {
        "blinker": {
            "hashes": [
                "sha256:1779309f71bf239144b9399d06ae925637cf6634cf6bd131104184531bf67c01",
                "sha256:8f77b09d3bf7c795e969e9486f39c2c5e9c39d4ee07424be2bc594ece9642d83"
            ],
            "markers": "python_version >= '3.8'",
            "version": "==1.8.2"
        },
        "click": {
            "hashes": [
                "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
                "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"
            ],
            "markers": "python_version >= '3.7'",
            "version": "==8.1.7"
        },
        "colorama": {
            "hashes": [
                "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
@@ -27,6 +43,7 @@
        "common-package": {
            "editable": true,
            "extras": [
                "auth",
                "postgres"
            ],
            "path": "./src"
@@ -38,6 +55,105 @@
            ],
            "version": "==0.9.1"
        },
        "flask": {
            "hashes": [
                "sha256:34e815dfaa43340d1d15a5c3a02b8476004037eb4840b34910c6e21679d288f3",
                "sha256:ceb27b0af3823ea2737928a4d99d125a06175b8512c445cbd9a9ce200ef76842"
            ],
            "version": "==3.0.3"
        },
        "itsdangerous": {
            "hashes": [
                "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef",
                "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"
            ],
            "markers": "python_version >= '3.8'",
            "version": "==2.2.0"
        },
        "jinja2": {
            "hashes": [
                "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
                "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
            ],
            "markers": "python_version >= '3.7'",
            "version": "==3.1.4"
        },
        "ldap3": {
            "hashes": [
                "sha256:2bc966556fc4d4fa9f445a1c31dc484ee81d44a51ab0e2d0fd05b62cac75daa6",
                "sha256:5630d1383e09ba94839e253e013f1aa1a2cf7a547628ba1265cb7b9a844b5687",
                "sha256:5869596fc4948797020d3f03b7939da938778a0f9e2009f7a072ccf92b8e8d70",
                "sha256:5ab7febc00689181375de40c396dcad4f2659cd260fc5e94c508b6d77c17e9d5",
                "sha256:f3e7fc4718e3f09dda568b57100095e0ce58633bcabbed8667ce3f8fbaa4229f"
            ],
            "version": "==2.9.1"
        },
        "markupsafe": {
            "hashes": [
                "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf",
                "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff",
                "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f",
                "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3",
                "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532",
                "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f",
                "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617",
                "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df",
                "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4",
                "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906",
                "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f",
                "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4",
                "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8",
                "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371",
                "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2",
                "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465",
                "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52",
                "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6",
                "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169",
                "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad",
                "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2",
                "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0",
                "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029",
                "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f",
                "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a",
                "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced",
                "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5",
                "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c",
                "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf",
                "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9",
                "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb",
                "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad",
                "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3",
                "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1",
                "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46",
                "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc",
                "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a",
                "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee",
                "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900",
                "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5",
                "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea",
                "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f",
                "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5",
                "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e",
                "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a",
                "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f",
                "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50",
                "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a",
                "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b",
                "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4",
                "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff",
                "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2",
                "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46",
                "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b",
                "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf",
                "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5",
                "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5",
                "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab",
                "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd",
                "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"
            ],
            "markers": "python_version >= '3.7'",
            "version": "==2.1.5"
        },
        "numpy": {
            "hashes": [
                "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b",
@@ -188,6 +304,14 @@
            ],
            "version": "==2.9.9"
        },
        "pyasn1": {
            "hashes": [
                "sha256:3a35ab2c4b5ef98e17dfdec8ab074046fbda76e281c5a706ccd82328cfc8f64c",
                "sha256:cca4bb0f2df5504f02f6f8a775b6e416ff9b0b3b16f7ee80b5a3153d9b804473"
            ],
            "markers": "python_version >= '3.8'",
            "version": "==0.6.0"
        },
        "pygments": {
            "hashes": [
                "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
@@ -201,7 +325,7 @@
                "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
                "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"
            ],
            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
            "version": "==2.9.0.post0"
        },
        "pytz": {
@@ -224,7 +348,7 @@
                "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
                "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
            ],
            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'",
            "version": "==1.16.0"
        },
        "sqlalchemy": {
@@ -297,6 +421,14 @@
            ],
            "markers": "python_version >= '2'",
            "version": "==2024.1"
        },
        "werkzeug": {
            "hashes": [
                "sha256:097e5bfda9f0aba8da6b8545146def481d06aa7d3266e7448e2cccf67dd8bd18",
                "sha256:fc9645dc43e03e4d630d23143a04a7f947a9a3b5727cd535fdfe155a17cc48c8"
            ],
            "markers": "python_version >= '3.8'",
            "version": "==3.0.3"
        }
    },
    "develop": {
+0 −202
Original line number Diff line number Diff line
@@ -4,20 +4,14 @@ from urllib.parse import urlparse, urlencode
import hashlib
import os

from common.mail import send_email
from common.env import check_environment as ce
from common.database import Database

try:
    from onelogin.saml2.auth import OneLogin_Saml2_Auth
    from ldap3 import Server, Connection, ALL, SUBTREE
    from ldap3.core.exceptions import LDAPException, LDAPBindError
    from flask import jsonify

except ImportError:
    import sys
    from common.logz import create_logger

    log = create_logger()
    log.warn("To use this module, install common-package[auth] extra.")
    sys.exit(1)
@@ -66,75 +60,6 @@ def authenticate_ldap_user(uid, password):
    return connection.entries[0]


def authenticate_saml_user(
    request_scheme: str,
    request_host: str,
    request_url: str,
    request_method: str,
    request_args: dict,
    request_form: dict,
    success_handler: Callable = lambda _: None,
    failure_handler: Callable = lambda _: None,
    saml_path: str = None,
    logger=None,
):
    """
    Handles SAML authentication by processing the necessary components extracted from a web request.

    Parameters:
    - request_scheme (str): The request scheme ('http' or 'https').
    - request_host (str): The request host.
    - request_url (str): The full URL of the request.
    - request_method (str): The HTTP method of the request.
    - request_args (dict): The query parameters of the request as a dictionary.
    - request_form (dict): The form data of the request as a dictionary.
    - success_handler (Callable, optional): Function to handle successful SAML authentication.
      Defaults to a no-op function.
    - failure_handler (Callable, optional): Function to handle SAML authentication failure.
      Defaults to a no-op function.
    - saml_path (str, optional): Custom path for SAML configuration files. If not provided, environment variable
      'SAML_PATH' is used.
    - logger (Logger, optional): Logger object for logging. If not provided, no logging is performed.

    Returns:
    - Result of the `success_handler` or `failure_handler` callable depending on the SAML processing outcome.
    """
    url_data = urlparse(request_url)
    saml_request = {
        "https": "on" if request_scheme == "https" else "off",
        "http_host": request_host,
        "server_port": url_data.port,
        "script_name": url_data.path,
        "get_data": request_args,
        "post_data": request_form,
        "query_string": urlencode(request_args) if request_method == "GET" else "",
    }

    saml_path = saml_path or ce("SAML_PATH")
    auth = OneLogin_Saml2_Auth(saml_request, custom_base_path=saml_path)

    try:
        if "sso" in request_args:
            return success_handler(auth.login())
        elif "slo" in request_args:
            return success_handler(auth.logout())
        elif "acs" in request_args:
            auth.process_response(
                request_id=None
            )  # Assuming request carries all needed info
            if auth.is_authenticated():
                return success_handler(None)  # pass user details / attributes
            else:
                return failure_handler("SAML authentication failed")
        else:
            return failure_handler("No valid SAML action found")
    except Exception as e:
        error_msg = f"SAML authentication error: {str(e)}"
        if logger:
            logger.error(error_msg)
        return failure_handler(error_msg)


def generate_salt() -> str:
    return str(os.urandom(32)).replace("\\", "").replace("b", "")

@@ -147,130 +72,3 @@ def hash_password(
    **kwargs: Any,
) -> str:
    return hash_algorithm(password.encode(), salt.encode(), *args, **kwargs).hex()


def login(
    username: str,
    password: str,
    db: str,
    table_name: str,
    username_column: str,
    password_column: str,
    salt_column: str,
) -> dict:
    user_data = db.query(
        f"SELECT {password_column}, {salt_column} FROM {table_name} WHERE {username_column} = '{username}'"
    )
    if len(user_data) == 0:
        return {"msg": "Username does not exist."}, 401

    user_pass, salt = user_data[0]
    pass_to_check = hash_password(password, salt)

    if pass_to_check == user_pass:
        # User authentication successful
        return {"msg": "Login successful!"}
    else:
        return {"msg": "Invalid uid or password"}, 401


def check_username_exists(args, kwargs):
    return True


def register_user(
    username: str,
    password: str,
    confirm_pw: str,
    first_name: str,
    last_name: str,
    email: str,
    work_sector: str,
    user_type: str,
    reason: str,
    db: Database,
    table_name: str,
    username_column: str,
    password_column: str,
    salt_column: str,
) -> dict:
    # Check if username already exists
    if check_username_exists(username, db, table_name, username_column):
        return {"msg": "Username already exists."}, 401

    # Check if passwords match
    if password != confirm_pw:
        return {"msg": "Passwords do not match."}, 401

    # Generate salt and hash the password
    salt = generate_salt()
    hashed_pw = hash_password(password, salt)

    try:
        # Insert user data into the database
        db.cursor.execute(
            f"""INSERT INTO {table_name} ({username_column}, first_name, last_name, email, work_sector, 
                             user_type, {password_column}, {salt_column}, last_login_date, enabled) VALUES 
                             ('{username}', '{first_name}', '{last_name}', '{email}', '{work_sector}', 
                             '{user_type}', '{hashed_pw}', '{salt}', CURRENT_TIMESTAMP, false);"""
        )
        db.commit()
    except Exception as e:
        return {"msg": "Error registering new user account.", "error": str(e)}, 401

    # Send email notification
    os.environ["EMAIL_RECIPIENTS"] = "plattmw@ornl.gov, burdetteja@ornl.gov"
    os.environ["EMAIL_SENDER"] = "psplatial@ornl.gov"
    subject = "PS Platial Account Request"
    msg = f"{last_name}, {first_name} at {email} has requested a PlanetSense Platial account for the following reason: {reason}."
    send_email(subject, msg)

    return {
        "msg": "Thank you for submitting an account request. Our team will review your request and respond as soon as possible."
    }


def reset_password(
    username: str,
    token: str,
    new_password: str,
    confirm_new_password: str,
    db: Database,
    table_name: str,
    username_column: str,
    salt_column: str,
    password_column: str,
) -> dict:
    # Retrieve user's salt from the database
    user_salt = db.query(
        f"SELECT {salt_column} FROM {table_name} WHERE {username_column} = '{username}';"
    )
    if not user_salt:
        return {"msg": "Username not found."}, 401

    user_salt = str(user_salt[0][0]).replace("b", "")

    # Validate token
    token_to_match = db.query(
        f"SELECT email_reset_code FROM {table_name} WHERE {username_column} = '{username}';"
    )
    if token != token_to_match[0][0]:
        return {"msg": "Token does not match."}, 401

    # Check if passwords match
    if new_password != confirm_new_password:
        return {"msg": "Passwords do not match."}, 401

    # Generate new hashed password and update in the database
    new_hashed_pw = hash_password(new_password, user_salt)
    try:
        db.cursor.execute(
            f"UPDATE {table_name} SET {password_column} = '{new_hashed_pw}' WHERE {username_column} = '{username}';"
        )
        db.commit()
    except Exception as e:
        return {"msg": "Failed to update password.", "error": str(e)}, 401

    return {
        "msg": "Password updated successfully! Redirecting you back to login page now..."
    }
+1 −5
Original line number Diff line number Diff line
@@ -40,10 +40,6 @@ postgres = ["psycopg2-binary==2.9.9"]
mssql = ["pymssql==2.2.11"]
influx = ["influxdb==5.3.1"]
auth = [
    "lxml",
    "xmlsec==1.3.13",
    "onelogin==2.0.3",
    "python3_saml==1.14.0",
    "ldap3==2.9.1",
    "flask>=2.0.2"
]
@@ -80,5 +76,5 @@ Source = "https://code.ornl.gov/nset-utilities/common-package"


[tool.setuptools]
packages = ['common', 'common.mixins']
packages = ['common', 'common.mixins', 'common.scrapers']