Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 220
PythonEnthusiast Avatar asked Feb 28 '18 14:02

PythonEnthusiast


4 Answers

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()),
]
like image 64
Gal Silberman Avatar answered Sep 25 '22 11:09

Gal Silberman


I'm registering user with regular django mechanism combined with django-oauth-toolkit's application client details (client id and client secret key).

I have separate UserRegisterApiView which is not restricted with token authentication but it checks for client id and client secret key while making post request to register a new user. In this way we are restricting register url access to only registered OAuth clients.

Here is the registration workflow:

  1. User registration request from React/Angular/View app with client_id and client_secret.
  2. Django will check if client_id and client_secret are valid if not respond 401 unauthorized.
  3. If valid and register user data is valid, register the user.
  4. On successful response redirect user to login page.
like image 42
Scorpionk Avatar answered Sep 23 '22 11:09

Scorpionk


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.

like image 32
Pandikunta Anand Reddy Avatar answered Sep 23 '22 11:09

Pandikunta Anand Reddy


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.

like image 24
David Chandler Avatar answered Sep 24 '22 11:09

David Chandler