Beispiel #1
0
def login():
    """ Login page """
    user_manager = UserManager()
    session_token = request.cookies.get('session_token')

    # redirect_page = request.args.get('redirect', request.headers.get('Referer', '/'))
    redirect_page = request.args.get('redirect')
    if not redirect_page:
        redirect_page = request.headers.get('Referer', '/')
    if re.search('(^https?://[^/]+)?/login[^?#]?', redirect_page):
        # Prevent redirect loop
        redirect_page = '/'

    if session_token:
        user, session = user_manager.authenticate_user_session(session_token)
        if user:
            return redirect(redirect_page, 302)

    if request.form:
        username = request.form.get('username')
        password = request.form.get('password')
        remember = request.form.get('remember')
        expires = datetime.datetime.utcnow() + datetime.timedelta(days=365) \
            if remember else None

        session = user_manager.create_user_session(username=username, password=password,
                                                   expires_at=expires)

        if session:
            redirect_target = redirect(redirect_page, 302)
            response = make_response(redirect_target)
            response.set_cookie('session_token', session.session_token, expires=expires)
            return response

    return render_template('login.html', utils=HttpUtils)
Beispiel #2
0
def _authenticate_http():
    user_manager = UserManager()

    if not request.authorization:
        return False

    username = request.authorization.username
    password = request.authorization.password
    return user_manager.authenticate_user(username, password)
Beispiel #3
0
def auth_endpoint():
    """
    Authentication endpoint. It validates the user credentials provided over a JSON payload with the following
    structure:

        .. code-block:: json

            {
                "username": "******",
                "password": "******",
                "expiry_days": "The generated token should be valid for these many days"
            }

    ``expiry_days`` is optional, and if omitted or set to zero the token will be valid indefinitely.

    Upon successful validation, a new JWT token will be generated using the service's self-generated RSA key-pair and it
    will be returned to the user. The token can then be used to authenticate API calls to ``/execute`` by setting the
    ``Authorization: Bearer <TOKEN_HERE>`` header upon HTTP calls.

    :return: Return structure:

        .. code-block:: json

            {
                "token": "<generated token here>"
            }
    """
    try:
        payload = json.loads(request.get_data(as_text=True))
        username, password = payload['username'], payload['password']
    except Exception as e:
        log.warning('Invalid payload passed to the auth endpoint: ' + str(e))
        abort(400)
        return jsonify({'token': None})

    expiry_days = payload.get('expiry_days')
    expires_at = None
    if expiry_days:
        expires_at = datetime.datetime.now() + datetime.timedelta(
            days=expiry_days)

    user_manager = UserManager()

    try:
        return jsonify({
            'token':
            user_manager.generate_jwt_token(username=username,
                                            password=password,
                                            expires_at=expires_at),
        })
    except UserException as e:
        abort(401, str(e))
        return jsonify({'token': None})
Beispiel #4
0
        def wrapper(*args, **kwargs):
            user_manager = UserManager()
            n_users = user_manager.get_user_count()
            skip_methods = skip_auth_methods or []

            # User/pass HTTP authentication
            http_auth_ok = True
            if n_users > 0 and 'http' not in skip_methods:
                http_auth_ok = _authenticate_http()
                if http_auth_ok:
                    return f(*args, **kwargs)

            # Token-based authentication
            token_auth_ok = True
            if 'token' not in skip_methods:
                token_auth_ok = _authenticate_token()
                if token_auth_ok:
                    return f(*args, **kwargs)

            # Session token based authentication
            session_auth_ok = True
            if n_users > 0 and 'session' not in skip_methods:
                session_auth_ok = _authenticate_session()
                if session_auth_ok:
                    return f(*args, **kwargs)

                return redirect(
                    '/login?redirect=' + (redirect_page or request.url), 307)

            # CSRF token check
            if check_csrf_token:
                csrf_check_ok = _authenticate_csrf_token()
                if not csrf_check_ok:
                    return abort(403, 'Invalid or missing csrf_token')

            if n_users == 0 and 'session' not in skip_methods:
                return redirect(
                    '/register?redirect=' + (redirect_page or request.url),
                    307)

            if ('http' not in skip_methods and http_auth_ok) or \
                    ('token' not in skip_methods and token_auth_ok) or \
                    ('session' not in skip_methods and session_auth_ok):
                return f(*args, **kwargs)

            return Response(
                'Authentication required', 401,
                {'WWW-Authenticate': 'Basic realm="Login required"'})
