def authenticate(self, request):
        error = None
        try:
            backend = self.application.getAuthBackend()
            if isinstance(backend, KerberosRepository):
                authentication_results = backend.get_backend(
                ).authenticate_token(logger, self.credentials)
                self.backend_id = str(backend.id)
                self.credentials = [authentication_results['data']['dn'], ""]
                logger.info(
                    "AUTH:authenticate: User '{}' successfully authenticated on kerberos backend '{}'"
                    .format(self.credentials[0], backend))
                return authentication_results
            else:
                raise AuthenticationError(
                    "Backend '{}' not a Kerberos Repository".format(backend))

        except (AuthenticationError, ACLError) as e:
            error = e
            logger.error(
                "AUTH::authenticate: Authentication failure for kerberos token on primary backend '{}' : '{}'"
                .format(str(backend), str(e)))
            for fallback_backend in self.application.getAuthBackendFallback():
                try:
                    if isinstance(fallback_backend, KerberosRepository):
                        authentication_results = fallback_backend.get_backend(
                        ).authenticate_token(logger, self.credentials)
                        self.backend_id = str(backend.id)
                        self.credentials = [
                            authentication_results['data']['dn'], ""
                        ]
                        logger.info(
                            "AUTH:authenticate: User '{}' successfully authenticated on kerberos fallback backend '{}'"
                            .format(self.credentials[0], fallback_backend))

                        return authentication_results
                    else:
                        raise AuthenticationError(
                            "Backend '{}' not a Kerberos Repository".format(
                                fallback_backend))

                except (AuthenticationError, ACLError) as e:
                    error = e
                    logger.error(
                        "AUTH::authenticate: Authentication failure for kerberos token on fallback backend '{}' : '{}'"
                        .format(str(fallback_backend), str(e)))
                    continue

        raise error or AuthenticationError
 def authenticate(self):
     self.oauth2_token = self.redis_portal_session.get_oauth2_token(
         self.authenticated_on_backend())
     if not self.oauth2_token:
         authentication_results = super(OAUTH2Authentication,
                                        self).authenticate(None)
         logger.debug(
             "OAUTH2_AUTH::authenticate: Oauth2 attributes : {}".format(
                 str(authentication_results['data'])))
         if authentication_results['data'].get('oauth2', None) is not None:
             self.oauth2_token = Uuid4().generate()
             self.register_authentication(
                 authentication_results['data']['oauth2'])
             authentication_results = authentication_results['data'][
                 'oauth2']
         elif self.application.enable_oauth2:
             authentication_results = {
                 'token_return_type': 'both',
                 'token_ttl': self.application.auth_timeout,
                 'scope': '{}'
             }
             self.oauth2_token = Uuid4().generate()
             self.register_authentication(authentication_results)
         else:
             raise AuthenticationError(
                 "OAUTH2_AUTH::authenticate: OAuth2 is not enabled on this app nor on this repository"
             )
     else:
         # REPLACE CREDENTIAL 'user"
         self.redis_oauth2_session = REDISOauth2Session(
             self.redis_base, "oauth2_" + self.oauth2_token)
         authentication_results = self.redis_oauth2_session.keys
     return authentication_results
    def authenticate(self, request):
        repository = self.application.otp_repository

        if repository.otp_type == 'email':
            if repository.otp_mail_service == 'vlt_mail_service':
                if self.credentials[0] != self.credentials[
                        1] and self.credentials[0] not in [
                            '', None, 'None', False
                        ]:
                    raise AuthenticationError(
                        "The taped OTP key does not match with Redis value saved"
                    )

        else:
            # The function raise itself AuthenticationError, or return True
            repository.get_backend().authenticate(
                self.credentials[0],
                self.credentials[1],
                app=str(self.application.id),
                app_name=self.application.name,
                backend=self.backend_id,
                login=self.redis_session.get_login())

        logger.info(
            "DB-AUTH::authenticate: User successfully double-authenticated on OTP backend '{}'"
            .format(repository))
        self.redis_session.register_doubleauthentication()
        logger.debug(
            "DB-AUTH::authenticate: Double-authentication results successfully written in Redis session"
        )
        self.redis_portal_session.register_doubleauthentication(
            str(self.application.id))
        logger.debug(
            "DB-AUTH::authenticate: Double-authentication results successfully written in Redis portal session"
        )
    def set_authentication_params(self, repo, authentication_results):
        if authentication_results:
            self.backend_id = str(repo.id)

            if isinstance(authentication_results, User):
                result = {
                    'data': {
                        'password_expired': False,
                        'account_locked':
                        (not authentication_results.is_active),
                        'user_email': authentication_results.email
                    },
                    'backend': repo
                }
                if self.application.enable_oauth2:
                    result['data']['oauth2'] = {
                        'scope': '{}',
                        'token_return_type': 'both',
                        'token_ttl': self.application.auth_timeout
                    }
            logger.debug(
                "AUTH::set_authentication_params: Authentication results : {}".
                format(authentication_results))
            return result
        else:
            raise AuthenticationError(
                "AUTH::set_authentication_params: Authentication results is empty : '{}' for username '{}'"
                .format(authentication_results, self.credentials[0]))
 def authenticate_token(self, logger, token):
     result = self.client.verify_token(logger, token)
     if not result:
         logger.error(
             "KRB5_BACKEND::authenticate_token: Authenticate krb5 token returned Null"
         )
         raise AuthenticationError("Authentication failed for given token")
     else:
         return self.set_authentication_results(result)
    def authenticate(self, username, password, **kwargs):
        logger = kwargs.get('logger')
        try:
            return self.set_authentication_results(
                self.client.authenticate(username, password))

        except SocketError as e:
            logger.error(
                "RADIUS_BACKEND::authenticate: Timeout reached while trying to authenticate user '{}' : {}"
                .format(username, e))
            raise AuthenticationError(
                "Timeout reached while trying to authenticate user {}".format(
                    username))

        except Exception as e:
            logger.error(
                "RADIUS_BACKEND::authenticate: Error while trying to authenticate user '{}' : {}"
                .format(username, e))
            raise AuthenticationError(
                "Error during authentication of user {}".format(username))
