Role Based Access Control provides restrictive access to the users in a system based on their role in the organization. This feature makes the application access refined and secure.
Django provides authentication and authorization features out of the box. You can use these features to build a Role Based Access Control. Django user authentication has built-in models like User, Group, and Permission. This enables a granular access control required by the application.
Here Are Some Build-In Models
User Objects: Core of Authentication
This model stores the actual users in the system. It has basic fields like username, password, and email. You can extend this class to add more attributes that your application needs. Django user authentication handles the authentication through session and middlewares.
With every request, Django hooks a request object. Using this, you can get the details of the logged in user through request.user. To achieve role-based access control, use the request.user to authorize user requests to access the information.
Groups: Way of Categorizing Users
These are logical groups of users as required by the system. You can assign permissions and users to these groups. Django provides a basic view in the admin to create these groups and manage the permissions.
The group denotes the “role” of the user in the system. As an “admin”, you may belong to a group called “admin”. As a “support staff”, you would belong to a group called “support”.
Permission: Granular Access Control
The defined groups control access based on the permissions assigned to each group. Django allows you to add, edit, and change permissions for each model by default.
You can use these permissions in the admin view or in your application. For example, if you have a model like ‘Blog’.
pub_date = models.DateField()
headline = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey(User)
Each of these models is registered as ContentType in Django. All of the permissions that Django creates underclass Permission will have a reference to this specific ContentType. In this case, the following permissions will be created by default:
add_blog: Any User or group that has this permission can add a new blog. change_blog: Any user or group that has this permission can edit the blog. delete_blog: Any user or group that has this permission can delete a blog.
Adding Custom Permissions
Django default permissions are pretty basic. It may not always meet the requirements of your application. Django allows you to add custom permissions and use them as you need. With a model meta attribute, you can add new permissions:
permissions = (
("view_blog", "Can view the blog"),
("can_publish_blog", "Can publish a blog"),
These extra permissions are created along with default permissions when you run manage.py, migrate.
How To Use These Permissions
You can assign permission to a user or a group. For instance, you can give all the permissions to the group “admin”. You can ensure that the “support” group gets only the “change_blog” permission. This way only an admin user can add or delete a blog. You need Role-Based Access control for this kind of permission in your views, templates or APIs.
To check permissions in a view, use has a _perm method or a decorator. The User object provides the method has_perm(perm, obj=None), where perm is “.” and returns True if the user has the permission.
You can also use a decorator ‘permission_required(perm, login_url=None, raise_exception=False)’. This decorator also takes permission in the form “.”. Additionally, it also takes a login_url which can be used to pass the URL to your login/error page. If the user does not have the required permission, then he will be redirected to this URL.
from Django.contrib.auth.decorators import permission_required
@permission_required(‘blog.can_publish_blog’, login_url=’/signin/’) def publish_blog(request): …
If you have a class-based view then you can use “PermissionRequiredMixin”. You can pass one or many permissions to the permission_required parameter.
from Django.contrib.auth.mixins import PermissionRequiredMixin
class PublishBlog(PermissionRequiredMixin, View): permission_required =blog.can_publish_blog’
The permissions of the logged in user are stored in the template variable. You can check for a particular permission within an app.
Level of Access Control: Middleware Vs Decorator
A common question that plagues developers:“Where do I put my permission check, decorator or middleware?”. To answer this question, you just need to know if your access control rule is global or specific to a few views.
For instance, imagine you have two access control rules. The first states that all the users accessing the application must have “view_blog” permission. As per the second rule, only a user having a permission “can_publish_blog” can publish a blog.
In the second case, you can add the check as a decorator to the”publish_blog” view.
In case of former, you will put that check in your middleware as it applies to all your URLs. A user who does not have this permission cannot enter your application. Even if you add it as a decorator, the views are safe.
But adding the decorator to every view of your application would be cumbersome. If a new developer forgets to add the decorator to a view he wrote, the rule gets violated. Thus, you should check any permission that’s valid globally in the middleware.
Use Django user authentication to achieve complete role-based access control for your application. Go ahead and make the most of these features to make your software more secure.