From 113dc850588fd97cfb46777f7e5608be06af364f Mon Sep 17 00:00:00 2001
From: Stefano Alberto Russo <stefano.russo@gmail.com>
Date: Tue, 5 Apr 2022 23:54:15 +0200
Subject: [PATCH] Implemented cookie-based post login redirects.

---
 services/webapp/code/rosetta/auth.py          | 22 ++++++++++++++++++-
 .../code/rosetta/core_app/decorators.py       |  5 ++++-
 .../webapp/code/rosetta/core_app/views.py     | 18 +++++++++++----
 services/webapp/code/rosetta/settings.py      |  5 +++++
 4 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/services/webapp/code/rosetta/auth.py b/services/webapp/code/rosetta/auth.py
index 207ce59..92c25a2 100644
--- a/services/webapp/code/rosetta/auth.py
+++ b/services/webapp/code/rosetta/auth.py
@@ -1,5 +1,7 @@
 from mozilla_django_oidc.auth import OIDCAuthenticationBackend
+from mozilla_django_oidc.views import OIDCAuthenticationCallbackView
 from .core_app.utils import finalize_user_creation
+from django.http import HttpResponseRedirect
 
 # Setup logging
 import logging
@@ -18,9 +20,27 @@ class RosettaOIDCAuthenticationBackend(OIDCAuthenticationBackend):
 
         return user
 
-
     def get_userinfo(self, access_token, id_token, payload):
 
         # Payload must contain the "email" key
         return payload
 
+
+class RosettaOIDCAuthenticationCallbackView(OIDCAuthenticationCallbackView):
+    
+    def login_success(self):
+        
+        # Call parent login_success but do not return
+        super(RosettaOIDCAuthenticationCallbackView, self).login_success()
+        
+        logger.debug('Trying to get cookie-based post login redirect')
+        post_login_page = self.request.COOKIES.get('post_login_redirect')
+        if post_login_page:
+            logger.debug('Got "%s" and redirecting', post_login_page )
+            response = HttpResponseRedirect(post_login_page)
+            response.delete_cookie('post_login_redirect')
+            return response
+        else:
+            logger.debug('No cookie-based post login redirect found, redirecting to "%s"', self.success_url)
+            return HttpResponseRedirect(self.success_url)
+
diff --git a/services/webapp/code/rosetta/core_app/decorators.py b/services/webapp/code/rosetta/core_app/decorators.py
index dca0655..d6e13e0 100644
--- a/services/webapp/code/rosetta/core_app/decorators.py
+++ b/services/webapp/code/rosetta/core_app/decorators.py
@@ -132,5 +132,8 @@ def private_view(wrapped_view):
 
         else:
             log_user_activity("DEBUG", "Redirecting to login since not authenticated", request)
-            return HttpResponseRedirect('/login')
+            logger.debug('Setting cookie-based post login redirect to "%s"', request.build_absolute_uri())
+            response = HttpResponseRedirect('/login')
+            response.set_cookie('post_login_redirect', request.build_absolute_uri())
+            return response
     return private_view_wrapper
diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py
index 08e4a16..2082ee5 100644
--- a/services/webapp/code/rosetta/core_app/views.py
+++ b/services/webapp/code/rosetta/core_app/views.py
@@ -35,10 +35,17 @@ _task_cache = {}
 def login_view(request):
 
     data = {}
+    
+    # Set post login page
+    post_login_page = request.COOKIES.get('post_login_redirect')
+    if post_login_page is None:
+        post_login_page = '/main'
 
     # If authenticated user reloads the main URL
     if request.method == 'GET' and request.user.is_authenticated:
-        return HttpResponseRedirect('/main/')
+        response = HttpResponseRedirect(post_login_page)
+        response.delete_cookie('post_login_redirect')
+        return response
     else:
         # If local auth disabled, just render login page
         # (will be rendered an open id connect url only)
@@ -73,7 +80,9 @@ def login_view(request):
                 user = authenticate(username=username, password=password)
                 if user:
                     login(request, user)
-                    return HttpResponseRedirect('/main')
+                    response = HttpResponseRedirect(post_login_page)
+                    response.delete_cookie('post_login_redirect')
+                    return response
                 else:
                     raise ErrorMessage('Check email and password')
             else:
@@ -138,8 +147,9 @@ def login_view(request):
             loginToken.delete()
 
             # Now redirect to site
-            return HttpResponseRedirect('/main/')
-
+            response = HttpResponseRedirect(post_login_page)
+            response.delete_cookie('post_login_redirect')
+            return response
 
     # All other cases, render the login page again with no other data than title
     return render(request, 'login.html', {'data': data})
diff --git a/services/webapp/code/rosetta/settings.py b/services/webapp/code/rosetta/settings.py
index 63a0410..9f854ac 100644
--- a/services/webapp/code/rosetta/settings.py
+++ b/services/webapp/code/rosetta/settings.py
@@ -264,6 +264,9 @@ if OIDC_RP_CLIENT_ID:
     # Optional
     OIDC_USE_NONCE =  booleanize(os.environ.get('OIDC_USE_NONCE', False))
     OIDC_TOKEN_USE_BASIC_AUTH = booleanize(os.environ.get('OIDC_TOKEN_USE_BASIC_AUTH', False))
+
+    # Custom callback to enable session-based post-login redirects
+    OIDC_CALLBACK_CLASS = 'rosetta.auth.RosettaOIDCAuthenticationCallbackView'
     
     # Non-customizable stuff
     LOGIN_REDIRECT_URL = '/'
@@ -274,6 +277,8 @@ if OIDC_RP_CLIENT_ID:
     # Required for the Open ID connect redirects to work properly
     USE_X_FORWARDED_HOST = True
     SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
+    
+
 
 
 
-- 
GitLab