0

I have a following user view:

class UserViewSet(viewsets.ModelViewSet):
    serializer_class = UserSerializer
    permission_classes = [NotSafeMethodAndAllowAny | permissions.IsAuthenticated]

    def get_queryset(self):
        if self.request.user.is_superuser:
            return User.objects.all()
        else:
            return User.objects.filter(id=self.request.user.id)

    @action(detail=False, methods=["get"])
    def current(self, request, *args, **kwargs):
        return Response(self.get_serializer(request.user).data)

As this is a ModelViewSet, it allows API users to create, list, update, delete the users.

Don't mind the NotSafeMethodAndAllowAny permission.

Now I want to somehow protect my API from the users using it like in a script. For example, when I submit the user registration form on my frontend (a separate React app), it should be accepted, but if someone posts to my api/user/ with random registration data like from Postman/curl/etc., I want it to be discarded.

Is there a way for DRF to distinguish between those two types of requests? And possibly via some setting, so I can test it via Postman when in development, but when it runs in production, it would not accept automated requests. I want to prevent a situation where someone would create like a bazillion users in a matter of minutes.

BTW: I use JWT for authentication, but for obvious reasons the registration/login endpoints do not require authentication.

dabljues
  • 1,663
  • 3
  • 14
  • 30
  • You can't block requests from Postman and other similar dev tools. Now some specifities like headers can help you identify if that comes from Postman (or any other tool), see this post: https://stackoverflow.com/a/62015405/13964753 – Guillaume May 05 '21 at 19:34
  • This is nice. But then people can use curl, python, anything to potentially attack my website. Is there any solution other than throttling/e-mail verification? – dabljues May 05 '21 at 19:38
  • What kind of attack are you talking about? If you securely build your website not messing around with Django security settings that should be just fine. If you're affraid of DDOS or that kind of thing, just go to a cloud provider which will provide you with a protection. Otherwise, using throttling, protected view etc.... should be enough. – Guillaume May 05 '21 at 20:18
  • Not DDoS per se, just some user abusing the API to create dummy users, just for the fun of it. I don't know if this is a real threat, I won't be releasing my app into real world any time soon. I was just wondering how that stuff works, cuz if for example Facebook wouldn't have e-mail confirmation, would they allow users to create 10-50 accounts in a row before the throttling kicks in? – dabljues May 05 '21 at 20:21
  • 1
    In that case, the only solution is throttling, and then email validation, but here again, whether via browser or via postman, that does not change anything... – Guillaume May 05 '21 at 20:59
  • 1
    True, just wanted to confirm. Cannot accept a comment, but you've answered my question, thank you! – dabljues May 05 '21 at 21:06

1 Answers1

0

If i understand maybe you can create a CustomPermission and only allow requests from specific IP ADDRESS.

from rest_framework import permissions

class IpAddressPermission(permissions.BasePermission):
"""
    Global permission check for IPs.
"""

def has_permission(self, request, view):

    remote_address = request.META['REMOTE_ADDR']
    if remote_addr == settings.ALLOWED_IP_ADDRESS:
        return True

    return False
  • That's not the solution, because potential users of my app would use it from different locations. I don't want to restricts users' access, I want to restricts bots' access - differentiate between my frontend app requests and simple requests from command line/tools. – dabljues May 05 '21 at 19:29
  • But your frontend app has a static ip address?, the ALLOWED_IP_ADDRESS must be the frontend ip address, – Christian Buendia May 05 '21 at 19:41
  • Hmm, not for now, but if it does distinguish between ports, then it would work for me I guess – dabljues May 05 '21 at 20:00