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
- Checks each request for an access token in the session
- Verifies if the token is close to expiring (within 60 seconds)
- Silently refreshes the token using the refresh token
- Updates the session with new tokens and expiry time
- 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:
- Remove from
MIDDLEWARElist - Implement manual token refresh in your views
- 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
- Always include middleware - Provides seamless token management
- Place after SessionMiddleware - Required for session access
- Monitor logs - Watch for refresh failures
- Handle errors gracefully - Middleware handles failures automatically
Next Steps
- Learn about Utilities for accessing user data
- Explore Decorators for view protection
- Check Client API for manual token operations