From b1e8ebc7585c2fc4ad7336df0597e1ac95c32dff Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Sat, 24 Oct 2020 17:56:26 +0200 Subject: [PATCH 2/5] idp_oidc: correctly load session in OIDCCode and OIDCAccessToken (#47900) * access_token can be valid without a session or with a session linked to the user * code is only valid with a live session linked to its user * session was not loaded correctly, it's only loaded after accessing its content, and session_key is only checked if the session is loaded. --- src/authentic2_idp_oidc/models.py | 70 +++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/authentic2_idp_oidc/models.py b/src/authentic2_idp_oidc/models.py index 0da97aaa..fb5e2961 100644 --- a/src/authentic2_idp_oidc/models.py +++ b/src/authentic2_idp_oidc/models.py @@ -293,7 +293,36 @@ class OIDCAuthorization(models.Model): self.scopes) -class OIDCCode(models.Model): +def get_session(session_key): + engine = import_module(settings.SESSION_ENGINE) + session = engine.SessionStore(session_key=session_key) + session.items() + if session._session_key == session_key: + return session + return None + + +class SessionMixin(object): + @property + def session(self): + if not hasattr(self, '_session'): + if self.session_key: + self._session = get_session(self.session_key) + else: + self._session = None + return getattr(self, '_session', None) + + @session.setter + def session(self, session): + if session: + self.session_key = session.session_key + self._session = session + else: + self.session_key = '' + self._session = None + + +class OIDCCode(SessionMixin, models.Model): uuid = models.CharField( max_length=128, verbose_name=_('uuid'), @@ -332,21 +361,17 @@ class OIDCCode(models.Model): objects = managers.OIDCExpiredManager() - @property - def session(self): - if not hasattr(self, '_session'): - engine = import_module(settings.SESSION_ENGINE) - session = engine.SessionStore(session_key=self.session_key) - session.load() - if session._session_key == self.session_key: - self._session = session - return getattr(self, '_session', None) - def scope_set(self): return utils.scope_set(self.scopes) def is_valid(self): - return self.expired >= now() and self.session is not None + if self.expired < now(): + return False + if not self.session: + return False + if self.session.get('_auth_user_id') != str(self.user_id): + return False + return True def __repr__(self): return '' % ( @@ -357,7 +382,7 @@ class OIDCCode(models.Model): self.scopes) -class OIDCAccessToken(models.Model): +class OIDCAccessToken(SessionMixin, models.Model): uuid = models.CharField( max_length=128, verbose_name=_('uuid'), @@ -389,17 +414,16 @@ class OIDCAccessToken(models.Model): def scope_set(self): return utils.scope_set(self.scopes) - @property - def session(self): - if not hasattr(self, '_session'): - engine = import_module(settings.SESSION_ENGINE) - session = engine.SessionStore(session_key=self.session_key) - if session._session_key == self.session_key: - self._session = session - return getattr(self, '_session', None) - def is_valid(self): - return self.expired >= now() and self.session is not None + if self.expired < now(): + return False + if not self.session_key: + return True + if not self.session: + return False + if self.session.get('_auth_user_id') != str(self.user_id): + return False + return True def __repr__(self): return '' % ( -- 2.29.2