3

I'm using httpie to test my custom authentication.

http POST http://127.0.0.1:8000/api-token-auth/ username='username1' password='Password123'

I did create a custom auth object using AbstractUser.

Using TokenAuthentication, I followed the docs and added my custom TokenAuthentication in my REST_FRAMEWORK settings:

REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
    'regis.models.CustomAuthentication',
    )
}

And added rest_framework.authtoken in my installed apps.

My AUTHENTICATION_BACKEND is as follows:

AUTHENTICATION_BACKENDS = [ 'regis.models.CustomAuthentication' ]

And here is my custom authentication class:

class CustomAuthentication(authentication.TokenAuthentication):
    def authenticate(self, request):
        username = request.META.get('X_USERNAME')
        print(username)
        user_model = get_user_model()
        if not username:
            return None
    try:
        user = user_model.objects.get(username=username)
    except User.DoesNotExist:
        raise exceptions.AuthenticationFailed('No such user')
    return (user, None)

urls.py:

urlpatterns += [
    url(r'^api-token-auth/', views.obtain_auth_token),

    ]

I'm pretty much following the DRF docs (http://www.django-rest-framework.org/api-guide/authentication/#custom-authentication). If there's any additional info needed to solve this, please let me know and I'll update. Any help on what I'm missing would be great.

To add: Just out of curiosity, do I need to make a custom authentication system if I have a custom user?

UPDATE:

I just deleted the class above, and just added the rest_framework.authentication.TokenAuthentication in my REST_FRAMEWORK settings. I'm still using a custom authentication which fetches my user.

It looks like this (not going to format it. SO sucks at formatting code from VIM):

class CustomAuthentication(object):
def authenticate(self, email=None, password=None):

    User = get_user_model()
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist:
        return None
    if user.check_password(password):
        return user

    return None

def get_user(self, user_id):
    try:
        user_model = get_user_model()
        user = user_model.objects.get(pk=user_id)
    except User.DoesNotExist:
        return None

I used this Django docs to create that code: https://docs.djangoproject.com/en/1.10/topics/auth/customizing/

5
  • Just to answer your curiosity: No, you do not need a custom Authentication if you are using a custom user. The build I use at work has a custom user and uses the default ModelBackend shipped with Django. :) Commented Feb 24, 2017 at 2:20
  • @Neelik ayyyee hook me up with a job there! Commented Feb 24, 2017 at 2:34
  • Maybe when the company grows a bit :P We're still a little local group right now. Commented Feb 24, 2017 at 2:44
  • The indentation in your code (the `try:) line, is incorrect, but I suspect this is only in this question, not in your actual code? Commented Feb 24, 2017 at 3:32
  • Yes, it's just in the question. Copying and pasting from vim is sort of a pain. Commented Feb 24, 2017 at 3:42

2 Answers 2

2

If you search for the error string in the DRF code, you find this (in authtoken/serializers.py:

from django.contrib.auth import authenticate
...

if username and password:                                                                                                                                                                                                              
    user = authenticate(username=username, password=password)                                                                                                                                                                          

    if user:                                                                                                                                                                                                                           
        # From Django 1.10 onwards the `authenticate` call simply                                                                                                                                                                      
        # returns `None` for is_active=False users.                                                                                                                                                                                    
        # (Assuming the default `ModelBackend` authentication backend.)                                                                                                                                                                
        if not user.is_active:                                                                                                                                                                                                         
            msg = _('User account is disabled.')                                                                                                                                                                                       
            raise serializers.ValidationError(msg, code='authorization')
    else:                                                                                                                                                                                                                     
        msg = _('Unable to log in with provided credentials.')                                                                                                                                                                         
        raise serializers.ValidationError(msg, code='authorization')
...

So it looks like depending on which version of Django you're using, either these credentials are incorrect, or the user is not active (for Django >= 1.10)?

Have you tried logging in manually in the admin with these credentials to verify them?

Sign up to request clarification or add additional context in comments.

2 Comments

I'm doing iOS development and using the email and password to log in which is fine. I went to the shell, and queried for the user's username and it's correct. I just checked if the user is active, and it shows 'true'. Does everything look correct in my question, or am I just missing something I'm not aware of?
btw, yes I'm using Django 1.10.2
1

OK I solved it. Inside my settings, I just had to remove the AUTHENTICATIONS_BACKEND. I thought my custom backend was different for merely logging a user in and the token authentication backend worked to get that token.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.