Django under the hood — Login

Sergio Daniel Cortez Chavez
4 min readNov 27, 2021
Photo by John Barkiple on Unsplash

Django under the hood is a series of posts that try to delve into the internal mechanisms of Django and explain the origin of its design.

In this chapter, we are going to delve into the design login mechanism, what Django checks, and how it does it.

View

The entry point for de login in own program is the view. The view is part of the MVT (Model, View, Template) that uses Django by default, this component defines the logic, and connects the rendering part (template) with the persisted one (model).

Django login mechanism defines a LoginView component as a children class of SuccessURLAllowedHostsMixin and FormView.

The first parent class SuccessURLAllowedHostsMixin is a mixin that defines a get_success_url_allowed_hosts method, this method is used to verify that the redirect URL is “allowed”, but what this means?

When you have a website with authenticated and not authenticated pages, you need to protect the authenticated parts with some mechanism that does not allow anonymous users to enter. Django gives some tools for these tasks, LoginRequiredMixin is one alternative for the views based in classes, and login_required is the contra part for view functions. These tools define a constraint for visiting a view, the constraint is that if the user is not authenticated, the user must be redirected to the login view with a parameter by default named next.

The next parameter is a convention followed in Django, that gives more information about the source of the user. One example, if you have an endpoint named dashboard that is only for authenticated users, but the user has an expired session and intent to visit this page, the page must force the user for authenticating and ideally redirect to the dashboard when the process finish the process. The next parameter defines where to redirect the user after the login process is finished, in this case, the dashboard page.

But…

Why does Django uses the method get_success_url_allowed_hosts in this process?. Because anyone person that has known of this feature can build a special path like this https://www.mywebsite.com/login?next=https://www.malwaresite.com.

This means that the user is going to visit your website, login in, and redirect to a malware website, that can be a clon of your web page and going to ask your credentials one more time (like you give incorrect credentials in the first intent in the original website).

How does Django avoid this?

Django checks that the next parameter has a URL that is part of the return value of the get_success_url_allowed_hosts method, which by default only contains the host of the server. For this task, Django checks the scheme and domain, and force that the twice parts must be matched with the host, in other words, is not possible to make a downgrade to the HTTP protocol or make an open redirect.

What more do?

Also, Django defines some more restrictions in the view, especially in the dispatch method of the LoginView class.

Dispatch method of LoginView class

The method_decorator is a utility given by Django for reuse decorator designed for functions, in a class method. In this case, is defined in the dispatch method because is going to apply to all requests that process the view.

The decorators used are:

  • sensitive_post_parameters. Indicate which variables used in the decorated function are sensitive so that those variables can later be treated specially, for example by hiding them when logging unhandled exceptions. In this case, mark all the post parameters as sensitive data.
  • csrf_protect. Decorator that protects of CsrfViewMiddleware to a view.
  • never_cache. This decorator adds a Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private header to a response to indicate that a page should never be cached.

That’s all?

In addition, Django defines an AuthenticationForm that has two fields.

  • Username
  • Password

This form makes two principal things:

  • Try to authenticate the user with the credentials (username, password). The process is done by the authenticate function. This function iterate over the authentication backends defined in the settings file, if someone can authenticate the user, the function returns a User object in another case returns None.
  • If the authentication is successful, the form checks if the user is active, in other words user.is_active must be true.

And that’s all, Django is an amazing piece of software, full of details in its implementation and good practices. This is all for this, post, I hope the content has been to your liking, see you in the next installment of the series.

--

--