Repository: mozilla/kitsune

Issue:
Support both OIDC and DB logins
And restrict use of `/admin/` to users authenticated with OIDC only. I'll be investigating whether this is possible in this issue. If we can't support this quickly in a single instance we will deploy an admin-only version of kitsune that will only work with OIDC auth and allow use of the Admin, and turn off `/admin/` on SUMO proper.

/cc @glogiotatidis 


Discussion:
I'm thinking we should be able to do this by detecting whether an authenticated user has certain OIDC keys in their session, e.g. ["oidc_id_token_expiration"](https://github.com/mozilla/mozilla-django-oidc/blob/5916a69ed7870053c4d4e194b45b42c2fac49496/mozilla_django_oidc/views.py#L54). Then we could have a separate middleware (or, more likely, a subclass of the OIDCRefresh middleware) that will only refresh the token on `/admin/*` URLs and will require a user to have those values in the session.

Resolving patch:
diff --git a/kitsune/settings.py b/kitsune/settings.py
--- a/kitsune/settings.py
+++ b/kitsune/settings.py
@@ -509,6 +509,9 @@ def parse_conn_max_age(value):
     # NoVarySessionMiddleware.
     'django.contrib.messages.middleware.MessageMiddleware',
 
+    # This should come after MessageMiddleware
+    'kitsune.sumo.middleware.SUMORefreshIDTokenAdminMiddleware',
+
     # This middleware should come after AuthenticationMiddleware.
     'kitsune.users.middleware.TokenLoginMiddleware',
 
@@ -574,9 +577,7 @@ def parse_conn_max_age(value):
     OIDC_ENABLE = config('OIDC_ENABLE', default=False, cast=bool)
     ENABLE_ADMIN = config('ENABLE_ADMIN', default=OIDC_ENABLE, cast=bool)
     if OIDC_ENABLE:
-        MIDDLEWARE_CLASSES += ('mozilla_django_oidc.middleware.RefreshIDToken',)
         AUTHENTICATION_BACKENDS += ('mozilla_django_oidc.auth.OIDCAuthenticationBackend',)
-
         OIDC_OP_AUTHORIZATION_ENDPOINT = config('OIDC_OP_AUTHORIZATION_ENDPOINT')
         OIDC_OP_TOKEN_ENDPOINT = config('OIDC_OP_TOKEN_ENDPOINT')
         OIDC_OP_USER_ENDPOINT = config('OIDC_OP_USER_ENDPOINT')
diff --git a/kitsune/sumo/middleware.py b/kitsune/sumo/middleware.py
--- a/kitsune/sumo/middleware.py
+++ b/kitsune/sumo/middleware.py
@@ -3,6 +3,8 @@
 import urllib
 
 from django.conf import settings
+from django.contrib.auth import logout
+from django.contrib import messages
 from django.core.exceptions import MiddlewareNotUsed
 from django.core.urlresolvers import is_valid_path
 from django.db.utils import DatabaseError
@@ -14,6 +16,7 @@
 from django.utils.encoding import iri_to_uri, smart_str, smart_unicode
 
 import mobility
+from mozilla_django_oidc.middleware import RefreshIDToken
 
 from kitsune.sumo.templatetags.jinja_helpers import urlparams
 from kitsune.sumo.urlresolvers import Prefixer, set_url_prefixer, split_path
@@ -26,6 +29,22 @@
     MiddlewareMixin = object
 
 
+class SUMORefreshIDTokenAdminMiddleware(RefreshIDToken):
+    def __init__(self, *args, **kwargs):
+        if not settings.OIDC_ENABLE:
+            raise MiddlewareNotUsed
+
+    def process_request(self, request):
+        """Only allow refresh and enforce OIDC auth on admin URLs"""
+        if request.path.startswith('/admin/') and request.path != '/admin/login/':
+            if 'oidc_id_token_expiration' not in request.session:
+                logout(request)
+                messages.error(request, 'OIDC login required for admin access')
+                return HttpResponseRedirect('/admin/login/')
+
+            return super(SUMORefreshIDTokenAdminMiddleware, self).process_request(request)
+
+
 class LocaleURLMiddleware(object):
     """
     Based on zamboni.amo.middleware.


Test patch: