django-jwt-auth is an application for authenticating users with jwt in Django.
Project description
d_jwt_auth
The d_jwt_auth
package is designed for user authentication via JSON Web Tokens (JWT).
Why use d_jwt_auth?
This package allows you to easily set up a secure JWT authentication system with useful features for your Django application.
Some key strengths of this package include:
-
Ability to use access token claims to retrieve user information instead of querying the database on each request. This feature has improved the performance of user retrieval threefold.
-
Token encryption
-
Professional and highly efficient token invalidation method
-
Ability to use caching, doubling the performance in token validation
-
Validation access token with ip address and device && validation refresh token with device name
-
**Limit the number of devices that use an account
Getting Started with d_jwt_auth
First, install the d_jwt_auth
package:
pip install d_jwt_auth
Add it to your INSTALLED_APPS
list:
INSTALLED_APPS = [
...
"d_jwt_auth",
]
Run the python manage.py migrate
command to create the user_auth
table.
Add JWTAuthentication in rest_framework Authentication Class:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'd_jwt_auth.authenticate.JWTAuthentication',
...
),
}
Creating Access Token and Refresh Token for a User
To create an access token and refresh token for a user, you can use the generate_token
function from the d_jwt_auth.token
module.
from d_jwt_auth.token import generate_token
class LoginView(APIView):
def post(self, request):
...
token = generate_token(request=request, user=user)
return Response(data=token, status=status.HTTP_200_OK)
The generate_token
function will generate a new access token and refresh token for the provided user.
Token Verification
To verify the validity of a token, you can use the verify_token
function from the d_jwt_auth.token
module.
from d_jwt_auth.token import verify_token
class VerifyTokenView(APIView):
def post(self, request):
...
if verify_token(request=request, raw_token=serializer.validated_data["token"]):
return Response(status=status.HTTP_200_OK)
return Response(status=status.HTTP_400_BAD_REQUEST)
The verify_token
function returns True
if the token is valid, and False
otherwise.
Refreshing Access Token
To refresh an access token, you can use the refresh_access_token
function from the d_jwt_auth.token
module.
from d_jwt_auth.token import refresh_access_token
from d_jwt_auth.exceptions import TokenError
class RefreshTokenView(APIView):
def post(self, request):
...
try:
access_token = refresh_access_token(
request=request, raw_refresh_token=serializer.refresh_token["refresh_token"])
except TokenError as err:
...
return Response(data={"access_token": access_token}, status=status.HTTP_200_OK)
The refresh_access_token
function takes the request object and the raw refresh token as arguments, and returns a new access token if the refresh token is valid. If there's an issue with the refresh token, it will raise a TokenError
exception.
Invalidating Tokens
To invalidate a token, use the update_user_auth_uuid
function.
When do we need to invalidate a token before its expiration date?
- When you create the user object using the access token. If the user information is updated, you should invalidate the user's access tokens.
- When a user logs out, you should invalidate their refresh_token and access_tokens.
Let's consider an example: Suppose you change the user's role from admin to a regular user. This user is currently logged in on two devices, and the user's access token is still valid on both devices. In this case, after updating the user's role, we should immediately invalidate all of the user's access_tokens.
In the d_jwt_auth package, discard all complicated and impractical methods for invalidating tokens! We use a much more practical approach.
We have a model called UserAuth
where we store the user_id
, token_type
, and a unique identifier uuid
.
Inside the token claims, we have a field called uuid_field
whose value is equal to the user_auth
value associated with that token and user.
During token validation, it is checked whether the uuid_field
value equals the uuid
value in the user_auth
associated with that user and token type.
When we need to invalidate an access or refresh token, all we need to do is change the uuid
value. In this case, the uuid
value in user_auth
will no longer match the uuid
value in the tokens associated with that user, and the tokens will be considered invalid.
Yes! We have replaced all the complicated methods with this practical approach.
Additionally, when the uuid
value is fetched from the database, it is cached with a key like user:{user_id}:access:uuid
, and subsequent requests retrieve it from the cache. So, it also performs well.
Example:
from rest_framework.views import APIView
from d_jwt_auth.services import update_user_auth_uuid
from d_jwt_auth.models import UserAuth
class UserUpdateView(APIView):
def post(self, request):
# Update user ...
update_user_auth_uuid(user_id=request.user.id, token_type=UserAuth.ACCESS_TOKEN)
# Well done!
class UserLogoutView(APIView):
def post(self, request):
# Update user ...
update_user_auth_uuid(user_id=request.user.id, token_type=UserAuth.ACCESS_TOKEN)
update_user_auth_uuid(user_id=request.user.id, token_type=UserAuth.REFRESH_TOKEN)
# Well done!
Important Note!
Below, it is explained how you can configure the system to obtain user information using the access_token, and avoid sending requests to the database every time you need to access request.user
.
It is recommended that you use this feature, but with caution!
If you intend to update the user information, make sure to first fetch the complete user data from the database, and then proceed with the update.
Example:
from django.contrib.auth import get_user_model
from rest_framework.views import APIView
from d_jwt_auth.services import update_user_auth_uuid
from d_jwt_auth.models import UserAuth
User = get_user_model()
class UserUpdateView(APIView):
def post(self, request):
# First, get the user
user = User.objects.get(id=request.user.id)
# Update the user
# ...
update_user_auth_uuid(user_id=request.user.id, token_type=UserAuth.ACCESS_TOKEN)
# Well done!
Therefore, make sure to fetch the complete user data from the database before making any changes to the user.
d_jwt_auth Settings
The d_jwt_auth
settings are configured in the settings.py
file of your Django project and include the following options:
JWT_AUTH_ACCESS_TOKEN_LIFETIME = timedelta(minutes=10)
The lifetime of the access token. The default is 10 minutes.
JWT_AUTH_REFRESH_TOKEN_LIFETIME = timedelta(days=30)
The lifetime of the refresh token. The default is 30 days.
JWT_AUTH_REFRESH_TOKEN_CLAIMS = {"id": 0, "ip_address": "", "device_name": ""}
This setting allows you to specify the claims you want to include in the refresh token. The id
field is for user identification, and the ip_address
and device_name
fields are for token validation. These fields are included by default, and you cannot remove them.
JWT_AUTH_ACCESS_TOKEN_CLAIMS = {"id": 0, "ip_address": "", "device_name": ""}
This setting allows you to specify the claims you want to include in the access token. Similar to the refresh token, the id
, ip_address
, and refresh_token
fields are included by default.
Note: If you want to create the user object using the access token claims and achieve better performance than retrieving user data from the database, you need to set the required fields from the user model exactly as they are defined in the model, in the access token claims. Finally, you need to set JWT_AUTH_GET_USER_BY_ACCESS_TOKEN
to True
.
For example:
JWT_AUTH_ACCESS_TOKEN_CLAIMS = {
"username": "",
"email": "",
"age": 0,
}
JWT_AUTH_GET_USER_BY_ACCESS_TOKEN = True
The d_jwt_auth
settings are configured in the settings.py
file of your Django project and include the following options:
JWT_AUTH_ACCESS_TOKEN_USER_FIELD_CLAIMS = { "id": 0, "username": "", "email": "", "age": 0, }
If you want to create the user object using the access token, you need to set this field along with the previous JWT_AUTH_ACCESS_TOKEN_CLAIMS
and JWT_AUTH_GET_USER_BY_ACCESS_TOKEN
fields. This field specifies the access token claims that correspond to the fields in your user model.
JWT_AUTH_ENCRYPT_KEY = b'32 bytes'
This field specifies the ENCRYPT_KEY
value. The tokens are encrypted and sent to the client.
If you don't set this field, a new ENCRYPT_KEY
is generated every time your Django app is run.
JWT_AUTH_CACHE_USING = False
This field allows you to specify whether to use caching for token validation or not. If you want to use caching, set it to True
. Using caching can improve performance by at least two times, and significantly fewer queries are made to the database to retrieve the UseAuth
object.
By default, this field is set to False
, but it is recommended to use caching.
JWT_AUTH_GET_USER_BY_ACCESS_TOKEN = False
Based on the previous explanations, if you set this field to True
, the user information will be retrieved from the access token. By using this feature, you no longer need to query the database every time to retrieve user information, and the response time for retrieving user information can be at least two times faster.
JWT_AUTH_DEVICE_LIMIT = True
Using this field, you can specify how many devices can use the same account at the same time. If you do not specify, no limit will be considered.
----------------------- ----------------------
For customizations and modifications, you have complete freedom, and you can easily personalize the package according to your project's needs.
I would appreciate it if you could support me by starring this project and contributing to its improvement.
I hope this package proves useful for you.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file d_jwt_auth-0.0.5.tar.gz
.
File metadata
- Download URL: d_jwt_auth-0.0.5.tar.gz
- Upload date:
- Size: 20.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.0 CPython/3.11.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 916b788d4296cf751e7ed0730e19525209f46670d7d40fc5a0cc8cd24fd1973e |
|
MD5 | 06d6bd5f79dc997bbcdb263371201b55 |
|
BLAKE2b-256 | d79d79fa63ac1e98c4fed34ad54378b538c5871277dc9adfb8c32cf3d7f0929f |