We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN 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 

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/djangooidc/views.py`
Content:
```
1 # coding: utf-8
2 
3 import logging
4 
5 from django.conf import settings
6 from django.contrib.auth import logout as auth_logout
7 from django.contrib.auth import authenticate, login
8 from django.http import HttpResponseRedirect
9 from django.shortcuts import redirect, render
10 from urllib.parse import parse_qs, urlencode
11 
12 from djangooidc.oidc import Client
13 from djangooidc import exceptions as o_e
14 from registrar.models import User
15 
16 logger = logging.getLogger(__name__)
17 
18 CLIENT = None
19 
20 
21 def _initialize_client():
22     """Initialize the OIDC client. Exceptions are allowed to raise
23     and will need to be caught."""
24     global CLIENT
25     # Initialize provider using pyOICD
26     OP = getattr(settings, "OIDC_ACTIVE_PROVIDER")
27     CLIENT = Client(OP)
28     logger.debug("Client initialized: %s" % CLIENT)
29 
30 
31 def _client_is_none():
32     """Return if the CLIENT is currently None."""
33     global CLIENT
34     return CLIENT is None
35 
36 
37 # Initialize CLIENT
38 try:
39     _initialize_client()
40 except Exception as err:
41     # In the event of an exception, log the error and allow the app load to continue
42     # without the OIDC Client. Subsequent login attempts will attempt to initialize
43     # again if Client is None
44     logger.error(err)
45     logger.error("Unable to configure OpenID Connect provider. Users cannot log in.")
46 
47 
48 def error_page(request, error):
49     """Display a sensible message and log the error."""
50     logger.error(error)
51     if isinstance(error, o_e.AuthenticationFailed):
52         return render(
53             request,
54             "401.html",
55             context={
56                 "friendly_message": error.friendly_message,
57                 "log_identifier": error.locator,
58             },
59             status=401,
60         )
61     if isinstance(error, o_e.InternalError):
62         return render(
63             request,
64             "500.html",
65             context={
66                 "friendly_message": error.friendly_message,
67                 "log_identifier": error.locator,
68             },
69             status=500,
70         )
71     if isinstance(error, Exception):
72         return render(request, "500.html", status=500)
73 
74 
75 def openid(request):
76     """Redirect the user to an authentication provider (OP)."""
77     global CLIENT
78     try:
79         # If the CLIENT is none, attempt to reinitialize before handling the request
80         if _client_is_none():
81             logger.debug("OIDC client is None, attempting to initialize")
82             _initialize_client()
83         request.session["acr_value"] = CLIENT.get_default_acr_value()
84         request.session["next"] = request.GET.get("next", "/")
85         # Create the authentication request
86         return CLIENT.create_authn_request(request.session)
87     except Exception as err:
88         return error_page(request, err)
89 
90 
91 def login_callback(request):
92     """Analyze the token returned by the authentication provider (OP)."""
93     global CLIENT
94     try:
95         # If the CLIENT is none, attempt to reinitialize before handling the request
96         if _client_is_none():
97             logger.debug("OIDC client is None, attempting to initialize")
98             _initialize_client()
99         query = parse_qs(request.GET.urlencode())
100         userinfo = CLIENT.callback(query, request.session)
101         # test for need for identity verification and if it is satisfied
102         # if not satisfied, redirect user to login with stepped up acr_value
103         if _requires_step_up_auth(userinfo):
104             # add acr_value to request.session
105             request.session["acr_value"] = CLIENT.get_step_up_acr_value()
106             return CLIENT.create_authn_request(request.session)
107         user = authenticate(request=request, **userinfo)
108         if user:
109             login(request, user)
110             logger.info("Successfully logged in user %s" % user)
111             # Double login bug (1507)?
112             return redirect(request.session.get("next", "/"))
113         else:
114             raise o_e.BannedUser()
115     except o_e.NoStateDefined as nsd_err:
116         # In the event that a user is in the middle of a login when the app is restarted,
117         # their session state will no longer be available, so redirect the user to the
118         # beginning of login process without raising an error to the user.
119         logger.warning(f"No State Defined: {nsd_err}")
120         return redirect(request.session.get("next", "/"))
121     except Exception as err:
122         return error_page(request, err)
123 
124 
125 def _requires_step_up_auth(userinfo):
126     """if User.needs_identity_verification and step_up_acr_value not in
127     ial returned from callback, return True"""
128     step_up_acr_value = CLIENT.get_step_up_acr_value()
129     acr_value = userinfo.get("ial", "")
130     uuid = userinfo.get("sub", "")
131     email = userinfo.get("email", "")
132     if acr_value != step_up_acr_value:
133         # The acr of this attempt is not at the highest level
134         # so check if the user needs the higher level
135         return User.needs_identity_verification(email, uuid)
136     else:
137         # This attempt already came back at the highest level
138         # so does not require step up
139         return False
140 
141 
142 def logout(request, next_page=None):
143     """Redirect the user to the authentication provider (OP) logout page."""
144     try:
145         user = request.user
146         request_args = {
147             "client_id": CLIENT.client_id,
148             "state": request.session["state"],
149         }
150         if (
151             "post_logout_redirect_uris" in CLIENT.registration_response.keys()
152             and len(CLIENT.registration_response["post_logout_redirect_uris"]) > 0
153         ):
154             request_args.update(
155                 {"post_logout_redirect_uri": CLIENT.registration_response["post_logout_redirect_uris"][0]}
156             )
157         url = CLIENT.provider_info["end_session_endpoint"]
158         url += "?" + urlencode(request_args)
159         return HttpResponseRedirect(url)
160     except Exception as err:
161         return error_page(request, err)
162     finally:
163         # Always remove Django session stuff - even if not logged out from OP.
164         # Don't wait for the callback as it may never come.
165         auth_logout(request)
166         logger.info("Successfully logged out user %s" % user)
167         next_page = getattr(settings, "LOGOUT_REDIRECT_URL", None)
168         if next_page:
169             request.session["next"] = next_page
170 
171 
172 def logout_callback(request):
173     """Simple redirection view: after logout, redirect to `next`."""
174     next = request.session.get("next", "/")
175     return redirect(next)
176
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

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 @@
         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

