0

Hi I'm trying to customize

jwt graphql Django default authentication

I need to achieve log in with username or email

normal Django we customized authentication backend.

mutation{
  tokenAuth(username:"myemail@email.com"
  password:"pass")
  {
    token
  }
}

Authenticate with username

mutation{
  tokenAuth(username:"myname"
  password:"pass")
  {
    token
  }
}

the normal username is working fine.

how I can authenticate the user by username or email in jwt graphql

I tried this link

https://django-graphql-jwt.domake.io/en/latest/customizing.html

I don't get any idea about that...

Does anyone have any idea about that??

prabhakaran7
  • 259
  • 4
  • 20

2 Answers2

0

You have to make the changes on the Model level not in JWT, JWT will follow, because JWT is only a presentation of what is going on behind the scenes.

Look at the link under here, maybe it will help you! :)

Multiple USERNAME_FIELD in django user model

mama
  • 2,046
  • 1
  • 7
  • 24
  • that doesn't help, since JWT's `token_auth` looks specifically at the `USERNAME_FIELD` Check it out here: https://github.com/flavors/django-graphql-jwt/blob/master/graphql_jwt/decorators.py – Jura Brazdil Oct 15 '20 at 09:32
  • I'm wrong, the token_auth then calls Django's `authenticate`, so if you override that in a way suggested in the link (the username arg accepts email as well) you're fine – Jura Brazdil Oct 15 '20 at 09:41
0

Disclaimer - mama's answer should work. Halfway through writting an answer I realised I'm wrong, but I still wanna show you what I wanted to suggest. It shows what JWT TokenAuth mutation does and a way to tap into that completely.

  1. change the inbuild Django authentication like mama's answer suggests
  2. rewrite graphql_jwt.decorators.token_auth to look at both fields, not just one
  3. write your own class for the TokenMutation that uses this decorator on it's mutate function

Something like so (untested):

def two_field_token_auth(f):
    @wraps(f)
    @setup_jwt_cookie
    @csrf_rotation
    @refresh_expiration
    def wrapper(cls, root, info, password, **kwargs):
        context = info.context
        context._jwt_token_auth = True
        username = kwargs.get('username')
        email = kwargs.get('email')

        user = your_auth_method(
            request=context,
            username=username,
            email=email,
            password=password,
        )
        if user is None:
            raise exceptions.JSONWebTokenError(
                _('Please enter valid credentials'),
            )

        if hasattr(context, 'user'):
            context.user = user

        result = f(cls, root, info, **kwargs)
        signals.token_issued.send(sender=cls, request=context, user=user)
        return maybe_thenable((context, user, result), on_token_auth_resolve)
    return wrapper

class TwoFieldJWTMutation(JSONWebTokenMutation):
    @classmethod
    @two_field_token_auth
    def mutate(cls, root, info, **kwargs):
        return cls.resolve(root, info, **kwargs)

All the necessary imports you can find here and here

Jura Brazdil
  • 970
  • 7
  • 15