Example #7
0
    def authenticate(self, username, password, **kwargs):
        acls = kwargs.get('acls', None)
        logger = kwargs.get('logger', None)
        try:
            attributes = self.client.authenticate(username, password)
            if attributes.get('account_locked'):
                raise AccountLocked("Locked account")
            logger.info(
                "LDAP_BACKEND::authenticate: Authentication succeed for user '{}'"
                .format(username))
            if acls and attributes:
                for acl in acls:
                    assert (self.verify_acl_user(logger, attributes['dn'], acl)
                            and self.verify_acl_group(logger, attributes['dn'],
                                                      acl))
            self.close_connection(logger)
            return self.set_authentication_results(attributes)

        except INVALID_CREDENTIALS:
            raise AuthenticationError(
                "LDAP_BACKEND::authenticate: Invalid credentials for user {}".
                format(username))

        except (UserNotFound, User.DoesNotExist) as e:
            raise AuthenticationError(
                "LDAP_BACKEND::authenticate: Username {} not found in LDAP base"
                .format(username))

        except AssertionError:
            self.close_connection(logger)
            raise ACLError(
                "User '{}' does not satisfy with any ACL".format(username))

        except Exception as e:
            self.close_connection(logger)
            logger.exception(e)
            logger.error(
                "LDAP_BACKEND::authenticate: Error while trying to authenticate user '{}' : {}"
                .format(username, e))
            raise e
Example #8
0
    def authenticate(self, user_id, key, **kwargs):
        totp = TOTP(user_id)
        if not totp.verify(key):
            raise AuthenticationError("TOTP taped token is not valid.")

        logger.info(
            "TOTP Token for user {} successfully verified.".format(user_id))

        # If the SSOProfile is not yet in MongoDB, set-it
        app_id = kwargs['app']
        app_name = kwargs['app_name']
        backend_id = kwargs['backend']
        login = kwargs['login']

        try:
            aes = AESCipher("{}{}{}{}{}".format(SECRET_KEY, app_id, backend_id,
                                                login, "totp"))
            encrypted_field = aes.key.hex()
            sso_profile = SSOProfile.objects.filter(
                encrypted_name=encrypted_field, login=login).first()
            if sso_profile:
                decrypted_value = sso_profile.get_data(
                    sso_profile.encrypted_value, app_id, backend_id, login,
                    "totp")
                if decrypted_value:
                    logger.debug(
                        "TOTP token for user '{}' retrieven from database.".
                        format(login))
                    return True

            # SSOProfile not found -> Create it
            sso_profile = SSOProfile()
            sso_profile.set_data(
                app_id, app_name, backend_id,
                BaseAbstractRepository.search_repository(
                    ObjectId(backend_id)).repo_name, login, "totp", user_id)
            logger.info(
                "TOTP token for user {} stored in database.".format(login))
            # Save in Mongo
            sso_profile.store()
        except Exception as e:
            logger.exception(e)
            raise e

        return True
