예제 #1
0
파일: core.py 프로젝트: proteanhq/authentic
    def process_request(self, request_object):
        """Process update Account Request"""

        identifier = request_object.identifier
        data = request_object.data
        account = Account.get(identifier)

        if pbkdf2_sha256.verify(data['current_password'], account.password):
            password_check = validate_new_password(data['new_password'],
                                                   account.password_history)
            if password_check['is_valid']:
                password = pbkdf2_sha256.hash(data['new_password'])
                password_history = modify_password_history(
                    account.password, account.password_history)
                account.update({
                    'password': password,
                    'password_history': password_history
                })
                return ResponseSuccess(Status.SUCCESS, {"message": "Success"})
            else:
                return ResponseFailure.build_unprocessable_error(
                    {'new_password': password_check['error']})
        else:
            return ResponseFailure.build_unprocessable_error(
                {'current_password': '******'})
예제 #2
0
    def process_request(self, request_object):
        token = request_object.token
        account = get_account_entity().query.filter(
            verification_token=token).first

        if account:
            token_time = account.token_timestamp
            if datetime.datetime.utcnow() > token_time:
                return ResponseFailure.build_unprocessable_error(
                    "Token expired")
            else:
                account.update({"is_verified": True})
                return ResponseSuccess(Status.SUCCESS, account)
        else:
            return ResponseFailure.build_unprocessable_error("Invalid Token")
예제 #3
0
파일: core.py 프로젝트: proteanhq/authentic
    def process_request(self, request_object):
        token = request_object.token
        data = request_object.data

        verify_token_use_case = VerifyTokenUseCase()
        verify_token_req_obj = VerifyTokenRequestObject.from_dict(
            request_object.entity_cls, {'token': token})
        response_object = verify_token_use_case.execute(verify_token_req_obj)

        if response_object.success:
            account = response_object.value
            password_check = validate_new_password(data['new_password'],
                                                   account.password_history)
            if password_check['is_valid']:
                password = pbkdf2_sha256.hash(data['new_password'])
                password_history = modify_password_history(
                    account.password, account.password_history)
                account.update({
                    'password': password,
                    'is_locked': False,
                    'login_attempts': 0,
                    'password_history': password_history
                })

                return ResponseSuccess(Status.SUCCESS, {"message": "Success"})
            else:
                return ResponseFailure.build_unprocessable_error(
                    {'new_password': password_check['error']})
        else:
            return response_object
예제 #4
0
파일: core.py 프로젝트: proteanhq/authentic
    def process_request(self, request_object):
        email = request_object.email
        account = Account.query.filter(email=email).first

        if account:
            token = str(uuid.uuid4())
            token_ts = datetime.datetime.utcnow() + datetime.timedelta(
                hours=24)
            account.update({
                "verification_token": token,
                "token_timestamp": token_ts
            })

            # Send the password request email
            email_builder = perform_import(active_config.RESET_EMAIL_CALLBACK)
            if not email_builder:
                raise ConfigurationError(
                    '`RESET_EMAIL_CALLBACK` config must be set to a '
                    'valid function.')
            email_msg = email_builder(account.email, token)
            email_msg.send()

            return ResponseSuccess(Status.SUCCESS, {"message": "Success"})
        else:
            return ResponseFailure.build_unprocessable_error(
                {'email': 'Account does not exist.'})
예제 #5
0
파일: core.py 프로젝트: proteanhq/authentic
    def process_request(self, request_object):
        """Process Login Request"""
        # FIXME Use `OR` condition for `username` or `email` query
        account = Account.query.filter(
            username=request_object.username_or_email).first
        if not account:
            account = Account.query.filter(
                email=request_object.username_or_email).first
            if not account:
                return ResponseFailure.build_unprocessable_error(
                    {'username_or_email': 'Account does not exist'})

        if not account.is_locked and account.is_active:
            if pbkdf2_sha256.verify(request_object.password, account.password):

                if active_config.ENABLE_ACCOUNT_VERIFICATION and \
                        not account.is_verified:
                    # Todo: Handle sending account verification mail
                    return ResponseFailure.build_unprocessable_error(
                        {'username_or_email': 'Account is not verified'})
                else:
                    # Run the login callback usecase and return its response
                    auth_backend = get_auth_backend()
                    cb_usecase = auth_backend.LoginCallbackUseCase()
                    cb_request_obj = LoginCallbackRequestObject.from_dict(
                        request_object.entity_cls, {'account': account})
                    return cb_usecase.execute(cb_request_obj)
            else:
                allowed_login_attempts = \
                    active_config.PASSWORD_RULES['max_invalid_attempts']
                if account.login_attempts and \
                        account.login_attempts >= allowed_login_attempts:
                    account.update(account.id, {'is_locked': True})
                    return ResponseFailure.build_unprocessable_error({
                        'password':
                        '******'
                        'Account has been locked.'
                    })
                else:
                    account.login_attempts += 1
                    account.update({'login_attempts': account.login_attempts})
                    return ResponseFailure.build_unprocessable_error(
                        {'password': '******'})
        else:
            return ResponseFailure.build_unprocessable_error(
                {'username_or_email': 'Account has been locked/deactivated.'})
