Skip to main content

Middleware

Automatic token refresh middleware for seamless OAuth session management.

TokenRefreshMiddleware

Location: sva_oauth_client.middleware.TokenRefreshMiddleware

Purpose: Automatically refreshes access tokens before they expire, providing a seamless user experience without requiring re-authentication.

How It Works

  1. Checks each request for an access token in the session
  2. Verifies if the token is close to expiring (within 60 seconds)
  3. Silently refreshes the token using the refresh token
  4. Updates the session with new tokens and expiry time
  5. Handles refresh failures gracefully by logging out the user

Configuration

Simply add it to your MIDDLEWARE list (after SessionMiddleware):

# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', # Must be before TokenRefreshMiddleware
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
# ... your other middleware
'sva_oauth_client.middleware.TokenRefreshMiddleware', # Add this
]

Critical: The TokenRefreshMiddleware must come after SessionMiddleware since it requires access to the session.

Features

Automatic Token Refresh

The middleware automatically refreshes tokens before they expire:

  • Checks token expiry on every request
  • Refreshes if token expires within 60 seconds
  • Updates session with new tokens
  • Preserves "Remember Me" session settings

Silent Operation

Token refresh is transparent to the user:

  • No redirects or interruptions
  • No visible loading states
  • Seamless user experience

Error Handling

If token refresh fails:

  • User is automatically logged out
  • Session is cleared
  • User is redirected to logout redirect URL
  • Errors are logged for debugging

Token Expiry Detection

The middleware checks if the access token is close to expiring:

# Token expires within 60 seconds
if time_until_expiry <= 60:
# Refresh token

This ensures tokens are refreshed before they expire, preventing authentication failures.

Session Management

The middleware updates the session with new tokens:

# Update access token
request.session['sva_oauth_access_token'] = new_token_response['access_token']

# Update refresh token (if rotated)
if 'refresh_token' in new_token_response:
request.session['sva_oauth_refresh_token'] = new_token_response['refresh_token']

# Update data token (if provided)
if 'data_token' in new_token_response:
request.session['sva_oauth_data_token'] = new_token_response['data_token']

# Update expiry timestamp
request.session['sva_access_token_expiry'] = new_expiry_timestamp

Remember Me Support

The middleware preserves "Remember Me" session settings:

  • Doesn't reset session expiry
  • Only updates token expiry timestamp
  • Maintains long-lived sessions when "Remember Me" is enabled

Logging

The middleware logs important events:

# Token refresh initiated
logger.info("Access token expiring soon, attempting refresh...")

# Token refresh successful
logger.info("Token refreshed successfully. New expiry in X seconds")

# Token refresh failed
logger.error("Token refresh failed: {error}", exc_info=True)

# Forced logout
logger.warning("No refresh token available, forcing logout")

Performance Considerations

The middleware is optimized for performance:

  • Only runs for requests with tokens in session
  • Skips refresh check if token is still valid
  • Minimal overhead on each request
  • Efficient token expiry calculation

Disabling Middleware

If you need to disable automatic token refresh:

  1. Remove from MIDDLEWARE list
  2. Implement manual token refresh in your views
  3. Handle token expiration manually

Example: Manual Token Refresh

If you're not using the middleware, you can refresh tokens manually:

from sva_oauth_client.client import get_client_from_settings
from sva_oauth_client.client import SVATokenError

def my_view(request):
refresh_token = request.session.get('sva_oauth_refresh_token')

if refresh_token:
try:
client = get_client_from_settings()
new_tokens = client.refresh_access_token(refresh_token)

# Update session
request.session['sva_oauth_access_token'] = new_tokens['access_token']
# ... update other tokens
except SVATokenError:
# Refresh failed, logout user
clear_oauth_session(request.session)
return redirect('sva_oauth_client:login')

Best Practices

  1. Always include middleware - Provides seamless token management
  2. Place after SessionMiddleware - Required for session access
  3. Monitor logs - Watch for refresh failures
  4. Handle errors gracefully - Middleware handles failures automatically

Next Steps