DRF auth_token: "non_field_errors": [ "Unable to log in with provided credentials."
Asked Answered
V

11

14

Both JWT packages written for Django gave me issues with poor documentation, so I try DRF-auth_token package. This is a good example I followed, Django Rest Framework Token Authentication. You should in theory be able to go to

localhost:8000/api-token-auth/

urls.py:

from django.conf.urls import url, include
from django.contrib import admin
from django.contrib.auth.models import User
from rest_framework.authtoken import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include('api.urls', namespace='api')),
    url(r'^orders/', include('orders.urls', namespace='orders')),
    url(r'^api-token-auth/', views.obtain_auth_token, name='auth-token'),

]

Getting a token for users is not working so I have rewritten it myself to make it work:

@api_view(['POST'])
def customer_login(request):
    """
    Try to login a customer (food orderer)
    """
    data = request.data

    try:
        username = data['username']
        password = data['password']
    except:
        return Response(status=status.HTTP_400_BAD_REQUEST)

    try:
        user = User.objects.get(username=username, password=password)
    except:
        return Response(status=status.HTTP_401_UNAUTHORIZED)

    try:
        user_token = user.auth_token.key
    except:
        user_token = Token.objects.create(user=user)

    data = {'token': user_token}
    return Response(data=data, status=status.HTTP_200_OK)

My version works:

http://localhost:8000/api/login/customer-login/
{"username": "[email protected]", "password": "wombat"}
-->
{
  "token": "292192b101153b7ced74dd52deb6b3df22ef2c74"
}

The DRF auth_token does not work:

http://localhost:8000/api-token-auth/
{"username": "[email protected]", "password": "wombat"}
-->
{
  "non_field_errors": [
    "Unable to log in with provided credentials."
  ]
}

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # third party:
    'django_extensions',
    'rest_framework',
    'rest_framework.authtoken',



REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    )
}

It seems set up correctly. Every user in my DB has a token. Each user is is_authenticated and is_active in DB. Super users can get their token:

localhost:8000/api-token-auth/
{"username": "mysuperuser", "password": "superuserpassword"}
-->
{
  "token": "9297ff1f44dbc6caea67bea534f6f7590d2161b0"
}

for some reason, only super user can get a token:

localhost:8000/api-token-auth/
{"username": "regularguy", "password": "password"}
-->
{
  "non_field_errors": [
    "Unable to log in with provided credentials."
  ]
}

Why can't my users log in and get their token?

Voracious answered 16/10, 2016 at 22:38 Comment(1)
The answer for me was the cryptography of the password when you create the User.Equivoque
B
7

I went ahead and did this from the drf token auth docs and didn't run into any problems with superusers, staffusers, or normal users.

Also try following the steps of the official docs instead of that SO answer and see if that fixes the problem - it's possible something changed.

Here were the general steps I took:

  • install django, drf
  • put 'rest_framework' and 'rest_framework.authtoken' in INSTALLED_APPS
  • add 'TokenAuthentication' in my rest_framework settings
  • run migrate
  • create tokens for users (I just did this in urls.py)
  • create the url for token
  • POST http://localhost:8000/token/ {"username": "...", "password": "..."}

If you have the code public anywhere I'd be glad to take a further look and see what I find.

