prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Increase reliability on OIDC connection
  ### Issue description
  
  While investigating #1726  we realized there is some areas for improvement in our handling of the connection to OIDC so that all scenarios of failure show a properly formatted 500 error page
  
  ### Acceptance criteria
  
  - [ ] Make sure all login.gov/identity sandbox connection issues result in the usual 500 error 
  - [ ] refactor the connection set up as needed
  
  ### Additional context
  
  _No response_
  
  ### Links to other issues
  
  relates to: #1726
  
  --- 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 try:
  19     # Initialize provider using pyOICD
  20     OP = getattr(settings, "OIDC_ACTIVE_PROVIDER")
  21     CLIENT = Client(OP)
  22     logger.debug("client initialized %s" % CLIENT)
  23 except Exception as err:
  24     CLIENT = None  # type: ignore
  25     logger.warning(err)
  26     logger.warning("Unable to configure OpenID Connect provider. Users cannot log in.")
  27 
  28 
  29 def error_page(request, error):
  30     """Display a sensible message and log the error."""
  31     logger.error(error)
  32     if isinstance(error, o_e.AuthenticationFailed):
  33         return render(
  34             request,
  35             "401.html",
  36             context={
  37                 "friendly_message": error.friendly_message,
  38                 "log_identifier": error.locator,
  39             },
  40             status=401,
  41         )
  42     if isinstance(error, o_e.InternalError):
  43         return render(
  44             request,
  45             "500.html",
  46             context={
  47                 "friendly_message": error.friendly_message,
  48                 "log_identifier": error.locator,
  49             },
  50             status=500,
  51         )
  52     if isinstance(error, Exception):
  53         return render(request, "500.html", status=500)
  54 
  55 
  56 def openid(request):
  57     """Redirect the user to an authentication provider (OP)."""
  58     # If the session reset because of a server restart, attempt to login again
  59     request.session["acr_value"] = CLIENT.get_default_acr_value()
  60 
  61     request.session["next"] = request.GET.get("next", "/")
  62 
  63     try:
  64         return CLIENT.create_authn_request(request.session)
  65     except Exception as err:
  66         return error_page(request, err)
  67 
  68 
  69 def login_callback(request):
  70     """Analyze the token returned by the authentication provider (OP)."""
  71     try:
  72         query = parse_qs(request.GET.urlencode())
  73         userinfo = CLIENT.callback(query, request.session)
  74         # test for need for identity verification and if it is satisfied
  75         # if not satisfied, redirect user to login with stepped up acr_value
  76         if requires_step_up_auth(userinfo):
  77             # add acr_value to request.session
  78             request.session["acr_value"] = CLIENT.get_step_up_acr_value()
  79             return CLIENT.create_authn_request(request.session)
  80         user = authenticate(request=request, **userinfo)
  81         if user:
  82             login(request, user)
  83             logger.info("Successfully logged in user %s" % user)
  84             # Double login bug (1507)?
  85             return redirect(request.session.get("next", "/"))
  86         else:
  87             raise o_e.BannedUser()
  88     except o_e.NoStateDefined as nsd_err:
  89         logger.warning(f"No State Defined: {nsd_err}")
  90         return redirect(request.session.get("next", "/"))
  91     except Exception as err:
  92         return error_page(request, err)
  93 
  94 
  95 def requires_step_up_auth(userinfo):
  96     """if User.needs_identity_verification and step_up_acr_value not in
  97     ial returned from callback, return True"""
  98     step_up_acr_value = CLIENT.get_step_up_acr_value()
  99     acr_value = userinfo.get("ial", "")
  100     uuid = userinfo.get("sub", "")
  101     email = userinfo.get("email", "")
  102     if acr_value != step_up_acr_value:
  103         # The acr of this attempt is not at the highest level
  104         # so check if the user needs the higher level
  105         return User.needs_identity_verification(email, uuid)
  106     else:
  107         # This attempt already came back at the highest level
  108         # so does not require step up
  109         return False
  110 
  111 
  112 def logout(request, next_page=None):
  113     """Redirect the user to the authentication provider (OP) logout page."""
  114     try:
  115         user = request.user
  116         request_args = {
  117             "client_id": CLIENT.client_id,
  118             "state": request.session["state"],
  119         }
  120         if (
  121             "post_logout_redirect_uris" in CLIENT.registration_response.keys()
  122             and len(CLIENT.registration_response["post_logout_redirect_uris"]) > 0
  123         ):
  124             request_args.update(
  125                 {"post_logout_redirect_uri": CLIENT.registration_response["post_logout_redirect_uris"][0]}
  126             )
  127         url = CLIENT.provider_info["end_session_endpoint"]
  128         url += "?" + urlencode(request_args)
  129         return HttpResponseRedirect(url)
  130     except Exception as err:
  131         return error_page(request, err)
  132     finally:
  133         # Always remove Django session stuff - even if not logged out from OP.
  134         # Don't wait for the callback as it may never come.
  135         auth_logout(request)
  136         logger.info("Successfully logged out user %s" % user)
  137         next_page = getattr(settings, "LOGOUT_REDIRECT_URL", None)
  138         if next_page:
  139             request.session["next"] = next_page
  140 
  141 
  142 def logout_callback(request):
  143     """Simple redirection view: after logout, redirect to `next`."""
  144     next = request.session.get("next", "/")
  145     return redirect(next)
  146
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/src/djangooidc/views.py b/src/djangooidc/views.py
  --- a/src/djangooidc/views.py
  +++ b/src/djangooidc/views.py
  @@ -15,15 +15,34 @@
   
   logger = logging.getLogger(__name__)
   
  -try:
  +CLIENT = None
  +
  +
  +def _initialize_client():
  +    """Initialize the OIDC client. Exceptions are allowed to raise
  +    and will need to be caught."""
  +    global CLIENT
       # Initialize provider using pyOICD
       OP = getattr(settings, "OIDC_ACTIVE_PROVIDER")
       CLIENT = Client(OP)
  -    logger.debug("client initialized %s" % CLIENT)
  +    logger.debug("Client initialized: %s" % CLIENT)
  +
  +
  +def _client_is_none():
  +    """Return if the CLIENT is currently None."""
  +    global CLIENT
  +    return CLIENT is None
  +
  +
  +# Initialize CLIENT
  +try:
  +    _initialize_client()
   except Exception as err:
  -    CLIENT = None  # type: ignore
  -    logger.warning(err)
  -    logger.warning("Unable to configure OpenID Connect provider. Users cannot log in.")
  +    # In the event of an exception, log the error and allow the app load to continue
  +    # without the OIDC Client. Subsequent login attempts will attempt to initialize
  +    # again if Client is None
  +    logger.error(err)
  +    logger.error("Unable to configure OpenID Connect provider. Users cannot log in.")
   
   
   def error_page(request, error):
  @@ -55,12 +74,15 @@
   
   def openid(request):
       """Redirect the user to an authentication provider (OP)."""
  -    # If the session reset because of a server restart, attempt to login again
  -    request.session["acr_value"] = CLIENT.get_default_acr_value()
  -
  -    request.session["next"] = request.GET.get("next", "/")
  -
  +    global CLIENT
       try:
  +        # If the CLIENT is none, attempt to reinitialize before handling the request
  +        if _client_is_none():
  +            logger.debug("OIDC client is None, attempting to initialize")
  +            _initialize_client()
  +        request.session["acr_value"] = CLIENT.get_default_acr_value()
  +        request.session["next"] = request.GET.get("next", "/")
  +        # Create the authentication request
           return CLIENT.create_authn_request(request.session)
       except Exception as err:
           return error_page(request, err)
  @@ -68,12 +90,17 @@
   
   def login_callback(request):
       """Analyze the token returned by the authentication provider (OP)."""
  +    global CLIENT
       try:
  +        # If the CLIENT is none, attempt to reinitialize before handling the request
  +        if _client_is_none():
  +            logger.debug("OIDC client is None, attempting to initialize")
  +            _initialize_client()
           query = parse_qs(request.GET.urlencode())
           userinfo = CLIENT.callback(query, request.session)
           # test for need for identity verification and if it is satisfied
           # if not satisfied, redirect user to login with stepped up acr_value
  -        if requires_step_up_auth(userinfo):
  +        if _requires_step_up_auth(userinfo):
               # add acr_value to request.session
               request.session["acr_value"] = CLIENT.get_step_up_acr_value()
               return CLIENT.create_authn_request(request.session)
  @@ -86,13 +113,16 @@
           else:
               raise o_e.BannedUser()
       except o_e.NoStateDefined as nsd_err:
  +        # In the event that a user is in the middle of a login when the app is restarted,
  +        # their session state will no longer be available, so redirect the user to the
  +        # beginning of login process without raising an error to the user.
           logger.warning(f"No State Defined: {nsd_err}")
           return redirect(request.session.get("next", "/"))
       except Exception as err:
           return error_page(request, err)
   
   
  -def requires_step_up_auth(userinfo):
  +def _requires_step_up_auth(userinfo):
       """if User.needs_identity_verification and step_up_acr_value not in
       ial returned from callback, return True"""
       step_up_acr_value = CLIENT.get_step_up_acr_value()
  
