Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Securely POST a request without login in django

I am developing a django server as a backend to an iOS app. Until now, I've been creating new users through a registration page through the browser. I would love though to be able to register new users through a form in my iOS app. I am using Django REST, for the mobile API to my django server.

Unfortunately, to be able to POST any requests, I need authorization. This is perfectly fine, as the vast majority of the time, my users need to be logged in. The only time they are using my app when not logged in, is exactly when they're signing up (new user).

Signing up means creating a new user. Creating a new user, means inserting new data to the database, which of course according to RESTful practices, means I need to use a POST request. But how do I do that without authorization, since I'm not logged in yet.

I have two ideas on how to potentially do it, below, but I would love to know what the best practice is.

1) When new user goes to the sign up view, the django server can silently create a new user account, with default initial data. This new account can be sent as data to the app, allowing authorization to be formalized. The registration view, simply updates the user account. I would probably need to delete this new user, if it isn't updated (registration form was not sent in due time).

2) Have a hardcoded "admin" user, that is simply used to authorize these anonymous POST requests. I imagine it is possible to limit this admins scope to only one function?

like image 583
jhc Avatar asked Sep 11 '25 05:09

jhc


2 Answers

Django REST framework allows you to set the permission policy on a per-view basis. You can use this to allow unauthenticated POST requests on just the registration view. For example, if you use an APIView for this:

from rest_framework.permissions import AllowAny
from rest_framework.views import APIView

class RegistrationView(APIView):
    permission_classes = (AllowAny,)

    ...

You can still keep IsAuthenticated as the default permission for all other views.

For more information, read "setting the permission policy"

like image 83
knbk Avatar answered Sep 13 '25 21:09

knbk


I'd try something like extend the Authentication class you are using (let's say it is BasicAuthentication) and customize the is_authenticated method to fit your scenario, this is a rough example.

class AnonymousPostAuthentication(BasicAuthentication):
    """ No auth on post / for user creation """

    def is_authenticated(self, request, **kwargs):
        """ If PATH and POST match your scenario, 
        don't check auth, otherwise fall back to parent """

        if request.path == "/<path_to_your_anonymous_post_service>" \
           and request.method == "POST" :
            return True
        else:
            return (super(AnonymousPostAuthentication,self)
                        .is_authenticated(request, **kwargs))

Of course, you need to change your Authentication backend later to something like:

AUTHENTICATION_BACKENDS = [
    'project.path.to.AnonymousPostAuthentication',
]

You can extend this in the official docs

like image 20
Rafael Aguilar Avatar answered Sep 13 '25 19:09

Rafael Aguilar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!