Change Expiration Dates for access and refresh tokens in Django JWT

To change the expiration dates for access and refresh tokens when using Django Simple JWT, you can configure the settings in your Django project’s settings file (settings.py). Here’s how you can do it:

  1. Install Simple JWT (if not already installed):
    pip install djangorestframework-simplejwt
    
  2. Update settings.py to include Simple JWT settings:
    from datetime import timedelta
    
    SIMPLE_JWT = {
        'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),  # Change this to your desired lifetime
        'REFRESH_TOKEN_LIFETIME': timedelta(days=1),  # Change this to your desired lifetime
        'ROTATE_REFRESH_TOKENS': False,
        'BLACKLIST_AFTER_ROTATION': True,
        'UPDATE_LAST_LOGIN': False,
    
        'ALGORITHM': 'HS256',
        'SIGNING_KEY': SECRET_KEY,
        'VERIFYING_KEY': None,
        'AUDIENCE': None,
        'ISSUER': None,
    
        'AUTH_HEADER_TYPES': ('Bearer',),
        'USER_ID_FIELD': 'id',
        'USER_ID_CLAIM': 'user_id',
        'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
        'TOKEN_TYPE_CLAIM': 'token_type',
    
        'JTI_CLAIM': 'jti',
    
        'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
        'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
        'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
    }
    
  3. Update the REST_FRAMEWORK settings to use Simple JWT as the authentication class:
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework_simplejwt.authentication.JWTAuthentication',
        ),
    }
    

Example

If you want to set the access token to expire in 15 minutes and the refresh token to expire in 7 days, you would update your settings.py as follows:

from datetime import timedelta

SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
    'ROTATE_REFRESH_TOKENS': False,
    'BLACKLIST_AFTER_ROTATION': True,
    'UPDATE_LAST_LOGIN': False,

    'ALGORITHM': 'HS256',
    'SIGNING_KEY': SECRET_KEY,
    'VERIFYING_KEY': None,
    'AUDIENCE': None,
    'ISSUER': None,

    'AUTH_HEADER_TYPES': ('Bearer',),
    'USER_ID_FIELD': 'id',
    'USER_ID_CLAIM': 'user_id',
    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
    'TOKEN_TYPE_CLAIM': 'token_type',

    'JTI_CLAIM': 'jti',

    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
    'SLIDING_TOKEN_LIFETIME': timedelta(minutes=15),
    'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=7),
}

These settings will ensure that your access tokens expire after 15 minutes and refresh tokens expire after 7 days. Adjust the timedelta values as needed for your application’s requirements.

Add a custom claim to the JWT in Django

Adding a custom claim to the JSON Web Tokens (JWT) in Django using the django-simple-jwt library involves extending the token creation process to include additional information. Here’s how you can achieve this:

  1. Install the necessary libraries: Make sure you have djangorestframework and djangorestframework-simplejwt installed.
    pip install djangorestframework djangorestframework-simplejwt
    
  2. Update your Django settings: Configure django-simple-jwt in your settings.py file.
    INSTALLED_APPS = [
        ...
        'rest_framework',
        'rest_framework_simplejwt',
    ]
    
    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework_simplejwt.authentication.JWTAuthentication',
        ),
    }
    
  3. Create a custom claims serializer: Extend the TokenObtainPairSerializer to include your custom claim.
    from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    
    class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    
        def get_token(self, user):
            token = super().get_token(user)
    
            # Add custom claims
            token['custom_claim'] = 'custom_value'
            
            # Example: Add user's email to the token
            token['email'] = user.email
    
            return token
    
  4. Create a custom view: Use the custom serializer in your view.
    from rest_framework_simplejwt.views import TokenObtainPairView
    from .serializers import MyTokenObtainPairSerializer
    
    class MyTokenObtainPairView(TokenObtainPairView):
        serializer_class = MyTokenObtainPairSerializer
    
  5. Update your URLs: Include the custom view in your URL configuration.
    from django.urls import path
    from .views import MyTokenObtainPairView
    from rest_framework_simplejwt.views import TokenRefreshView
    
    urlpatterns = [
        path('api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),
        path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    ]
    
  6. Test your custom claim: Now when you obtain a token, it should include your custom claim.

Implementing JWT (JSON Web Token) authentication in Django

Step 1: Install Necessary Packages

First, you need to install the required packages. For JWT authentication in Django, you can use the djangorestframework-simplejwt package.

pip install djangorestframework djangorestframework-simplejwt

Step 2: Configure Django Settings

Add rest_framework and rest_framework_simplejwt to your INSTALLED_APPS in settings.py.

INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework_simplejwt',
    ...
]

