Noble Obioma
Posted on March 9, 2020
In this article, we'll be adding user authentication to an already existing REST API. This is a continuation of a previous article where we built a simple Bookstore Django REST API with just one endpoint that sends a response {"message": "Welcome to the BookStore!"}
.
Want to Create a simple REST API with Django?
At the end of this article,
- User can register
- User can log in
- TokenBased Authentication
- User can Logout
Let's get started 😀
First, change directory into the project and spin up our environment:
$ cd bookstore
$ pipenv shell
Now, let's add some packages to our environment that will handle our authentication:
$ pipenv install django-rest-auth django-allauth
We've added some new packages, let's make our Django app aware of these authentication packages and add some functionalities too. To do this,
# ./bookstore_app/settings.py
...
INSTALLED_APPS = [
...
'rest_framework.authtoken',
'rest_auth',
'django.contrib.sites',
'allauth',
'allauth.account',
'rest_auth.registration',
]
Because Django tries to send an email e.g when a user creates an email account, we need to add a little config EMAIL_BACKEND
and SITE_ID
to the settings.py
file. This prints the email to be sent to the console.
# ./bookstore_app/settings.py
...
INSTALLED_APPS = [
...
]
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
SITE_ID = 1
MIDDLEWARE = [
...
]
...
Next, we'll add the URLs from the rest_auth
package to the project's urls.py
file. This gives us access to a host of auth functionalities.
- User Registration - registration/
- User Login - login/
- User Logout - logout/
- User Details - user/
- Change Password - password/change/
- Password Reset - password/reset/
- Confirm Password Reset - password/reset/confirm/
# ./bookstore_app/urls.py
urlpatterns = [
...
path('', include('rest_auth.urls')),
path('registration/', include('rest_auth.registration.urls')),
]
After adding the URLs, let's now set some Authentication Scheme
and
Permission Policies
. What file are we going to be setting these?? 🤔
NICE!!!! That will be the settings.py
file. Thank you for thinking about it for me. 😊
# ./bookstore_app/settings.py
...
REST_FRAMEWORK = {
# Authentication Scheme
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
# Permission Policies
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
Now, let's run our migrations:
$ python manage.py migrate
Let's add some restrictions to the welcome
viewset in the views.py
file so that unauthorized users would not have access.
# ./bookstore_app/api/views.py
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
@api_view(["GET"])
@csrf_exempt
@permission_classes([IsAuthenticated])
def welcome(request):
content = {"message": "Welcome to the BookStore!"}
return JsonResponse(content)
Finally, the restriction is set and an unauthenticated user cannot have access.
Now, let's test our endpoints. We'll create a user, log in and access the welcome
endpoint. You can use Postman to test with the same JSON properties, but I'll be using curl.
Registration
> Request
$ curl -X POST -H "Content-Type: application/json" -d '{"username":"testuser", "password1":"testpassword", "password2":"testpassword"}' localhost:8000/registration/
> Response:
{"key":"1565c60a136420bc733b10c4a165e07698014acb"}
Creating a user and Logging in returns a token that can be used to uniquely identify a user so we'll skip login and use the token to access the welcome endpoint that we added the restriction to.
Welcome endpoint with Token
> Request
$ curl -X GET -H 'Authorization: Token 1565c60a136420bc733b10c4a165e07698014acb' localhost:8000/api/welcome
> Response
{"message": "Welcome AH_Bookstore App!"}
Welcome endpoint without Token
> Request
$ curl -X GET -H '' localhost:8000/api/welcome
> Response
{"detail":"Authentication credentials were not provided."}
Finally, our authentication works fine. Next, we'll be adding CRUD functionality to our app and creating some models.
Thank you for reading. 😊
Posted on March 9, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
August 31, 2023
August 26, 2023