All notes
Auth

Intro

djangoProject doc.

Two items listed in your INSTALLED_APPS setting:

and these items in your MIDDLEWARE setting:

User objects

User objects are the core of the authentication system.

Only one class of user exists in Django’s authentication framework. 'superusers' or admin 'staff' users are just user objects with special attributes set, not different classes of user objects.

The primary attributes of the default user are:

Creating users


from django.contrib.auth.models import User
user = User.objects.create_user('john', '[email protected]', 'johnpassword')
# At this point, user is a User object that has already been saved to the database.

# You can continue to change its attributes if you want to change other fields.
user.last_name = 'Lennon'
user.save()

Creating superusers


python manage.py createsuperuser --username=joe [email protected]

Changing passwords

Django does not store raw (clear text) passwords on the user model, but only a hash.

Changing a user’s password will log out all their sessions.


manage.py changepassword *username*

from django.contrib.auth.models import User
u = User.objects.get(username='john')
u.set_password('new password')
u.save()

Authenticating users

authenticate() returns a User object if the credentials are valid for a backend. If the credentials aren’t valid for any backend or if a backend raises PermissionDenied, it returns None.


from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # A backend authenticated the credentials
else:
    # No backend authenticated the credentials

This is a low level way to authenticate a set of credentials; for example, it’s used by the RemoteUserMiddleware. Use login_required() decorator instead.

Authentication in Web requests

Django uses sessions and middleware to hook the authentication system into request objects.

These provide a request.user attribute on every request which represents the current user. If the current user has not logged in, this attribute will be set to an instance of AnonymousUser, otherwise it will be an instance of User.

You can tell them apart with is_authenticated, like so:


if request.user.is_authenticated:
    # Do something for authenticated users.
else:
    # Do something for anonymous users.

How to log a user in

If you have an authenticated user you want to attach to the current session - this is done with a login() function: login(request, user, backend=None)[source]

To log a user in, from a view, use login(). It takes an HttpRequest object and a User object. login() saves the user’s ID in the session, using Django’s session framework.

Note that any data set during the anonymous session is retained in the session after a user logs in.

This example shows how you might use both authenticate() and login():


from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(username=username, password=password)
    if user is not None:
        login(request, user)
        # Redirect to a success page.
    else:
        # Return an 'invalid login' error message.

The authentication backend

When a user logs in, the user’s ID and the backend that was used for authentication are saved in the user’s session. This allows the same authentication backend to fetch the user’s details on a future request. The authentication backend to save in the session is selected as follows:

  1. Use the value of the optional backend argument, if provided.
  2. Use the value of the user.backend attribute, if present. This allows pairing authenticate() and login(): authenticate() sets the user.backend attribute on the User object it returns.
  3. Use the backend in AUTHENTICATION_BACKENDS, if there is only one.
  4. Otherwise, raise an exception.

In cases 1 and 2, the value of the backend argument or the user.backend attribute should be a dotted import path string (like that found in AUTHENTICATION_BACKENDS), not the actual backend class.

How to log a user out

logout(request)[source]

Use django.contrib.auth.logout() within your view. It takes an HttpRequest object and has no return value. Example:


from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.

Note that logout() doesn’t throw any errors if the user wasn’t logged in.

When you call logout(), the session data for the current request is completely cleaned out. This is to prevent another person from using the same Web browser to log in and have access to the previous user’s session data. If you want to put anything into the session that will be available to the user immediately after logging out, do that after calling django.contrib.auth.logout().

Limiting access to logged-in users

The raw way


from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
    if not request.user.is_authenticated:
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # ...

#### or display an error message:

from django.shortcuts import render

def my_view(request):
    if not request.user.is_authenticated:
        return render(request, 'myapp/login_error.html')

login_required decorator

login_required(redirect_field_name='next', login_url=None)[source]

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

login_required() does the following:

By default, the path that the user should be redirected to upon successful authentication is stored in a query string parameter called "next". If you would prefer to use a different name for this parameter, login_required() takes an optional redirect_field_name parameter:


from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...

Note that if you provide a value to redirect_field_name, you will most likely need to customize your login template as well, since the template context variable which stores the redirect path will use the value of redirect_field_name as its key rather than "next" (the default).

login_required() also takes an optional login_url parameter. Example:


from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...

