saikat
saikat

Reputation: 155

Unable to get authorization token of a User

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

Answers (1)

Ken4scholars
Ken4scholars

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

Related Questions