Authentication System Django and React
Authentication System Django and React
class User(AbstractUser):
username = models.CharField(max_length=100)
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
def profile(self):
profile = Profile.objects.get(user=self)
● Automatically create profile for user after sign up using django signals
from django.db.models.signals import post_save
post_save.connect(create_user_profile, sender=User)
post_save.connect(save_user_profile, sender=User)
class ProfileAdmin(admin.ModelAdmin):
list_display = ['user', 'wallet', 'verified']
● In the settings.py add some configuration codes
● First, add the default authentication classes
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
● Also Add the simple jwt configurations
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
'REFRESH_TOKEN_LIFETIME': timedelta(days=50),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE':
'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
● Add the cors origin to allow external application like react access out api
CORS_ALLOW_ALL_ORIGINS = True
urlpatterns = [
path('token/refresh/', TokenRefreshView.as_view(),
name='token_refresh'),
]
class RegisterView(generics.CreateAPIView):
queryset = User.objects.all()
permission_classes = (AllowAny,)
serializer_class = RegisterSerializer
@api_view(['GET'])
def getRoutes(request):
routes = [
'/api/token/',
'/api/register/',
'/api/token/refresh/'
]
return Response(routes)
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
fields = ['user', 'full_name', 'bio', 'image',
‘verified]
● Create a function that will run when /api/test/ hits. The function will return a
response only if the user is authenticated, and it is a get or a post request.
● If you also want to try testing your API on Postman, then click on Authorization,
select type Bearer token. Now paste the latest access token of the user.
SECTION 2 - CREATING THE CLIENT USING REACT
We have to store the user on frontend & user state null or defined must be
accessible across the entire application. So, basically we need a store. If
we think of a store, Redux comes to our mind, right!. Let's make this
happen without Redux. Let's use React hook useContext
● Create a folder in src named context & create a file named AuthContext inside it.
database (credentials are valid), the user is logged in. Tokens (access & refresh)
are stored in local storage, registerUser — Requires username, password1,
password2. This function registers the user in the database. Unique username,
password match checks are done on the backend. If the registration request is
successful, then the user is redirected to a login page. logoutUser — Simply logs
the user out & clears the local storage. Whenever authTokens& state of loading is
changed. User state is changed (useEffectis causing this change). jwt_decode just
decodes an access token. If you want to see what jwt_decode outputs, go to
https://jwt.io/ & paste your access & see the decoded output, same thing
will be done here.
Problem: Access token lifespan is usually very less. So the user’s token will be
valid for a very small amount of time, and then it will expire, and the user will
not be able to access all the private routes of the application.
Approach: To solve this problem, we need a way such that we can intercept the
request before it is sent to the server. We intercept the request, we see if the
token is valid or not, if not valid we will request for a new token via refresh
token, we will get new access token, and we will use that for the API request to
the private route, and if the token valid, we use the same token to send request
to the private route.
Implementation: We can solve this problem using the axios library. axios has got
interceptors. axios will basically intercept all the requests. It will run interceptors first
and then the actual request to the server. So we have to use axios when you are
calling a private API. Also, we have to update the state of our application if we
get a new access token. So we can use React Custom Hook.
● Create folder named utils inside src folder & create file inside utils named useAxios.js.
All this code does is that it checks whether the user is present or not. If the user
is present, then it will pass all the props to the child component and that route
will be rendered. Otherwise, it will redirect to the login page.
The hard part is all over, now we have to use that part in the application. We
have to create routes (pages) & components.