Back
May 26, 2017

Tutorial: Django User Registration and Authentication

Most of web applications need to authenticate their users. Basic django login system uses username and password for authentication, but which user loves another password to remember? Thankfully, users may be authenticated with a well-known password, provided they have a social network account. Let’s start our django registration tutorial with a login via google example.

Django user registration via Google

Hereafter we’ll talk about the most recent Django version: 1.11. The right tool to do the job is python-social-auth. It’s got extensive documentation, however the reading flow isn’t very obvious. So, let’s see how to get a working configuration with a minimal effort.

Configuring python-social-auth

First of all add the lib to your pip requirements file and install into project virtual environment. The package name: social-auth-app-django. You’ll need to add the next configuration entries to the django config (usually settings.py):

INSTALLED_APPS = [
    # ...
    'social_django',
    # ...
]

AUTHENTICATION_BACKENDS = [
    'social_core.backends.google.GoogleOpenId',
    'social_core.backends.google.GoogleOAuth2',
]

SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '%some_digits_and_letters%.apps.googleusercontent.com'

SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = '%another_digits_and_letters%'

Nevermind the last two entries, they are dummies for now. In the next section we’ll see how to set them properly.

The last step of the minimal configuration is the root urls.py:

urlpatterns = [
    url('', include('social_django.urls', namespace='social')),
    # ...
]

For the complete set of options refer the lib docs for django framework. And now it’s time to make google ready to meet our users.

Configuring google side

You’ll need a google account to visit Google API Console. There create a project with suitable name and switch to “Credentials” section on the left.

First, fill basic info about your project in the “OAuth consent screen” subsection. After proceed to the “Credentials” subsection.

Now you should see the blue “Create credentials” button with a drop down. Choose “OAuth client ID”, as on the screenshot:

google-console.png

Select “Web application” for the “Application type” and type any suitable name of your web app.

The most important part is to configure “Authorized redirect URIs”. It’s the set of URIs where users will be redirected after the authentication. Set to http://127.0.0.1:8000/complete/google-oauth2/ to test locally.

Attention!

Despite the deploy is out of this tutorial scope, notice that “Cannot be a public IP address.” is not a joke. You have to get a public domain name of any level to make your app working on a server. Don’t forget to add http://your.domain.name.com/complete/google-oauth2/ here. You’ve been warned.

You should end up with a “client ID” which goes to SOCIAL_AUTH_GOOGLE_OAUTH2_KEYand “client secret” which goes to SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET.

However, our adventures at google console are not over. We have to specify which exactly google APIs will be accessible by our app. Go to the “Library” section, “Social APIs / Google+ API” and press blue “Enable” button on the top. That’s it. Congratulations! One may compare the simplicity of description with:

Basic views

The last thing left to see it all in action: django views. Some simple templates are assumed, if you wish them.

Add this to your root urls.py:

from django.contrib.auth.views import LogoutView, LoginView


urlpatterns = [
    # ...
    url(r'^$', views.index, name='index'),
    url(r'^login/$', LoginView.as_view(template_name='login.html'), name='login'),
    url(r'^logout/$', LogoutView.as_view(), name='logout'),
    # ...
]

Import views from any django-app of your project. Then add there the index view for main page, if it’s not there:

from django.contrib.auth.decorators import login_required
from django.http import HttpResponse

# ...

@login_required
def index(request):
    return HttpResponse('OK, Google!')

Notice the login_required decorator. Now our page is locked from anonymous visitors. They are redirected to the login page. Let’s specify its name in settings.py:

LOGIN_URL = 'login'
LOGIN_REDIRECT_URL = 'index'
LOGOUT_REDIRECT_URL = LOGIN_REDIRECT_URL

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    # ...
]

The good place to put this in is right before the password validators in default config to get all the auth stuff together.

Attentive reader will ask: “Hey, what about login.html template?”. This could be the simplest django login form ever:

Sign in with Google

The next GET-parameter trick is needed to redirect user back to the page that required to be logged in.

Now run your project locally and try to visit the default local address: http://127.0.0.1:8000/. You should be redirected to the login page with a single button “Sign in with Google”. Proceed with authentication and after you should be redirected back to the root URI and see what our protected index view returns. You haven’t even had to create a django registration form! Isn’t it great?

OK, Google! But what if your web app has its own RESTful API? How authentication can be implemented then? See the next section!

Django REST framework authentication

To be precise, here we talk about the third version of the framework.

First, let’s consider the simplest use case: when client-side of your web app sends ajax requests to the web app API. You’d be completely happy with the default DEFAULT_AUTHENTICATION_CLASSES setting.

'rest_framework.authentication.SessionAuthentication' is already here: logged in the web app == logged in the api. Nothing to configure!

The more complicated case is when you need to provide access to some external app, usually mobile or desktop one. Good approach here is to use token authentication. After setting this up as described in the DRF doc you’ll need to set HTTP header “Authorization” with value “Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b” for each request to the API from external app. Real token value denotes specific user in your django project.

There’s a way to obtain token from external app. You don’t need to build a django login form, but you’ll have to provide an endpoint receiving user credentials and returning respective token. Follow the instruction in the DRF docs to see how.

You might also want to consider using JWT and a DRF plugin for it. JWT is somewhat harder to setup, but it's more secure and flexible han basic token based authentication.

Django authentication in tests

Often we need to make requests by authenticated user. Naive approach could be to use test client login method. I’ve even met custom wrapper in the base class, something like:

def login_user(user):
    self.assertTrue(self.client.login(username=user.username, password=TEST_PASSWORD))

Bulletproof. Well, and time-wasting. Don’t do this. More efficient way: self.client.force_login(user)

Conclusion

Let’s recap what have we highlighted in django user registration and authentication:

  • Now you know how to register users with their google+ accounts, as straightforward as possible.
  • Authentication for RESTful API is needed? You’re armed and ready! Even to automatically generate tokens for external apps.
  • No more redundant authentication in tests, using credentials. Only forcing in tests. Only hardcore.

All of this is not emphasized too much in docs, is it? If you liked this article, stay tuned with our blog - even more enlightening articles are coming soon. Also feel free emailing me with any questions regarding software development or contact in any other way suitable for you. See ya!

Subscribe for the news and updates

More thoughts
Dec 22, 2024Technology
Python and the Point Rush in DeFi

This article demonstrates how to use Python to automate yield calculations in decentralized finance (DeFi), focusing on the Renzo and Pendle platforms. It guides readers through estimating potential rewards based on factors like token prices, liquidity, and reward distribution rules, emphasizing the importance of regular data updates and informed decision-making in DeFi investments.

Nov 27, 2024Technology
Stoicism At Work

This article explores how Stoic principles can be applied in the workplace to navigate stress, improve self-control, and focus on what truly matters, with practical examples from the author’s experience in software development.

Jul 13, 2022Technology
Prosemirror: Render node as react component

In this article I’m going to show how to declare custom prosemirror node, how to render it with toDom method and how improve that with custom NodeView using React component.

Jun 14, 2017Technology
How to Deploy a Django Application on Heroku?

In this article I'll show you how to deploy Django with Celery and Postgres to Heroku.

Mar 6, 2010Technology
Ajax form validation

There was a task to submit form with ajax, with server side validation of course. Obvious solution is to do validation and return json with erros. I didn't like idea of writing separate view for validation and then inserting errors in form html on client side. Especially since I already had a generic template for django form with errors display. In this article I'll describe how I solved the task.

Feb 18, 2010Technology
Business logic in models

In my recent project there was a lot of data business logic, so I had to organize this code somehow. In this article I'll describe a few hints on how to it.