Beispiel #5
0
def _authenticate_session():
    user_manager = UserManager()
    user_session_token = None
    user = None

    if 'X-Session-Token' in request.headers:
        user_session_token = request.headers['X-Session-Token']
    elif 'session_token' in request.args:
        user_session_token = request.args.get('session_token')
    elif 'session_token' in request.cookies:
        user_session_token = request.cookies.get('session_token')

    if user_session_token:
        user, session = user_manager.authenticate_user_session(
            user_session_token)

    return user is not None
Beispiel #6
0
def register():
    """ Registration page """
    user_manager = UserManager()
    redirect_page = request.args.get('redirect', '/')
    session_token = request.cookies.get('session_token')

    if session_token:
        user, session = user_manager.authenticate_user_session(session_token)
        if user:
            return redirect(redirect_page, 302)

    if request.form:
        username = request.form.get('username')
        password = request.form.get('password')
        confirm_password = request.form.get('confirm_password')
        remember = request.form.get('remember')

        if password == confirm_password:
            user_manager.create_user(username=username, password=password)
            session = user_manager.create_user_session(
                username=username,
                password=password,
                expires_at=datetime.datetime.utcnow() +
                datetime.timedelta(days=1) if not remember else None)

            if session:
                redirect_target = redirect(redirect_page, 302)
                response = make_response(redirect_target)
                response.set_cookie('session_token', session.session_token)
                return response

    if user_manager.get_user_count() > 0:
        return redirect('/login?redirect=' + redirect_page, 302)

    return render_template('register.html', utils=HttpUtils)
Beispiel #7
0
def logout():
    """ Logout page """
    user_manager = UserManager()
    redirect_page = request.args.get('redirect',
                                     request.headers.get('Referer', '/login'))
    session_token = request.cookies.get('session_token')

    if not session_token:
        return abort(417, 'Not logged in')

    user, session = user_manager.authenticate_user_session(session_token)
    if not user:
        return abort(403, 'Invalid session token')

    redirect_target = redirect(redirect_page, 302)
    response = make_response(redirect_target)
    response.set_cookie('session_token', '', expires=0)
    return response
Beispiel #8
0
def _authenticate_token():
    token = Config.get('token')
    user_manager = UserManager()

    if 'X-Token' in request.headers:
        user_token = request.headers['X-Token']
    elif 'Authorization' in request.headers and request.headers[
            'Authorization'].startswith('Bearer '):
        user_token = request.headers['Authorization'][len('Bearer '):]
    elif 'token' in request.args:
        user_token = request.args.get('token')
    else:
        return False

    try:
        user_manager.validate_jwt_token(user_token)
        return True
    except Exception as e:
        logger().debug(str(e))
        return token and user_token == token
Beispiel #9
0
def _authenticate_csrf_token():
    user_manager = UserManager()
    user_session_token = None

    if 'X-Session-Token' in request.headers:
        user_session_token = request.headers['X-Session-Token']
    elif 'session_token' in request.args:
        user_session_token = request.args.get('session_token')
    elif 'session_token' in request.cookies:
        user_session_token = request.cookies.get('session_token')

    if user_session_token:
        user, session = user_manager.authenticate_user_session(
            user_session_token)
    else:
        return False

    if user is None:
        return False

    return session.csrf_token is None or request.form.get(
        'csrf_token') == session.csrf_token
Beispiel #10
0
def register():
    """ Registration page """
    user_manager = UserManager()
    redirect_page = request.args.get('redirect')
    if not redirect_page:
        redirect_page = request.headers.get('Referer', '/')
    if re.search('(^https?://[^/]+)?/register[^?#]?', redirect_page):
        # Prevent redirect loop
        redirect_page = '/'

    session_token = request.cookies.get('session_token')

    if session_token:
        user, session = user_manager.authenticate_user_session(session_token)
        if user:
            return redirect(redirect_page, 302)  # lgtm [py/url-redirection]

    if user_manager.get_user_count() > 0:
        return redirect('/login?redirect=' + redirect_page,
                        302)  # lgtm [py/url-redirection]

    if request.form:
        username = request.form.get('username')
        password = request.form.get('password')
        confirm_password = request.form.get('confirm_password')
        remember = request.form.get('remember')

        if password == confirm_password:
            user_manager.create_user(username=username, password=password)
            session = user_manager.create_user_session(
                username=username,
                password=password,
                expires_at=datetime.datetime.utcnow() +
                datetime.timedelta(days=1) if not remember else None)

            if session:
                redirect_target = redirect(redirect_page,
                                           302)  # lgtm [py/url-redirection]
                response = make_response(redirect_target)
                response.set_cookie('session_token', session.session_token)
                return response
        else:
            abort(400, 'Password mismatch')

    return render_template('index.html', utils=HttpUtils)
