Django OAuth Toolkit - Register a user
You have to create the user using normal Django mechanism (For example, you can add new users from admin or from django shell). However, to get access token, OAuth consumer should send a request to OAuth server where user will authorize it, once the server validates the authorization, it will return the access token.
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()),
]
You must register users separately.
django-oauth-toolkit is necessary if you're going to, e.g., support an Alexa Skill that requires "linking" accounts. Amazon needs a token representing an existing user on your system.
django-allauth makes it easy to provide signup via third parties, e.g. Amazon, Google or Slack. You might consider using it to streamline user registration, e.g. during Alexa account "linking".
For a toy Slack command integration I wrote, I added custom code to create new django users based on their unique Slack user id, skipping the OAuth "sign in with Slack" workflow entirely. Only once those django users exist can django-oauth-toolkit issue tokens for them.