Next, configure the REST framework to use JWT for authentication:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

Step 3: Set Up URLs

In your urls.py, include the views for obtaining and refreshing tokens.

from django.urls import path
from rest_framework_simplejwt.views import (
    TokenObtainPairView,
    TokenRefreshView,
)

urlpatterns = [
    ...
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    ...
]

Step 4: Create Views and Protect Endpoints

Create views and protect your endpoints using the @api_view decorator and the permission_classes attribute.

from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@api_view(['GET'])
@permission_classes([IsAuthenticated])
def protected_view(request):
    return Response({'message': 'This is a protected view'})

Step 5: Testing

To test your JWT implementation, you can use tools like Postman or CURL to interact with your API. First, obtain a token by making a POST request to /api/token/ with your username and password.

curl -X POST http://localhost:8000/api/token/ -d "username=yourusername&password=yourpassword"

This will return a response containing the access and refresh tokens. Use the access token to access protected endpoints by including it in the Authorization header.

curl -H "Authorization: Bearer <your_access_token>" http://localhost:8000/protected-endpoint/

Example Project Structure

Here is a basic project structure for reference:

myproject/
    manage.py
    myproject/
        __init__.py
        settings.py
        urls.py
        wsgi.py
    myapp/
        __init__.py
        views.py
        models.py
        urls.py

Example settings.py

# settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'rest_framework_simplejwt',
    'myapp',
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ),
}

# Additional settings...

Example urls.py

# urls.py

from django.contrib import admin
from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from myapp.views import protected_view

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
    path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
    path('protected/', protected_view, name='protected_view'),
]

How It Works

The TokenObtainPairView and TokenRefreshView views provided by djangorestframework-simplejwt are already implemented and ready to use. You do not need to create additional views for these endpoints. They are automatically generated when you include them in your urls.py.

  • TokenObtainPairView: This view is used to obtain a pair of access and refresh tokens. You POST to this endpoint with user credentials (username and password) to get the tokens.
  • TokenRefreshView: This view is used to refresh the access token. You POST to this endpoint with a valid refresh token to get a new access token.

Example Requests

  1. Obtain Token Pair:
    curl -X POST http://127.0.0.1:8000/api/token/ -d "username=myusername&password=mypassword"
    

    This will return a JSON response with access and refresh tokens.

  2. Refresh Token:
    curl -X POST http://127.0.0.1:8000/api/token/refresh/ -d "refresh=your_refresh_token"
    

    This will return a new access token.

Example Response

  • TokenObtainPairView Response:
    {
        "refresh": "your_refresh_token",
        "access": "your_access_token"
    }
    
  • TokenRefreshView Response:
    {
        "access": "your_new_access_token"
    }
    

With these steps, you can seamlessly integrate JWT authentication into your Django application using djangorestframework-simplejwt. There is no need to create additional views for these token endpoints as they are provided out of the box by the package.

Decode JWT Token in ASP.NET Web API

var stream = "[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = jsonToken as JwtSecurityToken;

Or, without the cast:

var token = "[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(token);

I can get Claims using:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;

References
https://stackoverflow.com/questions/38340078/how-to-decode-jwt-token?utm_source=pocket_reader

Access JWT Token from Controller in ASP.NET Web API

[HttpGet]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public async Task<ActionResult<string>> Get()
{
    var token = await HttpContext.GetTokenAsync("access_token");
    return token;
}
var token = Request.Headers["Authorization"];
var token2 = await HttpContext.GetTokenAsync(JwtBearerDefaults.AuthenticationScheme, "access_token");

References
https://stackoverflow.com/questions/58887151/how-to-access-token-data-from-controller-method
https://stackoverflow.com/questions/52793488/jwt-cannot-be-retrieved-by-httpcontext-gettokenasync-in-net-core-2-1