Beispiel #11
0
def settings():
    """ Settings page """
    user_manager = UserManager()
    users = user_manager.get_users()
    return render_template('settings/index.html', utils=HttpUtils, users=users, token=Config.get('token'))
Beispiel #12
0
class UserPlugin(Plugin):
    """
    Plugin to programmatically create and manage users and user sessions
    """

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.user_manager = UserManager()

    @action
    def create_user(self, username, password, executing_user=None, executing_user_password=None, session_token=None,
                    **kwargs):
        """
        Create a user. This action needs to be executed by an already existing user, who needs to authenticate with
            their own credentials, unless this is the first user created on the system.

        :return: dict.

        Format::

            {
                "user_id": int,
                "username": str,
                "created_at": str (in ISO format)
            }

        """

        if self.user_manager.get_user_count() > 0 and not executing_user and not session_token:
            return None, "You need to authenticate in order to create another user"

        if not self.user_manager.authenticate_user(executing_user, executing_user_password):
            user, session = self.user_manager.authenticate_user_session(session_token)
            if not user:
                return None, "Invalid credentials and/or session_token"

        try:
            user = self.user_manager.create_user(username, password, **kwargs)
        except (NameError, ValueError) as e:
            return None, str(e)

        return {
            'user_id': user.user_id,
            'username': user.username,
            'created_at': user.created_at.isoformat(),
        }

    @action
    def authenticate_user(self, username, password):
        """
        Authenticate a user
        :return: True if the provided username and password are correct, False otherwise
        """

        return True if self.user_manager.authenticate_user(username, password) else False

    @action
    def update_password(self, username, old_password, new_password):
        """
        Update the password of a user
        :return: True if the password was successfully updated, false otherwise
        """

        return self.user_manager.update_password(username, old_password, new_password)

    @action
    def delete_user(self, username, executing_user=None, executing_user_password=None, session_token=None):
        """
        Delete a user
        """

        if not self.user_manager.authenticate_user(executing_user, executing_user_password):
            user, session = self.user_manager.authenticate_user_session(session_token)
            if not user:
                return None, "Invalid credentials and/or session_token"

        try:
            return self.user_manager.delete_user(username)
        except NameError:
            return None, "No such user: {}".format(username)

    @action
    def create_session(self, username, password, expires_at=None):
        """
        Create a user session
        :return: dict::

            {
                "session_token": str,
                "user_id": int,
                "created_at": str (in ISO format),
                "expires_at": str (in ISO format),
            }

        """

        session = self.user_manager.create_user_session(username=username,
                                                        password=password,
                                                        expires_at=expires_at)

        if not session:
            return None, "Invalid credentials"

        return {
            'session_token': session.session_token,
            'user_id': session.user_id,
            'created_at': session.created_at.isoformat(),
            'expires_at': session.expires_at.isoformat() if session.expires_at else None,
        }

    @action
    def authenticate_session(self, session_token):
        """
        Authenticate a session by token and return the associated user
        :return: dict.

        Format::

            {
                "user_id": int,
                "username": str,
                "created_at": str (in ISO format)
            }

        """

        user, session = self.user_manager.authenticate_user_session(session_token=session_token)
        if not user:
            return None, 'Invalid session token'

        return {
            'user_id': user.user_id,
            'username': user.username,
            'created_at': user.created_at.isoformat(),
        }

    @action
    def delete_session(self, session_token):
        """
        Delete a user session
        """

        return self.user_manager.delete_user_session(session_token)

    @action
    def get_users(self) -> List[Dict[str, Any]]:
        """
        Get the list of registered users.
        :return:

            .. code-block:: json

                [
                    {
                        "user_id": 1,
                        "username": "******",
                        "created_at": "2020-11-26T22:41:40.550574"
                    },
                    {
                        "user_id": 2,
                        "username": "******",
                        "created_at": "2020-11-28T21:10:23.224813"
                    }
                ]

        """
        return [
            {
                'user_id': user.user_id,
                'username': user.username,
                'created_at': user.created_at.isoformat(),
            }
            for user in self.user_manager.get_users().all()
        ]

    @action
    def get_user_by_session(self, session_token: str) -> dict:
        """
        Get the user record associated to a session token.

        :param session_token: Session token.
        :return:

            .. code-block:: json

                [
                    {
                        "user_id": 1,
                        "username": "******",
                        "created_at": "2020-11-26T22:41:40.550574"
                    }
                ]

        """
        user = self.user_manager.get_user_by_session(session_token)
        assert user, 'No user associated with the specified session token'

        return {
            'user_id': user.user_id,
            'username': user.username,
            'created_at': user.created_at.isoformat(),
        }
