Skip to content

Commit 91e3ce6

Browse files
committed
Added middleware to refresh access tokens
1 parent 80adc32 commit 91e3ce6

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

django_auth_adfs/backend.py

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import logging
2+
from datetime import datetime, timedelta
23

34
import jwt
4-
from django.contrib.auth import get_user_model
5+
from django.contrib.auth import get_user_model, logout
56
from django.contrib.auth.backends import ModelBackend
67
from django.contrib.auth.models import Group
78
from django.core.exceptions import (ImproperlyConfigured, ObjectDoesNotExist,
89
PermissionDenied)
10+
from requests import HTTPError
911

1012
from django_auth_adfs import signals
1113
from django_auth_adfs.config import provider_config, settings
@@ -398,10 +400,38 @@ def authenticate(self, request=None, authorization_code=None, **kwargs):
398400
provider_config.load_config()
399401

400402
adfs_response = self.exchange_auth_code(authorization_code, request)
401-
access_token = adfs_response["access_token"]
402-
user = self.process_access_token(access_token, adfs_response)
403+
user = self._process_adfs_response(request, adfs_response)
403404
return user
404405

406+
def _process_adfs_response(self, request, adfs_response):
407+
user = self.process_access_token(adfs_response['access_token'], adfs_response)
408+
request.session['adfs_access_token'] = adfs_response['access_token']
409+
expiry = datetime.now() + timedelta(seconds=adfs_response['expires_in'])
410+
request.session['adfs_token_expiry'] = expiry.isoformat()
411+
if 'refresh_token' in adfs_response:
412+
request.session['adfs_refresh_token'] = adfs_response['refresh_token']
413+
request.session.save()
414+
return user
415+
416+
def process_request(self, request):
417+
now = datetime.now() + settings.REFRESH_THRESHOLD
418+
expiry = datetime.fromisoformat(request.session['adfs_token_expiry'])
419+
if now > expiry:
420+
try:
421+
self._refresh_access_token(request, request.session['adfs_refresh_token'])
422+
except (PermissionDenied, HTTPError):
423+
logout(request)
424+
425+
def _refresh_access_token(self, request, refresh_token):
426+
provider_config.load_config()
427+
response = provider_config.session.post(
428+
provider_config.token_endpoint,
429+
data=f'grant_type=refresh_token&refresh_token={refresh_token}'
430+
)
431+
response.raise_for_status()
432+
adfs_response = response.json()
433+
self._process_adfs_response(request, adfs_response)
434+
405435

406436
class AdfsAccessTokenBackend(AdfsBaseBackend):
407437
"""

django_auth_adfs/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def __init__(self):
7272
self.USERNAME_CLAIM = "winaccountname"
7373
self.GUEST_USERNAME_CLAIM = None
7474
self.JWT_LEEWAY = 0
75+
self.REFRESH_THRESHOLD = timedelta(minutes=5)
7576
self.CUSTOM_FAILED_RESPONSE_VIEW = lambda request, error_message, status: render(
7677
request, 'django_auth_adfs/login_failed.html', {'error_message': error_message}, status=status
7778
)

django_auth_adfs/middleware.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
from re import compile
55

66
from django.conf import settings as django_settings
7+
from django.contrib import auth
78
from django.contrib.auth.views import redirect_to_login
89
from django.urls import reverse
910

11+
from django_auth_adfs.backend import AdfsAuthCodeBackend
1012
from django_auth_adfs.exceptions import MFARequired
1113
from django_auth_adfs.config import settings
1214

@@ -49,3 +51,17 @@ def __call__(self, request):
4951
return redirect_to_login('django_auth_adfs:login-force-mfa')
5052

5153
return self.get_response(request)
54+
55+
56+
def adfs_refresh_middleware(get_response):
57+
def middleware(request):
58+
try:
59+
backend_str = request.session[auth.BACKEND_SESSION_KEY]
60+
except KeyError:
61+
pass
62+
else:
63+
backend = auth.load_backend(backend_str)
64+
if isinstance(backend, AdfsAuthCodeBackend):
65+
backend.process_request(request)
66+
return get_response()
67+
return middleware

0 commit comments

Comments
 (0)