Пример #1
0
def token(request):

    # Ensure we've got a JWT
    jwt = get_jwt(request)
    if not jwt:
        return redirect("dbmi_login:login")

    # Set the token
    context = {"jwt": jwt}

    return render(request,
                  template_name="dbmi_client/login/jwt.html",
                  context=context)
Пример #2
0
    def get_jwt_user(request):

        # Check for a valid token
        token = authn.get_jwt(request)
        if not token or not authn.validate_rs256_jwt(token):
            return AnonymousUser()

        # Get their username
        username = authn.get_jwt_username(request, verify=False)

        # Use the usual routine to get the currently cached user
        user = django_auth.get_user(request)
        if user.is_authenticated:
            logger.debug("Found existing User session: {}".format(username))

            # A cached user is present. We need to double-check JWT user to ensure
            # they are the same as the cached user.
            username = authn.get_jwt_username(request, verify=False)
            email = authn.get_jwt_email(request, verify=False)
            if username and email:
                if not user.username.lower() == username.lower(
                ) or not user.email.lower() == email.lower():
                    logger.debug(
                        "User session does not match JWT, logging out")

                    # TODO: Figure out if its necessary to person any session invalidation here
                    return AnonymousUser()

        else:
            logger.debug(
                "No existing User, attempting to login: {}".format(username))

            # No user is logged in but we have a JWT token. Attempt to authenticate
            # the current JWT and if it succeeds, login and cache the user.
            user = django_auth.authenticate(request, token=token)
            if user and user.is_authenticated:
                logger.debug("User has authenticated: {}".format(username))

                # Store this user in session
                django_auth.login(request, user)

            else:
                logger.debug(
                    "User could not be authenticated: {}".format(username))
                # Whatever token this user has, it's not valid OR their account would/could not
                # be created, deny permission. This will likely be the case for instances where
                # automatic user creation is disabled and a user with a valid JWT is not being
                # granted an account.
                raise PermissionDenied

        return user
Пример #3
0
    def get_jwt_user(request):

        # Check for a valid token
        token = authn.get_jwt(request)
        if not token or not authn.validate_rs256_jwt(token):
            return AnonymousUser()

        # Get their username
        username = authn.get_jwt_username(request, verify=False)

        # Attempt to authenticate the current JWT.
        user = django_auth.authenticate(request, token=token)
        if not user or not user.is_authenticated:
            logger.debug(
                "User could not be authenticated: {}".format(username))
            # Whatever token this user has, it's not valid OR their account would/could not
            # be created, deny permission. This will likely be the case for instances where
            # automatic user creation is disabled and a user with a valid JWT is not being
            # granted an account.
            raise PermissionDenied

        return user
Пример #4
0
    def get_jwt_user(request):

        # Use super's implementation
        user = DBMIAuthenticationMiddleware.get_jwt_user(request)
        if user:

            # Check if they've been granted admin level privileges
            if user.is_staff or user.is_superuser:

                # Get details
                token = authn.get_jwt(request)
                username = authn.get_jwt_username(request, verify=False)
                email = authn.get_jwt_email(request, verify=False)

                logger.debug(
                    f'User "{username}":"{email}" is currently admin; rerunning sync...'
                )

                # Run their sync again to make absolutely sure they're still an admin
                user = django_auth.authenticate(request, token=token)
                if user and user.is_authenticated:
                    logger.debug(
                        "User has re-authenticated: {}".format(username))

                    # Check updated status
                    if user.is_superuser or user.is_staff:
                        logger.debug(
                            f'User "{username}":"{email}" is still admin')

                else:
                    logger.debug(
                        "User could not be authenticated: {}".format(username))
                    # Whatever token this user has, it's not valid OR their account would/could not
                    # be created, deny permission. This will likely be the case for instances where
                    # automatic user creation is disabled and a user with a valid JWT is not being
                    # granted an account.
                    raise PermissionDenied

        return user
Пример #5
0
def _headers(request=None):
    """
    Returns the headers to use for Fileservice requests. If a Fileservice token is specified in settings,
    this will use that token to sign calls, otherwise, the current user's JWT will be used.
    :param request: The request
    :return: dict
    """
    if dbmi_settings.FILESERVICE_TOKEN:

        # Use the service token from environment
        return {"Authorization": "Token {}".format(dbmi_settings.FILESERVICE_TOKEN), "Content-Type": "application/json"}

    elif request:

        # Get the JWT
        token = authn.get_jwt(request)

        # Use the service token from environment
        return {"Authorization": "JWT {}".format(token), "Content-Type": "application/json"}

    else:
        raise ValueError("Cannot properly authenticate service call")
