diff --git a/zerver/tests/test_auth_backends.py b/zerver/tests/test_auth_backends.py index 0e731d0368..aa4af80fa0 100644 --- a/zerver/tests/test_auth_backends.py +++ b/zerver/tests/test_auth_backends.py @@ -5375,6 +5375,31 @@ class GenericOpenIdConnectTest(SocialAuthBaseWithSyncAttrTest): ], ) + def test_social_auth_state_data_expired_in_redis(self) -> None: + account_data_dict = self.get_account_data_dict(email=self.email, name=self.name) + + # Simulate the state data having expired from redis, like when + # a user takes longer than REDIS_EXPIRATION_SECONDS to return + # from the IdP. + with ( + mock.patch.object( + GenericOpenIdConnectBackend, "get_data_from_redis", return_value=None + ), + self.assertLogs(self.logger_string, level="INFO") as m, + ): + result = self.social_auth_test(account_data_dict, subdomain="zulip") + self.assertEqual(result.status_code, 302) + self.assertEqual("/login/", result["Location"]) + self.assertEqual( + m.output, + [ + self.logger_output( + "State data expired in redis: authentication took too long to complete.", + "info", + ) + ], + ) + @override def test_social_auth_complete(self) -> None: def mock_process_error(backend: BaseOAuth2, data: Mapping[str, object]) -> None: diff --git a/zproject/backends.py b/zproject/backends.py index 87b45cfff5..86c5cfc056 100644 --- a/zproject/backends.py +++ b/zproject/backends.py @@ -4291,7 +4291,15 @@ class GenericOpenIdConnectBackend(SocialAuthMixin, OpenIdConnectAuth): assert state relayed_params = self.get_data_from_redis(state) - assert relayed_params is not None + if relayed_params is None: + # The relayed_params live in redis with a TTL of + # REDIS_EXPIRATION_SECONDS, so this means the user took + # too long to complete the authentication attempt. + self.logger.info( + "State data expired in redis: authentication took too long to complete." + ) + return None + for param in self.standard_relay_params: relayed_value = relayed_params.get(param) session_value = self.strategy.session_get(param)