Reputation: 155
In my django-rest-application, I successfully register a user using post method. However, when I am trying to login or get the Authorization token for the user I am getting unauthorize error.
I am updating Token database using the post_save receiver as below.
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
Even when I am checking the model in the python shell I could successfully verify the user and token data by the following method.
from django.contrib.auth.models import User
from rest_framework.authtoken.models import Token
user = User.objects.get(username='user1')
token = Token.objects.get(user__username='user1')
The user.password and token data are verified and exist. And the user is active. However, I could not able to get the authorization token using curl method. Even I am not able login in the browser using the credentials.
Curl request
curl -X POST http://127.0.0.1:8000/api-token-auth/ -d "username=user1&password=password"
My settings.py file is given below.
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'c8x*pc%c$0-_k-wx5&u42m3k8k1jv!^o27&-*1w3u*v!ut3-5b'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.staticfiles',
# Rest Framework app
'rest_framework',
'rest_framework.authtoken',
# Internal Apps
'src.main',
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
ROOT_URLCONF = 'market_place.urls'
WSGI_APPLICATION = 'market_place.wsgi.application'
# Database
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
# Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/
STATIC_URL = '/static/'
Where am I missing?
Edits Error with the curl command
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
My User profile model is below:
class UserProfileModel(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_image = models.ImageField(upload_to="user_profile_pic", null=True)
class UserProfileRegisterView(generics.CreateAPIView):
serializer_class = UserProfileSerializer
permission_classes = [
permissions.AllowAny # Or anon users can't register
]
Upvotes: 0
Views: 1578
Reputation: 6296
If what you posted is all there is to your user creation view, then that is where the issue is. Passwords are not stored in their plain form in Django for obvious security reasons. Instead, their hash is stored and during login, the hash of the input password is compared to the stored hash.
From the code you posted, it seems the password is stored in it's plain form, therefore when the authenticator tries to compare the hash of the password sent and the stored input, they do not match.
You should use the user.set_password()
to ensure it is properly hashed and saved.
Here is what the create()
method of your UserProfileSerializer
should look like:
def create(self, validated_data):
password = validated_data.pop('password')
instance = super().create(validated_data)
instance.user.set_password(password)
instance.user.save()
return instance
Of course the details of how the profile and user are created are beyond the scope of this code as I don't know how your UserProfileSerializer
is defined, but this should give you the general idea.
If you are creating the user object at the same time as the profile, then the create method will look a little bit more complex. Check DRF's writable nested serializers for details on how to achieve that
Upvotes: 1