pythondjangodjango-rest-frameworkdjango-registrationdjango-oauth

Django OAuth Toolkit - Register a user


I've gone through the docs of Provider and Resource of Django OAuth Toolkit, but all I'm able to find is how to 'authenticate' a user, not how to register a user.

I'm able to set up everything on my machine, but not sure how to register a user using username & password. I know I'm missing something very subtle. How do I exactly register a user and get an access token in return to talk to my resource servers.

OR

Is it like that I've to first register the user using normal Django mechanism and then get the token of the same?


Solution

  • You can do what you are asking, and its your lucky day. I faced that problem when I first started working with django and oauth-toolkit.

    The following is my implementation using django-rest-framework. It will register the user, authenticate and return an oauth response.

    The thought is this: Using django models we save the new user using the proper serializers and models. In the same response, we create a new oauth token and return it to the user.

    serializers.py

    from rest_framework import serializers
    import models
    from django.utils.translation import gettext_lazy as _
    
    
    class RegisterSerializer(serializers.ModelSerializer):
        confirm_password = serializers.CharField()
    
        def validate(self, data):
            try:
                user = models.User.objects.filter(username=data.get('username'))
                if len(user) > 0:
                    raise serializers.ValidationError(_("Username already exists"))
            except models.User.DoesNotExist:
                pass
    
            if not data.get('password') or not data.get('confirm_password'):
                raise serializers.ValidationError(_("Empty Password"))
    
            if data.get('password') != data.get('confirm_password'):
                raise serializers.ValidationError(_("Mismatch"))
    
            return data
    
        class Meta:
            model = models.User
            fields = ('username', 'first_name', 'last_name', 'password', 'confirm_password', 'is_active')
            extra_kwargs = {'confirm_password': {'read_only': True}}
    

    view.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import status, permissions
    from oauth2_provider.settings import oauth2_settings
    from braces.views import CsrfExemptMixin
    from oauth2_provider.views.mixins import OAuthLibMixin
    
    import json
    import models
    import serializers
    
    from django.utils.decorators import method_decorator
    from django.http import HttpResponse
    from django.views.generic import View
    from django.views.decorators.debug import sensitive_post_parameters
    from django.utils.translation import gettext_lazy as _
    from django.db import transaction
    
    
    class UserRegister(CsrfExemptMixin, OAuthLibMixin, APIView):
        permission_classes = (permissions.AllowAny,)
    
        server_class = oauth2_settings.OAUTH2_SERVER_CLASS
        validator_class = oauth2_settings.OAUTH2_VALIDATOR_CLASS
        oauthlib_backend_class = oauth2_settings.OAUTH2_BACKEND_CLASS
    
        def post(self, request):
            if request.auth is None:
                data = request.data
                data = data.dict()
                serializer = serializers.RegisterSerializer(data=data)
                if serializer.is_valid():
                    try:
                        with transaction.atomic():
                            user = serializer.save()
    
                            url, headers, body, token_status = self.create_token_response(request)
                            if token_status != 200:
                                raise Exception(json.loads(body).get("error_description", ""))
    
                            return Response(json.loads(body), status=token_status)
                    except Exception as e:
                        return Response(data={"error": e.message}, status=status.HTTP_400_BAD_REQUEST)
                return Response(data=serializer.errors, status=status.HTTP_400_BAD_REQUEST)
            return Response(status=status.HTTP_403_FORBIDDEN) 
    

    urls.py

    rom django.conf.urls import url
    from oauth2_provider import views as oauth2_views
    
    import views
    
    urlpatterns = [
        url(r'^user/register/$', views.UserRegister.as_view()),
    ]