Example #9
0
    def authenticate(self, user_id, key):
        authy_client = AuthyApiClient(str(self.authy_api_key))
        try:
            if self.type == 'phone':
                verification = authy_client.tokens.verify(
                    str(user_id), str(key))
                if verification.ok():
                    return True
            elif self.type == 'onetouch':
                # It's not the user_id but the 'send_request()' response that is sent here (bad variable name)
                verification = authy_client.one_touch.get_approval_status(
                    str(user_id))
        except Exception as e:
            logger.error(
                "AUTHY_CLIENT::authenticate: Error while trying to verify given key : {}"
                .format(e))
            raise OTPError("Authy error while verificating token : {}".format(
                str(e)))

        if self.type == 'onetouch':
            if verification.ok() and verification.status():
                if verification.content.get('approval_request',
                                            {}).get('status') == 'approved':
                    return True
                elif verification.content.get('approval_request',
                                              {}).get('status') == 'denied':
                    raise TwoManyOTPAuthFailure(
                        "The OneTouch request has been denied by the user")
                else:
                    raise OTPError(
                        "The OneTouch request is not yet approved, status : {}"
                        .format(
                            verification.content.get('approval_request',
                                                     {}).get('status')))

        # If we arrive here : verification.ok() returned False ; Authentication failure
        raise AuthenticationError(
            "Authy authentication error while verificating token : {}".format(
                verification.errors()))
Example #10
0
    def set_authentication_params(self, repo, authentication_results,
                                  username):
        if authentication_results:
            self.backend_id = str(repo.id)

            if isinstance(authentication_results, User):
                result = {
                    'data': {
                        'password_expired': False,
                        'account_locked':
                        (not authentication_results.is_active),
                        'user_email': authentication_results.email
                    },
                    'backend': repo
                }

            logger.debug(
                "AUTH::set_authentication_params: Authentication results : {}".
                format(authentication_results))
            return result
        else:
            raise AuthenticationError(
                "SELF::authenticate: Authentication result is empty for username '{}'"
                .format(username))
Example #11
0
    def perform_action(self, request, old_password):
        new_passwd = request.POST['password_1']
        new_passwd_cfrm = request.POST['password_2']

        rdm = (request.GET.get("rdm", None) or request.POST.get('rdm', None))

        # If not rdm : Verify password
        if not rdm:
            saved_app_id = self.redis_portal_session.keys['app_id_' +
                                                          str(self.backend.id)]
            saved_app = Application.objects(id=ObjectId(saved_app_id)).only(
                'id', 'name', 'pw_min_len', 'pw_min_upper', 'pw_min_lower',
                'pw_min_number', 'pw_min_symbol').first()
            if not self.redis_portal_session.getAutologonPassword(
                    str(saved_app.id), str(self.backend.id), self.username):
                raise AuthenticationError("Wrong old password")
        else:
            saved_app = self.application

        #Check if password meets required complexity
        upper_case = 0
        lower_case = 0
        number = 0
        symbol = 0

        min_len = int(saved_app.pw_min_len)
        min_upper = int(saved_app.pw_min_upper)
        min_lower = int(saved_app.pw_min_lower)
        min_number = int(saved_app.pw_min_number)
        min_symbol = int(saved_app.pw_min_symbol)

        for i in new_passwd:
            if i.isupper():
                upper_case += 1
            elif i.islower():
                lower_case += 1
            elif i.isdigit():
                number += 1
            else:
                symbol += 1

        if not (len(new_passwd) >= min_len and upper_case >= min_upper
                and lower_case >= min_lower and number >= min_number
                and symbol >= min_symbol):
            logger.info("SELF::change_password: Password is too weak")
            raise AuthenticationError(
                "Password do not meet complexity requirements")

        if issubclass(self.backend.__class__, Backend):
            self.backend.change_password(
                self.username,
                old_password,
                new_passwd,
                krb5_service=self.application.app_krb_service)
        elif isinstance(self.backend.get_backend(), MongoEngineBackend):
            user = User.objects.get(username=str(self.username))
            new_password_hash = make_password(new_passwd)
            user.password = new_password_hash
            user.save()
        else:
            self.backend.get_backend().change_password(
                self.username,
                old_password,
                new_passwd,
                krb5_service=self.application.app_krb_service)
        logger.info(
            "SELF::change_password: Password successfully changed in backend")

        # If not rdm : set new password in Redis portal session
        if not rdm:
            if self.redis_portal_session.setAutologonPassword(
                    str(saved_app.id), str(saved_app.name), str(
                        self.backend.id), self.username, old_password,
                    new_passwd) is None:
                # If setAutologonPasswd return None : the old_password was incorrect
                raise AuthenticationError("Wrong old password")
            logger.info(
                "SELF::change_password: Password successfully changed in Redis"
            )

        return "Password successfully changed"