JWT Token Creation, Authentication And Authorization In ASP.NET

Add Nuget Packages

Microsoft.AspNetCore.Authentication.JwtBearer
Microsoft.IdentityModel.Tokens
System.IdentityModel.Tokens.Jwt

Add setting in appsetting.json

"Jwt": {
    "Key": "ACDt1vR3lXToPQ1g3MyN", //Generate random String from https://www.random.org/strings
    "Issuer": "http://localhost:28747/", //Project Property-> Debug-> IIS-->App URL (you can local host url as well)
    "Audience": "http://localhost:28747/"
  },

Register JWT token for Authentication in Program.cs file

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
//JWT Authentication
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
    options.TokenValidationParameters = new TokenValidationParameters {
        ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
    };
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment()) {
    app.UseSwagger();
    app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

Create Models (UserLogin, UserModel and UserConstant)

namespace JWTLoginAuthenticationAuthorization.Models
{
    public class UserModel
    {
        public string Username { get; set; }
        public string Password { get; set; }
        public string Role { get; set; }
    }
}
namespace JWTLoginAuthenticationAuthorization.Models
{
    public class UserLogin
    {
        public string Username { get; set; }
        public string Password { get; set; }
    }
}
namespace JWTLoginAuthenticationAuthorization.Models
{
    // We are not taking data from data base so we get data from constant
    public class UserConstants
    {
        public static List<UserModel> Users = new()
            {
                    new UserModel(){ Username="naeem",Password="naeem_admin",Role="Admin"}
            };
    }
}

Create LoginAPI Controller (Authenticate user and generate token)

using JWTLoginAuthenticationAuthorization.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace JWTLoginAuthenticationAuthorization.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class LoginController : ControllerBase
    {
        private readonly IConfiguration _config;
        public LoginController(IConfiguration config)
        {
            _config = config;
        }

        [AllowAnonymous]
        [HttpPost]
        public ActionResult Login([FromBody] UserLogin userLogin)
        {
            var user = Authenticate(userLogin);
            if (user != null)
            {
                var token = GenerateToken(user);
                return Ok(token);
            }

            return NotFound("user not found");
        }

        // To generate token
        private string GenerateToken(UserModel user)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
            var claims = new[]
            {
                new Claim(ClaimTypes.NameIdentifier,user.Username),
                new Claim(ClaimTypes.Role,user.Role)
            };
            var token = new JwtSecurityToken(_config["Jwt:Issuer"],
                _config["Jwt:Audience"],
                claims,
                expires: DateTime.Now.AddMinutes(15),
                signingCredentials: credentials);


            return new JwtSecurityTokenHandler().WriteToken(token);

        }

        //To authenticate user
        private UserModel Authenticate(UserLogin userLogin)
        {
            var currentUser = UserConstants.Users.FirstOrDefault(x => x.Username.ToLower() ==
                userLogin.Username.ToLower() && x.Password == userLogin.Password);
            if (currentUser != null)
            {
                return currentUser;
            }
            return null;
        }
    }
}

Create User API Controller to authorize user role

namespace JWTLoginAuthenticationAuthorization.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class UserController : ControllerBase
    {
        //For admin Only
        [HttpGet]
        [Route("Admins")]
        [Authorize(Roles = "Admin")]
        public IActionResult AdminEndPoint()
        {
            var currentUser = GetCurrentUser();
            return Ok($"Hi you are an {currentUser.Role}");
        }
        private UserModel GetCurrentUser()
        {
            var identity = HttpContext.User.Identity as ClaimsIdentity;
            if (identity != null)
            {
                var userClaims = identity.Claims;
                return new UserModel
                {
                    Username = userClaims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier)?.Value,
                    Role = userClaims.FirstOrDefault(x => x.Type == ClaimTypes.Role)?.Value
                };
            }
            return null;
        }
    }
}

References
https://www.c-sharpcorner.com/article/jwt-token-creation-authentication-and-authorization-in-asp-net-core-6-0-with-po/
https://www.youtube.com/watch?v=UwruwHl3BlU
https://www.youtube.com/watch?v=6sMPvucWNRE