Search code examples
pythondjangodjango-rest-frameworkdjango-authenticationgraphene-django

Unable to login with provided credentials


I am trying to automatically login the user when user signs up instead of redirecting to login page and then only login. However, I get an error

"errors": [
   "email",
   "Unable to login with provided credentials."
],

Here is what I have done:

def get_token(**user):
    data = {}
    if user.get('email') and user.get('password'):
        serializer = JSONWebTokenSerializer(data=user)
        if serializer.is_valid():
            token = serializer.object['token']
            user = serializer.object['user']
            data = {
                'user': user,
                'token': token
            }
            return data
        else:
            data = {
                'errors': serializer.errors
            }
            return data
    data = {
        'errors': 'Email or Password not provided'
    }
    return data

# creates the user but could not login
class Register(graphene.Mutation):
    '''
        Mutation to register a user
    '''
    class Arguments:
        email = graphene.String(required=True)
        password = graphene.String(required=True)
        password_repeat = graphene.String(required=True)

    success = graphene.Boolean()
    token = graphene.String()
    user = graphene.Field(UserQuery)
    errors = graphene.List(graphene.String)

    def mutate(self, info, email, password, password_repeat):
        if password == password_repeat:
            try:
                serializer = RegistrationSerializer(data={
                    'email': email,
                    'password': password,
                    'is_active': False
                })
                if serializer.is_valid():
                    user = serializer.save()
                    user_identity = get_token(email=user.email, password=user.password)
                    if not user_identity.get('errors'):
                        return Register(success=True, user=user_identity.get('user'), token=user_identity.get('token'))
                    else:
                        return Register(success=False, token=None, errors=['email', 'Unable to login with provided credentials.'])
            except Exception as e:
                errors = [e]
                return Register(success=False, errors=errors)
            errors = ["password", "Passwords don't match."]
            return Register(success=False, errors=errors)


# this works
class Login(graphene.Mutation):
    """
    Mutation to login a user
    """
    class Arguments:
        email = graphene.String(required=True)
        password = graphene.String(required=True)

    success = graphene.Boolean()
    errors = graphene.List(graphene.String)
    token = graphene.String()
    user = graphene.Field(UserQuery)

    def mutate(self, info, email, password):
        user_identity = get_token(email=email, password=password)
        if not user_identity.get('errors'):
            return Login(success=True, user=user_identity.get('user'), token=user_identity.get('token'))
        else:
            return Login(success=False, token=None, errors=['email', 'Unable to login with provided credentials.'])

If I directly login then it works but if I want to login when registering the user then it does not work so I am not able to pass the token when registering the user.

How can I automatically log in user when registering so I can pass the token?


Solution

  • One possible reason is that you are mutating your newly created user object as NOT ACTIVE.

    Here in your code, you can see you are defining the newly created user as inactive

    serializer = RegistrationSerializer(data={
        'email': email,
        'password': password,
        'is_active': False
    })
    

    is_active: False means the username and password might be valid but your account is disabled that is why you could not login during signup.

    Also if can see the source code of JSONWebTokenSerializer which you are relying on, in the validate function it's checking if user is inactive then throw an error

    this is from JSONWebTokenSerializer source code

    def validate(self, attrs):
            credentials = {
                self.username_field: attrs.get(self.username_field),
                'password': attrs.get('password')
            }
    
            if all(credentials.values()):
                user = authenticate(**credentials)
    
                if user:
                    if not user.is_active:
                        msg = _('User account is disabled.')
                        raise serializers.ValidationError(msg)
    
                    payload = jwt_payload_handler(user)
    
                    return {
                        'token': jwt_encode_handler(payload),
                        'user': user
                    }
                else:
                    msg = _('Unable to log in with provided credentials.')
                    raise serializers.ValidationError(msg)
            else:
                msg = _('Must include "{username_field}" and "password".')
                msg = msg.format(username_field=self.username_field)
                raise serializers.ValidationError(msg)
    

    so, one solution that i can see is turn the is_active flag as true or remove is_active: False and it will work.