Badlands answered 17/10, 2016 at 2:53 Comment(4)
yes, thank you [email protected]:codyc54321/stack_overflow_nyble_copy.gitVoracious
I tried your code and got django.db.utils.OperationalError: no such table: auth_userVoracious
Were you able to get this working? I happen to face the same problem.Caliber
I don't remember rads, I've paused that project for now and gonna use flask anyway its just APIVoracious
K
31
  • I had the same error message when I tried to use this API endpoint :
    " obtain_auth_token" class from rest_framework.authtoken.views ,
    BUT surprise ! The problem was the User serializer in first place ! .

  • Users were created with the API endppint ,their passwords were saved as plain text !, as in this screenshot : User Database
    BUT the TokenAPI endpoint encrypts the password, so from there come the clash! ,

  • I've changed User Serializer class and override create function to use set_password function that hashes the passwords :

    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ['email', 'username', 'password']
            extra_kwargs = {'password': {'write_only': True}}
    
        def create(self, validated_data):
            user = User(
                email=validated_data['email'],
                username=validated_data['username']
            )
            user.set_password(validated_data['password'])
            user.save()
            return user
    
  • Now that I've edited my User Serializer , data are stored like this : User database after modification

  • And So the error : “non_field_errors”: [ “Unable to log in with provided credentials.” stopped showing ! , and the token API endpoint "localhost:8000/api-token-auth/" worked !

Kosel answered 13/11, 2019 at 5:18 Comment(3)
please edit your answer and put the codes as text instead of putting the image of them.Storekeeper
you can create user using user = self.Meta.model()Multiphase
I had the same issue and this helped me debug itThompkins
B
7

I went ahead and did this from the drf token auth docs and didn't run into any problems with superusers, staffusers, or normal users.

Also try following the steps of the official docs instead of that SO answer and see if that fixes the problem - it's possible something changed.

Here were the general steps I took:

  • install django, drf
  • put 'rest_framework' and 'rest_framework.authtoken' in INSTALLED_APPS
  • add 'TokenAuthentication' in my rest_framework settings
  • run migrate
  • create tokens for users (I just did this in urls.py)
  • create the url for token
  • POST http://localhost:8000/token/ {"username": "...", "password": "..."}

If you have the code public anywhere I'd be glad to take a further look and see what I find.

Badlands answered 17/10, 2016 at 2:53 Comment(4)
yes, thank you [email protected]:codyc54321/stack_overflow_nyble_copy.gitVoracious
I tried your code and got django.db.utils.OperationalError: no such table: auth_userVoracious
Were you able to get this working? I happen to face the same problem.Caliber
I don't remember rads, I've paused that project for now and gonna use flask anyway its just APIVoracious
D
6
  1. check username and password
  2. field in the table users.is_active = 1
Dybbuk answered 8/8, 2018 at 15:57 Comment(2)
Wow, after searching for a longer time to no avail this simple thing of setting user.is_active solved my issue. Thanks!Sabinesabino
This stupid error took me hours to debug! TYSM :DMaricamarice
R
6

Maybe the encryption is to blame. I am facing the same problem. I compared the information stored in mysql of superuser and a common user (let's call it user1). I found a difference. The password of superuser was encrypted, but user1's password wasn't encryted. So I changed user1's password into the superuser's password, then I posted the name and password of user1 to the jwt api and I got the right answer.

And now I find an answer, though it may not be the best one, it should work. I just overwrited the "create" method in "ModelSerializer". step1: copy the "create" method from "ModelSerializer" to your own serializers file step2: change the sentence "instance = ModelClass._default_manager.create(**validated_data)" into "instance = ModelClass._default_manager.create_user(**validated_data)".enter image description here step3: It worked![enter image description here]4 [enter image description here]5

Recipience answered 15/3, 2019 at 13:18 Comment(0)
M
3

I hope this helps for those using TokenAuthentication (not JWT), django-allauth and dj-rest-auth and getting the same error.

This answer from another similar question worked for me.

I just needed to add these Authentication Backends on settings.py:

AUTHENTICATION_BACKENDS = (
   "django.contrib.auth.backends.ModelBackend",
   "allauth.account.auth_backends.AuthenticationBackend"
)
Mabuse answered 22/6, 2021 at 9:23 Comment(0)
K
1

For me, I created the user with password 1234.

In the user admin panel I saw the below message

Password: Invalid password format or unknown hashing algorithm.

After updating the password with django password restrictions (minimum 8 characters and some others) I got the Token in resposne.

Kudu answered 7/6, 2020 at 8:44 Comment(0)
C
1

I got the same issue, I'm using Django 4.1. How I resolved:

  1. If you're creating a superuser provide a strong password. Sometimes it does not provide the error on a weak password which happened to me and then won't generate the token.
  2. If you are creating a user through code make sure to store the password as a hash.
  3. Add the following class in setting.py installed_apps=[ 'rest_framework.authtoken',]

    Now, give it a try!
Confetti answered 14/8, 2022 at 14:7 Comment(0)
M
0

the pasword is not correct

>>> nameko.Platform.Auth({'username': 'user', 'password': 'pass'})
[{'token': 'eefd5c0f747e121b9cb9986290f66b3c1089669d'}, 2
Melamie answered 17/11, 2020 at 19:39 Comment(0)
K
0

There can be several causes but IMHO the easiest way to clarify this, is to activate the logs in the settings file (with "level": "DEBUG") and to look at the generated SQL selection query by "api-token-auth"

for instance my personal jumped out in reading this request :

SELECT 
    profileapp_customuser.id, profileapp_customuser.password,
    profileapp_customuser.last_login, profileapp_customuser.is_superuser,
    [...]
    profileapp_customuser.email FROM profileapp_customuser
WHERE
    **profileapp_customuser.email = 'username_test3**' LIMIT 21;

In fact my custom model was inoperate cause my user unique id was no more username but email.

Karl answered 2/3, 2021 at 13:49 Comment(0)
R
0

In my cases, I was using username and password for authentication. But the django authenticte method by was expecting email value against username key becuase of the following customized code in the project as it was already existing developed by someone else

class User(AbstractUser):
    .....
    USERNAME_FIELD = 'email'

So I provided that against username to make it functional.

See the screenshots for the reference

Using Username value

enter image description here

Using Email value

enter image description here

Note: it's because Django filter the username value against the field lookup as per mentioned USERNAME_FIELD value see the reference of the code below

https://github.com/django/django/blob/61d5e57353bb811df7b5457a1856baee31299429/django/contrib/auth/backends.py#L42

user = UserModel._default_manager.get_by_natural_key(username)

Recurved answered 29/3, 2021 at 8:44 Comment(0)
T
0

The solution to your problem is to back up authentication.

To login with rest_framework.authtoken, the login fields are username and password.

But in django jwt changed this field to USERNAME_FIELD.

You need to write a new Auth Backend and replace username with USERNAME_FIELD in the authentication function parameter.

Teador answered 4/10, 2022 at 7:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.