verification_info: {"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@@ -15,15 +15,34 @@\n \n logger = logging.getLogger(__name__)\n \n-try:\n+CLIENT = None\n+\n+\n+def _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+    logger.debug(\"Client initialized: %s\" % CLIENT)\n+\n+\n+def _client_is_none():\n+    \"\"\"Return if the CLIENT is currently None.\"\"\"\n+    global CLIENT\n+    return CLIENT is None\n+\n+\n+# Initialize CLIENT\n+try:\n+    _initialize_client()\n except Exception as err:\n-    CLIENT = None  # type: ignore\n-    logger.warning(err)\n-    logger.warning(\"Unable to configure OpenID Connect provider. Users cannot log in.\")\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 \n def error_page(request, error):\n@@ -55,12 +74,15 @@\n \n def openid(request):\n     \"\"\"Redirect the user to an authentication provider (OP).\"\"\"\n-    # If the session reset because of a server restart, attempt to login again\n-    request.session[\"acr_value\"] = CLIENT.get_default_acr_value()\n-\n-    request.session[\"next\"] = request.GET.get(\"next\", \"/\")\n-\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@@ -68,12 +90,17 @@\n \n def 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+        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@@ -86,13 +113,16 @@\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 \n-def requires_step_up_auth(userinfo):\n+def _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", "issue": "Increase reliability on OIDC connection\n### Issue description\n\nWhile investigating #1726  we realized there is some areas for improvement in our handling of the connection to OIDC so that all scenarios of failure show a properly formatted 500 error page\n\n### Acceptance criteria\n\n- [ ] Make sure all login.gov/identity sandbox connection issues result in the usual 500 error \r\n- [ ] refactor the connection set up as needed\n\n### Additional context\n\n_No response_\n\n### Links to other issues\n\nrelates to: #1726\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\ntry:\n    # Initialize provider using pyOICD\n    OP = getattr(settings, \"OIDC_ACTIVE_PROVIDER\")\n    CLIENT = Client(OP)\n    logger.debug(\"client initialized %s\" % CLIENT)\nexcept Exception as err:\n    CLIENT = None  # type: ignore\n    logger.warning(err)\n    logger.warning(\"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    # If the session reset because of a server restart, attempt to login again\n    request.session[\"acr_value\"] = CLIENT.get_default_acr_value()\n\n    request.session[\"next\"] = request.GET.get(\"next\", \"/\")\n\n    try:\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    try:\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        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            \"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"}]}