Repository: cisagov/manage.get.gov

Issue:
Logout: OIDC logout behavior resulting on "500" error in server restart/recompile
### Current Behavior

Logout behavior observed:

1. 500 error is displayed when user logs out
2. By clicking sign in and then sign out, user is able to successfully log out without error

Logs being shown when this error occurs
![image](https://github.com/cisagov/manage.get.gov/assets/144387994/20b28946-e63f-47a4-bba7-40ffdc0f954e)


### Expected Behavior

User logs out successfully without encountering error.

### Steps to Reproduce

1. sign in to server
2. restart the server
3. click sign out
4. 500 error is displayed 
5. By clicking sign in and then sign out, user is able to successfully log out without error


when running locally:
1. sign in to server
2. make a code change that causes the code to recompile
3. click sign out
4. 500 error is displayed 
5. By clicking sign in and then sign out, user is able to successfully log out without error
### Environment
Observed locally on all branches, observed on sandboxes

### Additional Context

_No response_

### Issue Links

Related to #1505 


Discussion:

Resolving patch:
diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py
--- a/src/djangooidc/views.py
+++ b/src/djangooidc/views.py
@@ -145,8 +145,12 @@ def logout(request, next_page=None):
         user = request.user
         request_args = {
             "client_id": CLIENT.client_id,
-            "state": request.session["state"],
         }
+        # if state is not in request session, still redirect to the identity
+        # provider's logout url, but don't include the state in the url; this
+        # will successfully log out of the identity provider
+        if "state" in request.session:
+            request_args["state"] = request.session["state"]
         if (
             "post_logout_redirect_uris" in CLIENT.registration_response.keys()
             and len(CLIENT.registration_response["post_logout_redirect_uris"]) > 0


Test patch:
diff --git a/src/djangooidc/tests/test_views.py b/src/djangooidc/tests/test_views.py
--- a/src/djangooidc/tests/test_views.py
+++ b/src/djangooidc/tests/test_views.py
@@ -327,6 +327,27 @@ def test_logout_redirect_url(self, mock_client):
             self.assertEqual(response.status_code, 302)
             self.assertEqual(actual, expected)
 
+    def test_logout_redirect_url_with_no_session_state(self, mock_client):
+        """Test that logout redirects to the configured post_logout_redirect_uris."""
+        with less_console_noise():
+            # MOCK
+            mock_client.callback.side_effect = self.user_info
+            mock_client.registration_response = {"post_logout_redirect_uris": ["http://example.com/back"]}
+            mock_client.provider_info = {"end_session_endpoint": "http://example.com/log_me_out"}
+            mock_client.client_id = "TEST"
+            # TEST
+            with less_console_noise():
+                response = self.client.get(reverse("logout"))
+            # ASSERTIONS
+            # Assert redirect code and url are accurate
+            expected = (
+                "http://example.com/log_me_out?client_id=TEST"
+                "&post_logout_redirect_uri=http%3A%2F%2Fexample.com%2Fback"
+            )
+            actual = response.url
+            self.assertEqual(response.status_code, 302)
+            self.assertEqual(actual, expected)
+
     @patch("djangooidc.views.auth_logout")
     def test_logout_always_logs_out(self, mock_logout, _):
         """Without additional mocking, logout will always fail.