Пример #6
0
def get_permissions(request, email, item=None, children=False):
    """
    Consults the DBMIAuthz server for authorization checks. Uses the JWT to
    authenticate the call and checks the returned permissions for the one
    specified.
    :param request: The current request or JWT to authenticate the call
    :type HttpRequest: str
    :param email: The email in the JWT
    :type email: str
    :param item: The item string to check for the permission
    :type item: str
    :param children: Whether children of the passed item should be returned
    :type children: bool
    :return: A list of permissions
    :rtype: list
    """
    url = None
    content = None
    try:
        # Build the request
        url = furl(dbmi_settings.AUTHZ_URL)
        url.path.segments.append("user_permission")
        url.path.segments.append("")
        url.query.params.add("email", email)
        url.query.params.add("client", dbmi_settings.CLIENT)

        # Include children
        if children:
            url.query.params.add("children", "true")

        # Check for specific item
        if item:
            url.query.params.add("item", item)

        # Get the JWT token depending on request type
        if type(request) is str:
            token = request
        else:
            token = authn.get_jwt(request)

        # Ensure we've got a token
        if not token:
            return False

        # Build headers for the SciAuthZ call
        headers = {
            "Authorization": "{}{}".format(dbmi_settings.JWT_HTTP_PREFIX,
                                           token),
            "Content-Type": "application/json",
        }

        # Run it
        response = requests.get(url.url, headers=headers)
        content = response.content
        response.raise_for_status()

        return response.json().get("results", [])

    except (requests.HTTPError, TypeError, KeyError):
        logger.error(
            "SciAuthZ permission lookup failed",
            exc_info=True,
            extra={
                "email": email,
                "url": url,
                "content": content,
                "item": item
            },
        )

    return []
Пример #7
0
def has_a_permission(request, email, item, permissions, check_parents=False):
    """
    Consults the DBMIAuthz server for authorization checks. Uses the JWT to
    authenticate the call and checks the returned permissions for the one
    specified.
    :param request: The current request containing the JWT to be checked or the JWT itself
    :param email: The email in the JWT
    :param item: The item string to check for the permission
    :param permissions: A list of permissions
    :param check_parents: For every item, also attempt to match parents for the given permission
    :return: bool
    """
    url = None
    content = None
    try:
        # Build the request
        url = furl(dbmi_settings.AUTHZ_URL)
        url.path.segments.append("user_permission")
        url.path.segments.append("")
        url.query.params.add("email", email)
        url.query.params.add("client", dbmi_settings.CLIENT)

        # If we are searching parents, we need to fetch all permissions for this user
        if not check_parents:
            url.query.params.add("item", item)

        # Get the JWT token depending on request type
        if type(request) is str:
            token = request
        else:
            token = authn.get_jwt(request)

        # Ensure we've got a token
        if not token:
            return False

        # Build headers for the SciAuthZ call
        headers = {
            "Authorization": "{}{}".format(dbmi_settings.JWT_HTTP_PREFIX,
                                           token),
            "Content-Type": "application/json",
        }

        # Run it
        response = requests.get(url.url, headers=headers)
        content = response.content
        response.raise_for_status()

        # If checking parents...
        if check_parents and len(item.split(".")) > 1:

            # ... build list of all parent paths
            components = item.lower().split(".")
            items = [
                ".".join(components[:i + 1]) for i in range(len(components))
            ]

        else:

            # Set the single item list to search
            items = [item.lower()]

        # Parse permissions
        for permission_result in response.json().get("results"):

            # Get the items
            item = permission_result["item"].lower()
            permission = permission_result["permission"].lower()

            # Check it
            if item in items and permission in map(str.lower, permissions):
                logger.debug("DBMIAuthZ: {} has {} on {}".format(
                    email, permission, item))
                return True

    except (requests.HTTPError, TypeError, KeyError):
        logger.error(
            "SciAuthZ permission lookup failed",
            exc_info=True,
            extra={
                "request": request,
                "email": email,
                "permissions": permissions,
                "url": url,
                "content": content
            },
        )

    return False