Search code examples
djangoapitastypiebasic-authentication

Tastypie request user is anonymous on logout method


using the tastypie API and implementing some functionality for the user resource (following this example code: How can I login to django using tastypie), I wonder how the authenticated user is deposited or how I can access it in the right way. While testing the login method:

curl -u "user:pw" -H "Content-Type: application/json" -X POST --data '{"username" : "user", "password": "pw"}' http://localhost:8000/api/user/login/?format=json   

everything works fine; but the logout method sees the request.user as an anonymous user. How can I pass to the logout method the right authenticated user? Thanks a lot.

Snippet from api.py

class UserResource(ModelResource):
    class Meta:
        queryset = AppUser.objects.all()
        resource_name = 'user'
        fields = ['first_name', 'last_name', 'username', 'email', 'is_staff']
        allowed_methods = ['get', 'post', 'patch']
        always_return_data = True
        authentication = BasicAuthentication()
        authorization = Authorization()

    def prepend_urls(self):
        params = (self._meta.resource_name, trailing_slash())
        return [
            url(r"^(?P<resource_name>%s)/login%s$" % params, self.wrap_view('login'), name="api_login"),
            url(r"^(?P<resource_name>%s)/logout%s$" % params, self.wrap_view('logout'), name="api_login")
        ]

    def login(self, request, **kwargs):
        """
        Authenticate a user, create a CSRF token for them, and return the user object as JSON.
        """
        self.method_check(request, allowed=['post'])

        data = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))

        username = data.get('username', '')
        password = data.get('password', '')

        if username == '' or password == '':
            return self.create_response(request, {
                'success': False,
                'error_message': 'Missing username or password'
            })

        user = authenticate(username=username, password=password)

        if user:
            if user.is_active:
                login(request, user)
                response = self.create_response(request, {
                    'success': True,
                    'username': user.username
                })
                response.set_cookie("csrftoken", get_new_csrf_key())
                return response
            else:
                return self.create_response(request, {
                    'success': False,
                    'reason': 'disabled',
                }, HttpForbidden )
        else:
            return self.create_response(request, {
                'success': False,
                'error_message': 'Incorrect username or password'
            })

    def logout(self, request, **kwargs):
        """ 
        Attempt to log a user out, and return success status.       
        """
        self.method_check(request, allowed=['get'])
        if request.user and request.user.is_authenticated():
            logout(request)
            return self.create_response(request, { 'success': True })
        else:
            return self.create_response(request, { 'success': False, 'error_message': 'You are not authenticated, %s' % request.user.is_authenticated() })

Solution

  • If you're making your own custom tastypie URLs you need to call the tastypie authentication yourself before the request.user object is populated correctly.

    def logout(self, request, **kwargs):
        """ 
        Attempt to log a user out, and return success status.       
        """
        self.method_check(request, allowed=['get'])
    
        # Run tastypie's BasicAuthentication
        self.is_authenticated(request)
    
        if request.user and request.user.is_authenticated():
            logout(request)
            return self.create_response(request, { 'success': True })
        else:
            return self.create_response(request, { 'success': False, 'error_message': 'You are not authenticated, %s' % request.user.is_authenticated() })