{"golden_diff": "diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py\n--- a/src/djangooidc/views.py\n+++ b/src/djangooidc/views.py\n@@ -145,8 +145,12 @@\n         user = request.user\n         request_args = {\n             \"client_id\": CLIENT.client_id,\n-            \"state\": request.session[\"state\"],\n         }\n+        # if state is not in request session, still redirect to the identity\n+        # provider's logout url, but don't include the state in the url; this\n+        # will successfully log out of the identity provider\n+        if \"state\" in request.session:\n+            request_args[\"state\"] = request.session[\"state\"]\n         if (\n             \"post_logout_redirect_uris\" in CLIENT.registration_response.keys()\n             and len(CLIENT.registration_response[\"post_logout_redirect_uris\"]) > 0\n", "issue": "Logout: OIDC logout behavior resulting on \"500\" error in server restart/recompile\n### Current Behavior\r\n\r\nLogout behavior observed:\r\n\r\n1. 500 error is displayed when user logs out\r\n2. By clicking sign in and then sign out, user is able to successfully log out without error\r\n\r\nLogs being shown when this error occurs\r\n![image](https://github.com/cisagov/manage.get.gov/assets/144387994/20b28946-e63f-47a4-bba7-40ffdc0f954e)\r\n\r\n\r\n### Expected Behavior\r\n\r\nUser logs out successfully without encountering error.\r\n\r\n### Steps to Reproduce\r\n\r\n1. sign in to server\r\n2. restart the server\r\n3. click sign out\r\n4. 500 error is displayed \r\n5. By clicking sign in and then sign out, user is able to successfully log out without error\r\n\r\n\r\nwhen running locally:\r\n1. sign in to server\r\n2. make a code change that causes the code to recompile\r\n3. click sign out\r\n4. 500 error is displayed \r\n5. By clicking sign in and then sign out, user is able to successfully log out without error\r\n### Environment\r\nObserved locally on all branches, observed on sandboxes\r\n\r\n### Additional Context\r\n\r\n_No response_\r\n\r\n### Issue Links\r\n\r\nRelated to #1505 \n", "before_files": [{"content": "# coding: utf-8\n\nimport logging\n\nfrom django.conf import settings\nfrom django.contrib.auth import logout as auth_logout\nfrom django.contrib.auth import authenticate, login\nfrom django.http import HttpResponseRedirect\nfrom django.shortcuts import redirect, render\nfrom urllib.parse import parse_qs, urlencode\n\nfrom djangooidc.oidc import Client\nfrom djangooidc import exceptions as o_e\nfrom registrar.models import User\n\nlogger = logging.getLogger(__name__)\n\nCLIENT = None\n\n\ndef _initialize_client():\n    \"\"\"Initialize the OIDC client. Exceptions are allowed to raise\n    and will need to be caught.\"\"\"\n    global CLIENT\n    # Initialize provider using pyOICD\n    OP = getattr(settings, \"OIDC_ACTIVE_PROVIDER\")\n    CLIENT = Client(OP)\n    logger.debug(\"Client initialized: %s\" % CLIENT)\n\n\ndef _client_is_none():\n    \"\"\"Return if the CLIENT is currently None.\"\"\"\n    global CLIENT\n    return CLIENT is None\n\n\n# Initialize CLIENT\ntry:\n    _initialize_client()\nexcept Exception as err:\n    # In the event of an exception, log the error and allow the app load to continue\n    # without the OIDC Client. Subsequent login attempts will attempt to initialize\n    # again if Client is None\n    logger.error(err)\n    logger.error(\"Unable to configure OpenID Connect provider. Users cannot log in.\")\n\n\ndef error_page(request, error):\n    \"\"\"Display a sensible message and log the error.\"\"\"\n    logger.error(error)\n    if isinstance(error, o_e.AuthenticationFailed):\n        return render(\n            request,\n            \"401.html\",\n            context={\n                \"friendly_message\": error.friendly_message,\n                \"log_identifier\": error.locator,\n            },\n            status=401,\n        )\n    if isinstance(error, o_e.InternalError):\n        return render(\n            request,\n            \"500.html\",\n            context={\n                \"friendly_message\": error.friendly_message,\n                \"log_identifier\": error.locator,\n            },\n            status=500,\n        )\n    if isinstance(error, Exception):\n        return render(request, \"500.html\", status=500)\n\n\ndef openid(request):\n    \"\"\"Redirect the user to an authentication provider (OP).\"\"\"\n    global CLIENT\n    try:\n        # If the CLIENT is none, attempt to reinitialize before handling the request\n        if _client_is_none():\n            logger.debug(\"OIDC client is None, attempting to initialize\")\n            _initialize_client()\n        request.session[\"acr_value\"] = CLIENT.get_default_acr_value()\n        request.session[\"next\"] = request.GET.get(\"next\", \"/\")\n        # Create the authentication request\n        return CLIENT.create_authn_request(request.session)\n    except Exception as err:\n        return error_page(request, err)\n\n\ndef login_callback(request):\n    \"\"\"Analyze the token returned by the authentication provider (OP).\"\"\"\n    global CLIENT\n    try:\n        # If the CLIENT is none, attempt to reinitialize before handling the request\n        if _client_is_none():\n            logger.debug(\"OIDC client is None, attempting to initialize\")\n            _initialize_client()\n        query = parse_qs(request.GET.urlencode())\n        userinfo = CLIENT.callback(query, request.session)\n        # test for need for identity verification and if it is satisfied\n        # if not satisfied, redirect user to login with stepped up acr_value\n        if _requires_step_up_auth(userinfo):\n            # add acr_value to request.session\n            request.session[\"acr_value\"] = CLIENT.get_step_up_acr_value()\n            return CLIENT.create_authn_request(request.session)\n        user = authenticate(request=request, **userinfo)\n        if user:\n            login(request, user)\n            logger.info(\"Successfully logged in user %s\" % user)\n            # Double login bug (1507)?\n            return redirect(request.session.get(\"next\", \"/\"))\n        else:\n            raise o_e.BannedUser()\n    except o_e.NoStateDefined as nsd_err:\n        # In the event that a user is in the middle of a login when the app is restarted,\n        # their session state will no longer be available, so redirect the user to the\n        # beginning of login process without raising an error to the user.\n        logger.warning(f\"No State Defined: {nsd_err}\")\n        return redirect(request.session.get(\"next\", \"/\"))\n    except Exception as err:\n        return error_page(request, err)\n\n\ndef _requires_step_up_auth(userinfo):\n    \"\"\"if User.needs_identity_verification and step_up_acr_value not in\n    ial returned from callback, return True\"\"\"\n    step_up_acr_value = CLIENT.get_step_up_acr_value()\n    acr_value = userinfo.get(\"ial\", \"\")\n    uuid = userinfo.get(\"sub\", \"\")\n    email = userinfo.get(\"email\", \"\")\n    if acr_value != step_up_acr_value:\n        # The acr of this attempt is not at the highest level\n        # so check if the user needs the higher level\n        return User.needs_identity_verification(email, uuid)\n    else:\n        # This attempt already came back at the highest level\n        # so does not require step up\n        return False\n\n\ndef logout(request, next_page=None):\n    \"\"\"Redirect the user to the authentication provider (OP) logout page.\"\"\"\n    try:\n        user = request.user\n        request_args = {\n            \"client_id\": CLIENT.client_id,\n            \"state\": request.session[\"state\"],\n        }\n        if (\n            \"post_logout_redirect_uris\" in CLIENT.registration_response.keys()\n            and len(CLIENT.registration_response[\"post_logout_redirect_uris\"]) > 0\n        ):\n            request_args.update(\n                {\"post_logout_redirect_uri\": CLIENT.registration_response[\"post_logout_redirect_uris\"][0]}\n            )\n        url = CLIENT.provider_info[\"end_session_endpoint\"]\n        url += \"?\" + urlencode(request_args)\n        return HttpResponseRedirect(url)\n    except Exception as err:\n        return error_page(request, err)\n    finally:\n        # Always remove Django session stuff - even if not logged out from OP.\n        # Don't wait for the callback as it may never come.\n        auth_logout(request)\n        logger.info(\"Successfully logged out user %s\" % user)\n        next_page = getattr(settings, \"LOGOUT_REDIRECT_URL\", None)\n        if next_page:\n            request.session[\"next\"] = next_page\n\n\ndef logout_callback(request):\n    \"\"\"Simple redirection view: after logout, redirect to `next`.\"\"\"\n    next = request.session.get(\"next\", \"/\")\n    return redirect(next)\n", "path": "src/djangooidc/views.py"}], "after_files": [{"content": "# coding: utf-8\n\nimport logging\n\nfrom django.conf import settings\nfrom django.contrib.auth import logout as auth_logout\nfrom django.contrib.auth import authenticate, login\nfrom django.http import HttpResponseRedirect\nfrom django.shortcuts import redirect, render\nfrom urllib.parse import parse_qs, urlencode\n\nfrom djangooidc.oidc import Client\nfrom djangooidc import exceptions as o_e\nfrom registrar.models import User\n\nlogger = logging.getLogger(__name__)\n\nCLIENT = None\n\n\ndef _initialize_client():\n    \"\"\"Initialize the OIDC client. Exceptions are allowed to raise\n    and will need to be caught.\"\"\"\n    global CLIENT\n    # Initialize provider using pyOICD\n    OP = getattr(settings, \"OIDC_ACTIVE_PROVIDER\")\n    CLIENT = Client(OP)\n    logger.debug(\"Client initialized: %s\" % CLIENT)\n\n\ndef _client_is_none():\n    \"\"\"Return if the CLIENT is currently None.\"\"\"\n    global CLIENT\n    return CLIENT is None\n\n\n# Initialize CLIENT\ntry:\n    _initialize_client()\nexcept Exception as err:\n    # In the event of an exception, log the error and allow the app load to continue\n    # without the OIDC Client. Subsequent login attempts will attempt to initialize\n    # again if Client is None\n    logger.error(err)\n    logger.error(\"Unable to configure OpenID Connect provider. Users cannot log in.\")\n\n\ndef error_page(request, error):\n    \"\"\"Display a sensible message and log the error.\"\"\"\n    logger.error(error)\n    if isinstance(error, o_e.AuthenticationFailed):\n        return render(\n            request,\n            \"401.html\",\n            context={\n                \"friendly_message\": error.friendly_message,\n                \"log_identifier\": error.locator,\n            },\n            status=401,\n        )\n    if isinstance(error, o_e.InternalError):\n        return render(\n            request,\n            \"500.html\",\n            context={\n                \"friendly_message\": error.friendly_message,\n                \"log_identifier\": error.locator,\n            },\n            status=500,\n        )\n    if isinstance(error, Exception):\n        return render(request, \"500.html\", status=500)\n\n\ndef openid(request):\n    \"\"\"Redirect the user to an authentication provider (OP).\"\"\"\n    global CLIENT\n    try:\n        # If the CLIENT is none, attempt to reinitialize before handling the request\n        if _client_is_none():\n            logger.debug(\"OIDC client is None, attempting to initialize\")\n            _initialize_client()\n        request.session[\"acr_value\"] = CLIENT.get_default_acr_value()\n        request.session[\"next\"] = request.GET.get(\"next\", \"/\")\n        # Create the authentication request\n        return CLIENT.create_authn_request(request.session)\n    except Exception as err:\n        return error_page(request, err)\n\n\ndef login_callback(request):\n    \"\"\"Analyze the token returned by the authentication provider (OP).\"\"\"\n    global CLIENT\n    try:\n        # If the CLIENT is none, attempt to reinitialize before handling the request\n        if _client_is_none():\n            logger.debug(\"OIDC client is None, attempting to initialize\")\n            _initialize_client()\n        query = parse_qs(request.GET.urlencode())\n        userinfo = CLIENT.callback(query, request.session)\n        # test for need for identity verification and if it is satisfied\n        # if not satisfied, redirect user to login with stepped up acr_value\n        if _requires_step_up_auth(userinfo):\n            # add acr_value to request.session\n            request.session[\"acr_value\"] = CLIENT.get_step_up_acr_value()\n            return CLIENT.create_authn_request(request.session)\n        user = authenticate(request=request, **userinfo)\n        if user:\n            login(request, user)\n            logger.info(\"Successfully logged in user %s\" % user)\n            # Double login bug (1507)?\n            return redirect(request.session.get(\"next\", \"/\"))\n        else:\n            raise o_e.BannedUser()\n    except o_e.NoStateDefined as nsd_err:\n        # In the event that a user is in the middle of a login when the app is restarted,\n        # their session state will no longer be available, so redirect the user to the\n        # beginning of login process without raising an error to the user.\n        logger.warning(f\"No State Defined: {nsd_err}\")\n        return redirect(request.session.get(\"next\", \"/\"))\n    except Exception as err:\n        return error_page(request, err)\n\n\ndef _requires_step_up_auth(userinfo):\n    \"\"\"if User.needs_identity_verification and step_up_acr_value not in\n    ial returned from callback, return True\"\"\"\n    step_up_acr_value = CLIENT.get_step_up_acr_value()\n    acr_value = userinfo.get(\"ial\", \"\")\n    uuid = userinfo.get(\"sub\", \"\")\n    email = userinfo.get(\"email\", \"\")\n    if acr_value != step_up_acr_value:\n        # The acr of this attempt is not at the highest level\n        # so check if the user needs the higher level\n        return User.needs_identity_verification(email, uuid)\n    else:\n        # This attempt already came back at the highest level\n        # so does not require step up\n        return False\n\n\ndef logout(request, next_page=None):\n    \"\"\"Redirect the user to the authentication provider (OP) logout page.\"\"\"\n    try:\n        user = request.user\n        request_args = {\n            \"client_id\": CLIENT.client_id,\n        }\n        # if state is not in request session, still redirect to the identity\n        # provider's logout url, but don't include the state in the url; this\n        # will successfully log out of the identity provider\n        if \"state\" in request.session:\n            request_args[\"state\"] = request.session[\"state\"]\n        if (\n            \"post_logout_redirect_uris\" in CLIENT.registration_response.keys()\n            and len(CLIENT.registration_response[\"post_logout_redirect_uris\"]) > 0\n        ):\n            request_args.update(\n                {\"post_logout_redirect_uri\": CLIENT.registration_response[\"post_logout_redirect_uris\"][0]}\n            )\n        url = CLIENT.provider_info[\"end_session_endpoint\"]\n        url += \"?\" + urlencode(request_args)\n        return HttpResponseRedirect(url)\n    except Exception as err:\n        return error_page(request, err)\n    finally:\n        # Always remove Django session stuff - even if not logged out from OP.\n        # Don't wait for the callback as it may never come.\n        auth_logout(request)\n        logger.info(\"Successfully logged out user %s\" % user)\n        next_page = getattr(settings, \"LOGOUT_REDIRECT_URL\", None)\n        if next_page:\n            request.session[\"next\"] = next_page\n\n\ndef logout_callback(request):\n    \"\"\"Simple redirection view: after logout, redirect to `next`.\"\"\"\n    next = request.session.get(\"next\", \"/\")\n    return redirect(next)\n", "path": "src/djangooidc/views.py"}]}