Beispiel #13
0
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     self.user_manager = UserManager()
Beispiel #14
0
class UserPlugin(Plugin):
    """
    Plugin to programmatically create and manage users and user sessions
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.user_manager = UserManager()

    @action
    def create_user(self,
                    username,
                    password,
                    executing_user=None,
                    executing_user_password=None,
                    session_token=None,
                    **kwargs):
        """
        Create a user. This action needs to be executed by an already existing user, who needs to authenticate with
            their own credentials, unless this is the first user created on the system.

        :return: dict.

        Format::

            {
                "user_id": int,
                "username": str,
                "created_at": str (in ISO format)
            }

        """

        if self.user_manager.get_user_count(
        ) > 0 and not executing_user and not session_token:
            return None, "You need to authenticate in order to create another user"

        if not self.user_manager.authenticate_user(executing_user,
                                                   executing_user_password):
            user, session = self.user_manager.authenticate_user_session(
                session_token)
            if not user:
                return None, "Invalid credentials and/or session_token"

        try:
            user = self.user_manager.create_user(username, password, **kwargs)
        except (NameError, ValueError) as e:
            return None, str(e)

        return {
            'user_id': user.user_id,
            'username': user.username,
            'created_at': user.created_at.isoformat(),
        }

    @action
    def authenticate_user(self, username, password):
        """
        Authenticate a user
        :return: True if the provided username and password are correct, False otherwise
        """

        return self.user_manager.authenticate_user(username, password)

    @action
    def update_password(self, username, old_password, new_password):
        """
        Update the password of a user
        :return: True if the password was successfully updated, false otherwise
        """

        return self.user_manager.update_password(username, old_password,
                                                 new_password)

    @action
    def delete_user(self,
                    username,
                    executing_user=None,
                    executing_user_password=None,
                    session_token=None):
        """
        Delete a user
        """

        if not self.user_manager.authenticate_user(executing_user,
                                                   executing_user_password):
            user, session = self.user_manager.authenticate_user_session(
                session_token)
            if not user:
                return None, "Invalid credentials and/or session_token"

        try:
            return self.user_manager.delete_user(username)
        except NameError:
            return None, "No such user: {}".format(username)

    @action
    def create_session(self, username, password, expires_at=None):
        """
        Create a user session
        :return: dict::

            {
                "session_token": str,
                "user_id": int,
                "created_at": str (in ISO format),
                "expires_at": str (in ISO format),
            }

        """

        session = self.user_manager.create_user_session(username=username,
                                                        password=password,
                                                        expires_at=expires_at)

        if not session:
            return None, "Invalid credentials"

        return {
            'session_token':
            session.session_token,
            'user_id':
            session.user_id,
            'created_at':
            session.created_at.isoformat(),
            'expires_at':
            session.expires_at.isoformat() if session.expires_at else None,
        }

    @action
    def authenticate_session(self, session_token):
        """
        Authenticate a session by token and return the associated user
        :return: dict.

        Format::

            {
                "user_id": int,
                "username": str,
                "created_at": str (in ISO format)
            }

        """

        user, session = self.user_manager.authenticate_user_session(
            session_token=session_token)
        if not user:
            return None, 'Invalid session token'

        return {
            'user_id': user.user_id,
            'username': user.username,
            'created_at': user.created_at.isoformat(),
        }

    @action
    def delete_session(self, session_token):
        """
        Delete a user session
        """

        return self.user_manager.delete_user_session(session_token)