def clean(self):

        try:
            user_dict = client.sso_search_user_by_email(self.cleaned_data["email"])
        except HTTPError as e:
            error_text = e.response.text
            if e.response.status_code == 404:
                msg = _("User with email %s not found")
                raise ValidationError({"email": msg % self.cleaned_data["email"]})
            logger.error("Error when searching user on the SSO: %s", error_text)
            raise ValidationError(error_text[:MAX_ERROR_MESSAGE_LENGTH])
        user = client.construct_user(user_dict)
        logger.info("Added SSO user %s locally", user)
Exemple #2
0
    def get(self, request, *args, **kwargs):
        # verify the authentication token and
        # retrieve the User instance from the SSO server
        message = request.GET.get('message', None)
        if not message:
            return HttpResponseBadRequest('No message')

        if settings.SSO_USE_V2_LOGIN:
            try:
                payload = jwt.decode(message, settings.SSO_SECRET,
                                     audience=settings.SSO_KEY)
            except jwt.exceptions.DecodeError:
                return HttpResponseBadRequest(
                    "Failed to decode JWT signature.")
            except jwt.exceptions.ExpiredSignatureError:
                return HttpResponseBadRequest(
                    "JWT recieved from the SSO has expired.")
            user_data = json.loads(payload['user'])
            if settings.SSO_ALLOW_ONLY_KNOWN_USERS:
                # First check if the user is known.
                if not User.objects.filter(username=user_data['username'],
                                           is_active=True).exists():
                    logger.info(
                        "Username %s isn't known/active locally",
                        user_data['username'])
                    return HttpResponseRedirect(
                        reverse('lizard_auth_client.disallowed_user'))

            user = client.construct_user(user_data)
        else:
            user = verify_auth_token(message)

        if not user:
            return HttpResponseBadRequest('Verification failed')

        # link the user instance to the default database backend
        # and call django-auth's login function
        user.backend = "%s.%s" % (BACKEND.__module__,
                                  BACKEND.__class__.__name__)
        django_login(request, user)
        # redirect the user to the stored "next" url, which is probably a
        # protected page
        if 'sso_after_login_next' in request.session:
            sso_after_login_next = request.session['sso_after_login_next']
            del request.session['sso_after_login_next']
        else:
            sso_after_login_next = getattr(
                settings, 'LOGIN_REDIRECT_URL', '/')

        return HttpResponseRedirect(sso_after_login_next)
Exemple #3
0
def verify_auth_token(untrusted_message):
    """
    Verifies a Auth Token. Returns a
    django.contrib.auth.models.User instance if successful or False.
    """
    # decrypt the message
    untrusted = URLSafeTimedSerializer(settings.SSO_SECRET).loads(
        untrusted_message, max_age=300)

    # do some extra validation
    if 'auth_token' not in untrusted:
        return False
    if 'request_token' not in untrusted:
        return False

    # call the SSO server to verify the token
    params = {
        'auth_token': untrusted['auth_token'],
        'key': settings.SSO_KEY
    }
    message = URLSafeTimedSerializer(settings.SSO_SECRET).dumps(params)
    url = urljoin(settings.SSO_SERVER_PRIVATE_URL, 'sso/api/verify') + '/'
    response = requests.get(
        url,
        params={
            'key': settings.SSO_KEY,
            'message': message
        },
        timeout=10
    )

    # ensure the response is sane
    if response.status_code != 200:
        return False

    # build a User object from the message
    data = URLSafeTimedSerializer(settings.SSO_SECRET).loads(
        response.content, max_age=300)
    user_data = json.loads(data['user'])

    user = client.construct_user(user_data)

    if 'roles' in data:
        role_data = json.loads(data['roles'])
        client.synchronize_roles(user, role_data)

    return user
    def clean(self):

        try:
            user_dict = client.sso_create_user(
                self.cleaned_data["first_name"],
                self.cleaned_data["last_name"],
                self.cleaned_data["email"],
                self.cleaned_data["username"],
            )
        except HTTPError as e:
            error_text = e.response.text
            if "duplicate username" in error_text:
                raise ValidationError({"username": (_("Username %s already used") % self.cleaned_data["username"])})
            logger.error("Error when creating user on the SSO: %s", error_text)
            raise ValidationError(error_text[:MAX_ERROR_MESSAGE_LENGTH])
        user = client.construct_user(user_dict)
        logger.info("Created user %s on the SSO and added it locally", user)
 def handle(self, *args, **options):
     """
     """
     sso_user = options.get('sso_user')
     if not sso_user:
         msg = '[E] Please provide the username for the user ' \
               'you are trying to sync.'
         raise Exception(msg)
     if V:
         print("[*] About to SSO-sync data for a User "
               "with username '%s'..." % sso_user)
     try:
         user_data = sso_get_user_django(sso_user)
         if V:
             print("[+] Received serialized User object: %s"
                   % str(user_data))
         user = construct_user(user_data)
         if V:
             print("[+] OK, build User instance: %s" % str(user))
         user.save()
         if V:
             print("[+] OK, succesfully saved this User instance!")
     except Exception as err:
         print("[E] err = '%s'" % str(err))
Exemple #6
0
    def authenticate(self, username=None, password=None):
        try:
            if username and password:
                user_data = None
                cache_key = 'SSOBackend.authenticate.{0}'.format(username)
                # Try getting the user_data from cache first.
                cached_credentials = cache.get(cache_key)
                if cached_credentials is not None:
                    logger.debug(
                        'Found user "%s" in the credential cache.', username)
                    # Found in cache, check the (hashed) password.
                    (cached_user_data,
                     cached_hashed_password) = cached_credentials
                    if check_password(password, cached_hashed_password):
                        logger.debug('Cached hashed password is OK.')
                        user_data = cached_user_data
                    else:
                        logger.debug(
                            'Failed cached password check for user "%s".',
                            username)
                else:
                    logger.debug(
                        'Could not find user "%s" in the credential cache.',
                        username)
                    # Not found in cache, call the SSO server.
                    if settings.SSO_USE_V2_LOGIN:
                        if settings.SSO_ALLOW_ONLY_KNOWN_USERS:
                            # First check if the user is known.
                            if not User.objects.filter(
                                    username=username,
                                    is_active=True).exists():
                                logger.debug(
                                    "Username %s isn't known/active locally",
                                    username)
                                return None

                        user_data = client.sso_authenticate_django_v2(
                            username, password)
                    else:
                        user_data = client.sso_authenticate_django_v1(
                            username, password)

                    # Store user_data in cache.
                    hashed_password = make_password(password)
                    if not is_password_usable(hashed_password):
                        return None
                    else:
                        cache.set(
                            cache_key,
                            (user_data, hashed_password),
                            settings.SSO_CREDENTIAL_CACHE_TIMEOUT_SECONDS)
                # Use either the cached user profile data, or fresh data from
                # the SSO server to construct a Django User instance. If
                # fresh data is used, also synchronize roles.
                if user_data:
                    user = client.construct_user(user_data)
                    if not cached_credentials:
                        if not settings.SSO_USE_V2_LOGIN:
                            client.sso_sync_user_organisation_roles(user)
                    return user
        except client.AuthenticationFailed as e:
            logger.info(e)
            return None
        except:
            logger.exception('Error while authenticating user "%s".', username)
            return None