Example #12
0
    def retrieve_credentials(self, request):
        """ We may have a password reset token in URI """
        rdm = request.GET.get("rdm", None) or request.POST.get('rdm', None)

        if not rdm:
            super(SELFServiceChange, self).retrieve_credentials(request)

        old_password = None  # None if rdm
        new_passwd = request.POST['password_1']
        new_passwd_cfrm = request.POST['password_2']
        if new_passwd != new_passwd_cfrm:
            raise PasswordMatchError("Password and confirmation mismatches")

        auth_backend = self.application.getAuthBackend()
        auth_backend_fallbacks = self.application.getAuthBackendFallback()

        if rdm:
            assert re_match("^[0-9a-f-]+$",
                            rdm), "PORTAL::self: Injection attempt on 'rdm'"

            email = self.redis_base.hget('password_reset_' + rdm, 'email')
            assert email, "SELF::Change: Invalid Random Key provided: '{}'".format(
                rdm)

            user_infos = self.get_username_by_email(auth_backend,
                                                    auth_backend_fallbacks,
                                                    email)
            self.username = user_infos['user']
            self.backend = user_infos['backend']

        else:
            # Get old_password
            old_password = request.POST[
                'password_old']  # If raise -> ask credentials

            # Get redis_portal_session
            portal_cookie = request.COOKIES.get(self.cluster.getPortalCookie())
            self.redis_portal_session = REDISPortalSession(
                self.redis_base, portal_cookie)
            # If not present -> 403
            assert self.redis_portal_session.exists(
            ), "PORTAL::self: portal session is not valid !"

            # And get username & backend from redis_portal_session
            user_infos = dict()
            auth_backend = self.application.getAuthBackend()
            if self.redis_portal_session.keys.get(
                    'login_' + str(self.application.getAuthBackend().id)):
                try:
                    user_infos = self.authenticate_on_backend(
                        auth_backend, self.username, old_password)
                    self.username = self.redis_portal_session.keys.get(
                        'login_' + str(auth_backend.id))
                    self.backend = auth_backend
                except Exception as e:
                    logger.error(
                        "Seems to have wrong old password on backend : '{}', exception details : "
                        + self.application.getAuthBackend().repo_name)
                    logger.exception(e)
            if not user_infos:
                for backend_fallback in self.application.getAuthBackendFallback(
                ):
                    if self.redis_portal_session.keys.get(
                            'login_' + str(backend_fallback.id)):
                        try:
                            user_infos = self.authenticate_on_backend(
                                backend_fallback, self.username, old_password)
                            self.username = self.redis_portal_session.keys.get(
                                'login_' + str(backend_fallback.id))
                            self.backend = backend_fallback
                            break
                        except:
                            logger.error(
                                "Seems to have wrong old password on backend : "
                                + backend_fallback.repo_name)

            if not self.backend:
                raise AuthenticationError("Wrong old password")
            logger.debug(
                "PORTAL::self: Found username from portal session: {}".format(
                    self.username))

        return old_password