def execute(self, user_id: int, name: str, code: str) -> Set[str]: mfa = self._mfa_model.objects.get_by_name(user_id=user_id, name=name) get_mfa_handler(mfa).confirm_activation(code) rows_affected = self._mfa_model.objects.filter( user_id=user_id, name=name).update( is_active=True, is_primary=not self._mfa_model.objects.primary_exists( user_id=user_id), ) if rows_affected < 1: raise MFAMethodDoesNotExistError() backup_codes = regenerate_backup_codes_for_mfa_method_command( user_id=user_id, name=name, ) return backup_codes
def is_authenticated(self, user_id: int, code: str) -> None: for auth_method in self._mfa_model.objects.list_active(user_id=user_id): validated_backup_code = validate_backup_code_command( value=code, backup_codes=auth_method.backup_codes ) if get_mfa_handler(mfa_method=auth_method).validate_code(code=code): return if validated_backup_code: remove_backup_code_command( user_id=auth_method.user_id, method_name=auth_method.name, code=code ) return raise InvalidCodeError()
def post(self, request: Request) -> Response: serializer = LoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) try: user = authenticate_user_command( request=request, username=serializer.validated_data[User.USERNAME_FIELD], password=serializer.validated_data["password"], ) except MFAValidationError as cause: return ErrorResponse(error=cause) try: mfa_model = get_mfa_model() mfa_method = mfa_model.objects.get_primary_active(user_id=user.id) get_mfa_handler(mfa_method=mfa_method).dispatch_message() return Response( data={ "ephemeral_token": user_token_generator.make_token(user), "method": mfa_method.name, }) except MFAMethodDoesNotExistError: return self._successful_authentication_response(user=user)
def post(request: Request) -> Response: serializer = MFAMethodCodeSerializer(data=request.data) serializer.is_valid(raise_exception=True) try: method = serializer.validated_data.get("method") mfa_model = get_mfa_model() if method is None: method = mfa_model.objects.get_primary_active_name( user_id=request.user.id) mfa = mfa_model.objects.get_by_name(user_id=request.user.id, name=method) return get_mfa_handler(mfa_method=mfa).dispatch_message() except MFAValidationError as cause: return ErrorResponse(error=cause)
def authenticate_multi_factor( self, mfa_method: MFAMethod, user: AbstractUser, path: str = PATH_AUTH_JWT_LOGIN, path_2nd_factor: str = PATH_AUTH_JWT_LOGIN_CODE, ) -> Response: response = self._first_factor_request(user=user, path=path) ephemeral_token = self._extract_ephemeral_token_from_response( response=response) handler = get_mfa_handler(mfa_method=mfa_method) response = self._second_factor_request(handler=handler, ephemeral_token=ephemeral_token, path=path_2nd_factor) self._update_jwt_from_response(response=response) return response
def post(request: Request, method: str) -> Response: try: source_field = get_mfa_config_by_name_query( name=method).get(SOURCE_FIELD) except MFAMethodDoesNotExistError as cause: return ErrorResponse(error=cause) if source_field is not None: serializer_class = generate_model_serializer( name="MFAMethodActivationValidator", model=request.user.__class__, fields=(source_field, ), ) serializer = serializer_class(data=request.data) serializer.is_valid(raise_exception=True) try: mfa = create_mfa_method_command( user_id=request.user.id, name=method, ) except MFAValidationError as cause: return ErrorResponse(error=cause) return get_mfa_handler(mfa_method=mfa).dispatch_message()
def validate_code(self, value: str) -> str: if not value: raise OTPCodeMissingError() mfa_model = get_mfa_model() mfa = mfa_model.objects.get_by_name(user_id=self._user.id, name=self._mfa_method_name) self._validate_mfa_method(mfa) validated_backup_code = validate_backup_code_command( value=value, backup_codes=mfa.backup_codes) handler = get_mfa_handler(mfa) validation_method = getattr(handler, self._get_validation_method_name()) if validation_method(value): return value if validated_backup_code: remove_backup_code_command(user_id=mfa.user_id, method_name=mfa.name, code=value) return value raise CodeInvalidOrExpiredError()