diff --git a/inst/loops/config.py b/inst/loops/config.py index b30e1cf..be6499e 100644 --- a/inst/loops/config.py +++ b/inst/loops/config.py @@ -24,6 +24,9 @@ dbpassword = getenv('DBPASSWORD', 'secret') dbschema = getenv('DBSCHEMA', 'demo') # OpenID Connect (OIDC, e.g. via zitadel) authentication settings +authentication_method = 'cookie' # 'legacy'|'select'|'oidc'|'cookie' + +# OpenID Connect (OIDC) authentication settings oidc_provider = getenv('OIDC_PROVIDER', '') #'https://instance1-abcdef.zitadel.cloud') oidc_client_id = getenv('OIDC_CLIENT_ID', '12345') oidc_params = dict( diff --git a/inst/loops/overrides.zcml b/inst/loops/overrides.zcml index 7996f67..0c42adb 100644 --- a/inst/loops/overrides.zcml +++ b/inst/loops/overrides.zcml @@ -1,4 +1,27 @@ - + + + + + + + + + diff --git a/loops/server/auth.py b/loops/server/auth.py index 5784d32..7e713c0 100644 --- a/loops/server/auth.py +++ b/loops/server/auth.py @@ -4,8 +4,9 @@ # and other authentication and authorization stuff. from scopes.web.auth import oidc -from zope.authentication.interfaces import IAuthentication +from zope.authentication.interfaces import IAuthentication, IUnauthenticatedPrincipal from zope.browserpage import ViewPageTemplateFile +from zope.cachedescriptors.property import Lazy from zope.component import provideAdapter, getUtility, provideUtility from zope.interface import implementer, Interface from zope.publisher.interfaces.browser import IBrowserRequest, IBrowserPage @@ -14,6 +15,9 @@ from zope.security.proxy import removeSecurityProxy import config +from logging import getLogger +logger = getLogger("loops.server.auth") + def registerAuthUtility(config): baseAuth = getUtility(IAuthentication) print('*** registerAuthUtility, baseAuth:', baseAuth) @@ -38,6 +42,10 @@ class LoginPage: return self.authOidc() return self.index() + @Lazy + def isAnonymous(self): + return IUnauthenticatedPrincipal.providedBy(self.request.principal) + def authOidc(self): oidc.Authenticator(self.request).login() return '' @@ -57,9 +65,17 @@ class LoginPageSelect(LoginPage): class Unauthorized(LoginPage): def __call__(self): - print(f'*** unauthorized: user = {self.request.principal.id}, authMethod = {self.authMethod}') - return "Unauthorized" - #return super(Unauthorized, self).__call__() + response = self.request.response + # make sure that squid does not keep the response in the cache + response.setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT') + response.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate') + response.setHeader('Pragma', 'no-cache') + logger.warn(f'unauthorized: user={self.request.principal.id}, authMethod={self.authMethod}') + if self.isAnonymous: + return super(Unauthorized, self).__call__() # open or redirect to login page + else: + response.setStatus(403) + return 'Unauthorized' def getConfigAuthMethod():