Skip to main content
The E-commerce API uses JSON Web Tokens (JWT) for stateless authentication. This page covers token generation, refresh, and best practices.

Token Configuration

JWT settings are configured in config/settings.py:208-214:
SIMPLE_JWT = {
    'ACCESS_TOKEN_LIFETIME': timedelta(hours=1),
    'REFRESH_TOKEN_LIFETIME': timedelta(days=3),
    'UPDATE_LAST_LOGIN': True,
    "AUTH_HEADER_TYPES": ("Bearer",),
    "AUTH_HEADER_NAME": "HTTP_AUTHORIZATION"
}
Access tokens expire after 1 hour, while refresh tokens remain valid for 3 days.

Obtain Token Pair

Exchange user credentials for access and refresh tokens.

Endpoint

POST /auth/token/

Permission

  • AllowAny - No authentication required

Implementation

This endpoint uses TokenObtainPairView from rest_framework_simplejwt (see config/urls.py:36):
path("token/", TokenObtainPairView.as_view(), name="token_obtain_pair")

Request Body

email
string
required
Customer’s email address (used instead of username)
password
string
required
Customer’s password
The API uses email as the username field since USERNAME_FIELD = "email" in the Customer model.

Example Request

curl -X POST https://api.example.com/auth/token/ \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "SecurePass123!"
  }'

Success Response (200 OK)

access
string
JWT access token (valid for 1 hour)
refresh
string
JWT refresh token (valid for 3 days)
{
  "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjk4MzQwODAwLCJpYXQiOjE2OTgzMzcyMDAsImp0aSI6IjEyMzQ1Njc4OTAiLCJ1c2VyX2lkIjoxfQ.signature",
  "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY5ODU5NjQwMCwiaWF0IjoxNjk4MzM3MjAwLCJqdGkiOiIwOTg3NjU0MzIxIiwidXNlcl9pZCI6MX0.signature"
}

Error Responses

{
  "detail": "No active account found with the given credentials"
}
The email or password is incorrect, or the account is inactive.
{
  "email": [
    "This field is required."
  ]
}
Required fields are missing from the request.

Refresh Access Token

Obtain a new access token using a valid refresh token.

Endpoint

POST /auth/token/refresh/

Permission

  • AllowAny - No authentication required (but valid refresh token needed)

Implementation

This endpoint uses TokenRefreshView from rest_framework_simplejwt (see config/urls.py:37):
path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh")

Request Body

refresh
string
required
Valid refresh token obtained from /auth/token/ endpoint

Example Request

curl -X POST https://api.example.com/auth/token/refresh/ \
  -H "Content-Type: application/json" \
  -d '{
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
  }'

Success Response (200 OK)

access
string
New JWT access token (valid for 1 hour)
{
  "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjk4MzQ0NDAwLCJpYXQiOjE2OTgzNDA4MDAsImp0aSI6ImFiY2RlZmdoaWoiLCJ1c2VyX2lkIjoxfQ.signature"
}

Error Responses

{
  "detail": "Token is invalid or expired",
  "code": "token_not_valid"
}
The refresh token is invalid, expired, or has been revoked.

Using Access Tokens

Once you have an access token, include it in the Authorization header for all authenticated requests:
Authorization: Bearer <access_token>

Example Authenticated Request

curl https://api.example.com/api/v1/customers/1/ \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."

Logout Implementation

JWT tokens are stateless and cannot be invalidated server-side by default. To implement logout, simply delete the tokens from client storage.

Client-Side Logout

// Remove tokens from storage
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');

// Redirect to login page
window.location.href = '/login';

Token Best Practices

  • Web apps: Use httpOnly cookies or secure session storage
  • Mobile apps: Use secure keychain/keystore
  • Never store tokens in localStorage for production apps (vulnerable to XSS)
import requests
from datetime import datetime, timedelta

class APIClient:
    def __init__(self):
        self.access_token = None
        self.refresh_token = None
        self.token_expiry = None

    def refresh_access_token(self):
        response = requests.post(
            'https://api.example.com/auth/token/refresh/',
            json={'refresh': self.refresh_token}
        )
        data = response.json()
        self.access_token = data['access']
        self.token_expiry = datetime.now() + timedelta(hours=1)

    def make_request(self, url):
        # Refresh if token expired
        if datetime.now() >= self.token_expiry:
            self.refresh_access_token()

        return requests.get(
            url,
            headers={'Authorization': f'Bearer {self.access_token}'}
        )
Don’t wait for the access token to expire. Refresh it when you detect a 401 response or before expiry:
  • Refresh when access token has < 5 minutes remaining
  • Implement automatic retry logic for 401 responses
  • Keep refresh token secure and use it only for token refresh
The API automatically updates the user’s last_login field when obtaining tokens (configured via UPDATE_LAST_LOGIN: True in settings).
The API also includes standard Django REST Framework authentication URLs at /auth/ (see config/urls.py:35):
path("", include("rest_framework.urls"))
These provide:
  • /auth/login/ - Browser-based login (for browsable API)
  • /auth/logout/ - Browser-based logout
These endpoints are primarily for the browsable API interface and are not typically used in production client applications.

Next Steps

Permission Classes

Learn about permission classes and access control for protected resources

Build docs developers (and LLMs) love