예제 #6
0
파일: core.py 프로젝트: proteanhq/authentic
    def process_request(self, request_object):
        """Process Create Account Request"""
        data = request_object.data
        is_idp_login = request_object.data.get('is_idp', False)

        if Account.query.filter(email=data['email']):
            return ResponseFailure.build_unprocessable_error(
                {'email': 'Email already exists'})

        if not is_idp_login:
            if Account.query.filter(username=data['username']):
                return ResponseFailure.build_unprocessable_error(
                    {'username': '******'})

            password_check = validate_new_password(data['password'], [])
            if not password_check['is_valid']:
                return ResponseFailure.build_unprocessable_error(
                    {'password': password_check['error']})

        data['password'] = pbkdf2_sha256.hash(data['password'])
        account = Account.create(data)

        return ResponseSuccessCreated(account)
예제 #7
0
파일: core.py 프로젝트: proteanhq/authentic
    def process_request(self, request_object):
        """Process update Account Request"""
        account_obj = Account.get(request_object.identifier)
        if request_object.data.get('email') and \
                account_obj.email != request_object.data.get('email') and \
                Account.query.filter(email=request_object.data['email']):
            return ResponseFailure.build_unprocessable_error(
                {'email': 'Email already exists'})

        # Remove fields that cannot be updated
        for field in ['password', 'username']:
            request_object.data.pop(field, None)

        return super().process_request(request_object)
예제 #8
0
    def process_request(self, request_object):
        """Process Authentication Request"""
        # Get the decode key for the alg
        decode_key = active_config.SECRET_KEY
        if active_config.JWT_ALGORITHM in requires_cryptography:
            with open(active_config.JWT_PUBLIC_KEY) as fp:
                decode_key = fp.read()

        # Decode and validate the jwt
        try:
            jwt_data = decode_jwt(
                encoded_token=request_object.credentials,
                secret=decode_key,
                algorithm=active_config.JWT_ALGORITHM,
                identity_claim_key=active_config.JWT_IDENTITY_CLAIM)
        except (JWTDecodeError, DecodeError, ExpiredSignatureError) as e:
            return ResponseFailure(Status.UNAUTHORIZED,
                                   {'credentials': f'Invalid JWT Token. {e}'})

        # Find the identity in the decoded jwt
        identity = jwt_data.get(active_config.JWT_IDENTITY_CLAIM, None)
        try:
            account = Account.get(identity.get('account_id'))
        except ObjectNotFoundError:
            return ResponseFailure(
                Status.UNAUTHORIZED,
                {'username_or_email': 'Account does not exist'})

        # Make sure that the session exits
        session = Session.query.filter(
            session_key=f'token-{account.id}-{jwt_data["jti"]}', )
        if not session or session.first.expire_date < datetime.utcnow():
            return ResponseFailure(Status.UNAUTHORIZED,
                                   {'token': 'Invalid Token'})

        context.set_context({'jwt_data': jwt_data})
        return ResponseSuccess(Status.SUCCESS, account)
예제 #9
0
    def process_request(self, request_object):
        identifier = request_object.identifier
        mfa_otp = request_object.mfa_otp
        account = Account.get(identifier)
        # FIXME MFA throws invalid key with the following approach
        # secret = base64.b64encode(bytes(account.mfa_key + CONFIG.MFA_SECRET_KEY,
        #                                 encoding='utf-8')).decode('utf-8')[:16]
        totp = pyotp.TOTP(account.mfa_key)
        if not totp.verify(mfa_otp):
            return ResponseFailure.build_unprocessable_error(
                "Invalid OTP")
        if not account.mfa_enabled:
            account.update({"mfa_enabled": True})

        return ResponseSuccess({"message": "Valid OTP"})
예제 #10
0
    def process_request(self, request_object):
        """Process Authentication Request"""

        try:
            auth_parts = base64.b64decode(
                request_object.credentials).decode('iso-8859-1').partition(':')
        except (TypeError, UnicodeDecodeError, binascii.Error):
            return ResponseFailure.build_unprocessable_error({
                'credentials':
                'Invalid basic header. Credentials not '
                'correctly base64 encoded.'
            })

        payload = {
            'username_or_email': auth_parts[0],
            'password': auth_parts[2],
        }

        request_object = LoginRequestObject.from_dict(
            request_object.entity_cls, payload)
        use_case = LoginUseCase()
        return use_case.execute(request_object)