Note that if you don’t specify the login_url parameter, you’ll need to ensure that the settings.LOGIN_URL and your login view are properly associated. For example, using the defaults, add the following lines to your URLconf:


from django.contrib.auth import views as auth_views
url(r'^accounts/login/$', auth_views.login),

The settings.LOGIN_URL also accepts view function names and named URL patterns. This allows you to freely remap your login view within your URLconf without having to update the setting.

NOTE: The login_required decorator does NOT check the is_active flag on a user, but the default AUTHENTICATION_BACKENDS reject inactive users.

If you are writing custom views for Django’s admin (or need the same authorization check that the built-in views use), you may find the django.contrib.admin.views.decorators.staff_member_required() decorator a useful alternative to login_required().

The LoginRequired mixin

When using class-based views, you can achieve the same behavior as with login_required by using the LoginRequiredMixin. This mixin should be at the leftmost position in the inheritance list.

New in Django 1.9.

If a view is using this mixin, all requests by non-authenticated users will be redirected to the login page or shown an HTTP 403 Forbidden error, depending on the raise_exception parameter.

You can set any of the parameters of AccessMixin to customize the handling of unauthorized users:


from django.views import View
from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Permissions and Authorization

The Django admin site uses permissions as follows: add, change, delete.

Permissions can be set not only per type of object, but also per specific object instance. By using the has_add_permission(), has_change_permission() and has_delete_permission() methods provided by the ModelAdmin class, it is possible to customize permissions for different object instances of the same type.

User objects have two many-to-many fields: groups and user_permissions.


myuser.groups.set([group_list])
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions.set([permission_list])
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

Default permissions

When django.contrib.auth is listed in your INSTALLED_APPS setting, it will ensure that three default permissions – add, change and delete – are created for each Django model defined in one of your installed applications.

These permissions will be created when you run manage.py migrate. Afterward, it will create default permissions for new models each time you run manage.py migrate (the function that creates permissions is connected to the post_migrate signal).

Assuming you have an application with an app_label foo and a model named Bar, to test for basic permissions you should use:

add: user.has_perm('foo.add_bar')
change: user.has_perm('foo.change_bar')
delete: user.has_perm('foo.delete_bar')

The Permission model is rarely accessed directly.

Custom permissions

While custom permissions can be defined within a model’s Meta class, you can also create permissions directly.

For example, you can create the can_publish permission for a BlogPost model in myapp:


from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)

The permission can then be assigned to a User via its user_permissions attribute or to a Group via its permissions attribute.

Permission caching

The ModelBackend caches permissions on the User object after the first time they are fetched for a permissions check.

If you are adding permissions and checking them immediately afterward, the easiest solution is to re-fetch the User from the database. For example:


from django.contrib.auth.models import Permission, User
from django.shortcuts import get_object_or_404

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('myapp.change_bar')

    permission = Permission.objects.get(codename='change_bar')
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('myapp.change_bar')  # False

    # Request new instance of User
    # Be aware that user.refresh_from_db() won't clear the cache.
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('myapp.change_bar')  # True

Groups

django.contrib.auth.models.Group models are a generic way of categorizing users, or apply some other label to those users.

A user can belong to any number of groups.

A user in a group automatically has the permissions granted to that group. For example, if the group Site editors has the permission can_edit_home_page, any user in that group will have that permission.

Beyond permissions, groups are a convenient way to categorize users to give them some label, or extended functionality.

Reference

djangoProject docs: contrib.auth.

django.contrib.auth
    User model
        Fields
        Attributes
        Methods
        Manager methods
    AnonymousUser object
    Permission model
        Fields
        Methods
    Group model
        Fields
    Validators
    Login and logout signals
    Authentication backends
        Available authentication backends

FAQ

How to add fields to AUTH user table?

SO: extending the user model with custom fields in django.

The least painful and indeed Django-recommended way of doing this is through a OneToOneField(User) property.

If you wish to store information related to User, you can use a one-to-one relationship to a model containing the fields for additional information. This one-to-one model is often called a profile model, as it might store non-auth related information about a site user.

No template: registration/login.html

Yes, the file "registration/login.html" needs to be created anew. You can use "admin/login.html" instead:


from django.contrib.auth.views import login

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^accounts/login/$', login, {'template_name': 'admin/login.html'}),
]

SO: is there a built in login template in DJango.