Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django rest framework: Obtain auth token using email instead username

I'm working on a project to enable the django rest framework authentication for mobile devices. I'm using the default token authentication for get the user token from a post request sending username and password.

curl --data "username=username&password=password" http://127.0.0.1:8000/api/api-token-auth/

(api/api-token-auth/ is the url configured with the obtain_auth_token view)

urlpatterns = [
    url(r'^api/api-token-auth/', obtain_auth_token),
    url(r'^', include(router.urls)),
]

and the response is the user token.

{"token":"c8a8777aca969ea3a164967ec3bb341a3495d234"}

I need to obtain the user token auth using email-password on the post instead username-password, or both. I was reading the documentation of custom authentication http://www.django-rest-framework.org/api-guide/authentication/#custom-authentication... but really, isn't very clear to me. It's very helpful to me... thanks :).

like image 886
Andrés Quiroga Avatar asked Jan 21 '15 01:01

Andrés Quiroga


People also ask

How do I authenticate an email in Django?

Email authentication for Django 3.x For using email/username and password for authentication instead of the default username and password authentication, we need to override two methods of ModelBackend class: authenticate() and get_user():

What is Obtain_auth_token?

The obtain_auth_token view will return a JSON response when valid username and password fields are POSTed to the view using form data or JSON: { 'token' : '9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b' }


1 Answers

Ok,I found a way for get the auth token using email or username... This is the serializer:

class AuthCustomTokenSerializer(serializers.Serializer):
    email_or_username = serializers.CharField()
    password = serializers.CharField()

    def validate(self, attrs):
        email_or_username = attrs.get('email_or_username')
        password = attrs.get('password')

        if email_or_username and password:
            # Check if user sent email
            if validateEmail(email_or_username):
                user_request = get_object_or_404(
                    User,
                    email=email_or_username,
                )

                email_or_username = user_request.username

            user = authenticate(username=email_or_username, password=password)

            if user:
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise exceptions.ValidationError(msg)
            else:
                msg = _('Unable to log in with provided credentials.')
                raise exceptions.ValidationError(msg)
        else:
            msg = _('Must include "email or username" and "password"')
            raise exceptions.ValidationError(msg)

        attrs['user'] = user
        return attrs

In the email_or_username field, the user can send the email or the username, and using the function validateEmail(), we can check if the user is trying to login using email or username. Then, we can make the query for get the user instance if is valid, and authenticate it.

This is the view.

class ObtainAuthToken(APIView):
    throttle_classes = ()
    permission_classes = ()
    parser_classes = (
        parsers.FormParser,
        parsers.MultiPartParser,
        parsers.JSONParser,
    )

    renderer_classes = (renderers.JSONRenderer,)

    def post(self, request):
        serializer = AuthCustomTokenSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data['user']
        token, created = Token.objects.get_or_create(user=user)

        content = {
            'token': unicode(token.key),
        }

        return Response(content)

and then:

curl --data "email_or_username=emailorusername&password=password" http://127.0.0.1:8000/api/my-api-token-auth/.

It's ready.

like image 129
Andrés Quiroga Avatar answered Sep 23 '22 01:09

Andrés Quiroga