You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2020/10/05 21:24:22 UTC

[airavata-django-portal] 02/04: AIRAVATA-3346 Add authz_token to request in auth backend

This is an automated email from the ASF dual-hosted git repository.

machristie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-django-portal.git

commit 561296d2533d9821b079aabeba11cd8be330a5b3
Author: Marcus Christie <ma...@apache.org>
AuthorDate: Mon Oct 5 14:06:44 2020 -0400

    AIRAVATA-3346 Add authz_token to request in auth backend
---
 django_airavata/apps/api/authentication.py |  9 ---------
 django_airavata/apps/auth/backends.py      | 27 ++++++++++++++++++++-------
 django_airavata/apps/auth/utils.py         |  4 +++-
 3 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/django_airavata/apps/api/authentication.py b/django_airavata/apps/api/authentication.py
index fd282ba..9e12b94 100644
--- a/django_airavata/apps/api/authentication.py
+++ b/django_airavata/apps/api/authentication.py
@@ -3,8 +3,6 @@ import logging
 from django.contrib.auth import authenticate
 from rest_framework import authentication, exceptions
 
-from django_airavata.apps.auth.utils import get_authz_token
-
 logger = logging.getLogger(__name__)
 
 
@@ -19,13 +17,6 @@ class OAuthAuthentication(authentication.BaseAuthentication):
                         "Token failed to authenticate")
                 _, token = request.META.get('HTTP_AUTHORIZATION').split()
 
-                # authz_token_middleware has already run, so must manually add
-                # the `request.authz_token` attribute
-
-                # Must pass user directly since `request.user` access will
-                # trigger this Authentication being called again, resulting in
-                # an infinite loop
-                request.authz_token = get_authz_token(request, user=user, access_token=token)
                 logger.debug(f"OAuthAuthentication authenticated user {user}")
                 return (user, token)
             except Exception as e:
diff --git a/django_airavata/apps/auth/backends.py b/django_airavata/apps/auth/backends.py
index 1c9591d..5bb832a 100644
--- a/django_airavata/apps/auth/backends.py
+++ b/django_airavata/apps/auth/backends.py
@@ -9,6 +9,8 @@ from django.views.decorators.debug import sensitive_variables
 from oauthlib.oauth2 import InvalidGrantError, LegacyApplicationClient
 from requests_oauthlib import OAuth2Session
 
+from django_airavata.apps.auth.utils import get_authz_token
+
 from . import utils
 
 logger = logging.getLogger(__name__)
@@ -28,22 +30,24 @@ class KeycloakBackend(object):
                      password=None,
                      refresh_token=None):
         try:
+            user = None
+            access_token = None
             if username and password:
                 token, userinfo = self._get_token_and_userinfo_password_flow(
                     username, password)
                 if token is None:  # login failed
                     return None
                 self._process_token(request, token)
-                return self._process_userinfo(request, userinfo)
+                user = self._process_userinfo(request, userinfo)
+                access_token = token['access_token']
             elif 'HTTP_AUTHORIZATION' in request.META:
                 bearer, token = request.META.get('HTTP_AUTHORIZATION').split()
                 if bearer != "Bearer":
                     raise Exception("Unexpected Authorization header")
                 # implicitly validate token by using it to get userinfo
                 userinfo = self._get_userinfo_from_token(request, token)
-                # Token should be added as a request attribute (request.auth)
-                # self._process_token(request, token)
-                return self._process_userinfo(request, userinfo)
+                user = self._process_userinfo(request, userinfo)
+                access_token = token
             # user is already logged in and can use refresh token
             elif request.user and not utils.is_refresh_token_expired(request):
                 logger.debug("Refreshing token...")
@@ -51,19 +55,28 @@ class KeycloakBackend(object):
                     self._get_token_and_userinfo_from_refresh_token(request)
                 self._process_token(request, token)
                 # user is already logged in
-                return request.user
+                user = request.user
+                access_token = token['access_token']
             elif refresh_token:
                 logger.debug("Refreshing supplied token...")
                 token, userinfo = \
                     self._get_token_and_userinfo_from_refresh_token(
                         request, refresh_token=refresh_token)
                 self._process_token(request, token)
-                return self._process_userinfo(request, userinfo)
+                user = self._process_userinfo(request, userinfo)
+                access_token = token['access_token']
             else:
                 token, userinfo = self._get_token_and_userinfo_redirect_flow(
                     request)
                 self._process_token(request, token)
-                return self._process_userinfo(request, userinfo)
+                user = self._process_userinfo(request, userinfo)
+                access_token = token['access_token']
+            # authz_token_middleware has already run, so must manually add
+            # the `request.authz_token` attribute
+            if user is not None:
+                request.authz_token = get_authz_token(
+                    request, user=user, access_token=access_token)
+            return user
         except Exception as e:
             logger.exception("login failed")
             return None
diff --git a/django_airavata/apps/auth/utils.py b/django_airavata/apps/auth/utils.py
index d350850..caf0088 100644
--- a/django_airavata/apps/auth/utils.py
+++ b/django_airavata/apps/auth/utils.py
@@ -17,7 +17,9 @@ from . import models
 
 def get_authz_token(request, user=None, access_token=None):
     """Construct AuthzToken instance from session; refresh token if needed."""
-    if not is_access_token_expired(request):
+    if access_token is not None:
+        return _create_authz_token(request, user=user, access_token=access_token)
+    elif not is_access_token_expired(request):
         return _create_authz_token(request, user=user, access_token=access_token)
     elif not is_refresh_token_expired(request):
         # Have backend reauthenticate the user with the refresh token