We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Improve analytics for auth claims flow
With the move to integer claims in #2046, IdG will return error codes in place of True (`0`) or False (`1`) when an error occurs in processing the user's eligibility. Any integer that is greater than or equal to `10` is considered an error code.

We want to improve our analytics around the auth flow, in particular to capture any errors that occur as described by IdG error codes.

## Acceptance Criteria

<!-- Remember to consider edge cases -->

- [x] The [`FinishedSignInEvent`](https://github.com/cal-itp/benefits/blob/dev/benefits/oauth/analytics.py#L32) is updated to allow an optional `error_code` event property.
- [x] The `error_code` property is the integer value of the claim error code (originally transmitted as a string)

## Additional context

In #2046, we will handle the regular True (`0`) / False (`1`) cases.

This issue has been scoped back to exclude lookup of the error message associated with a given code. This needs further discussion and design with CDT.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `benefits/oauth/analytics.py`
Content:
```
1 """
2 The oauth application: analytics implementation.
3 """
4 
5 from benefits.core import analytics as core, session
6 
7 
8 class OAuthEvent(core.Event):
9     """Base OAuth analytics event."""
10 
11     def __init__(self, request, event_type):
12         super().__init__(request, event_type)
13         verifier = session.verifier(request)
14         if verifier and verifier.uses_auth_verification:
15             self.update_event_properties(auth_provider=verifier.auth_provider.client_name)
16 
17 
18 class StartedSignInEvent(OAuthEvent):
19     """Analytics event representing the beginning of the OAuth sign in flow."""
20 
21     def __init__(self, request):
22         super().__init__(request, "started sign in")
23 
24 
25 class CanceledSignInEvent(OAuthEvent):
26     """Analytics event representing the canceling of application sign in."""
27 
28     def __init__(self, request):
29         super().__init__(request, "canceled sign in")
30 
31 
32 class FinishedSignInEvent(OAuthEvent):
33     """Analytics event representing the end of the OAuth sign in flow."""
34 
35     def __init__(self, request):
36         super().__init__(request, "finished sign in")
37 
38 
39 class StartedSignOutEvent(OAuthEvent):
40     """Analytics event representing the beginning of application sign out."""
41 
42     def __init__(self, request):
43         super().__init__(request, "started sign out")
44 
45 
46 class FinishedSignOutEvent(OAuthEvent):
47     """Analytics event representing the end of application sign out."""
48 
49     def __init__(self, request):
50         super().__init__(request, "finished sign out")
51         self.update_event_properties(origin=session.origin(request))
52 
53 
54 def started_sign_in(request):
55     """Send the "started sign in" analytics event."""
56     core.send_event(StartedSignInEvent(request))
57 
58 
59 def canceled_sign_in(request):
60     """Send the "canceled sign in" analytics event."""
61     core.send_event(CanceledSignInEvent(request))
62 
63 
64 def finished_sign_in(request):
65     """Send the "finished sign in" analytics event."""
66     core.send_event(FinishedSignInEvent(request))
67 
68 
69 def started_sign_out(request):
70     """Send the "started signed out" analytics event."""
71     core.send_event(StartedSignOutEvent(request))
72 
73 
74 def finished_sign_out(request):
75     """Send the "finished sign out" analytics event."""
76     core.send_event(FinishedSignOutEvent(request))
77
```

Path: `benefits/oauth/views.py`
Content:
```
1 import logging
2 
3 from django.shortcuts import redirect
4 from django.urls import reverse
5 from django.utils.decorators import decorator_from_middleware
6 
7 from benefits.core import session
8 from . import analytics, redirects
9 from .client import oauth
10 from .middleware import VerifierUsesAuthVerificationSessionRequired
11 
12 
13 logger = logging.getLogger(__name__)
14 
15 
16 ROUTE_AUTH = "oauth:authorize"
17 ROUTE_START = "eligibility:start"
18 ROUTE_CONFIRM = "eligibility:confirm"
19 ROUTE_UNVERIFIED = "eligibility:unverified"
20 ROUTE_POST_LOGOUT = "oauth:post_logout"
21 
22 
23 @decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)
24 def login(request):
25     """View implementing OIDC authorize_redirect."""
26     verifier = session.verifier(request)
27     oauth_client = oauth.create_client(verifier.auth_provider.client_name)
28 
29     if not oauth_client:
30         raise Exception(f"oauth_client not registered: {verifier.auth_provider.client_name}")
31 
32     route = reverse(ROUTE_AUTH)
33     redirect_uri = redirects.generate_redirect_uri(request, route)
34 
35     logger.debug(f"OAuth authorize_redirect with redirect_uri: {redirect_uri}")
36 
37     analytics.started_sign_in(request)
38 
39     return oauth_client.authorize_redirect(request, redirect_uri)
40 
41 
42 @decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)
43 def authorize(request):
44     """View implementing OIDC token authorization."""
45     verifier = session.verifier(request)
46     oauth_client = oauth.create_client(verifier.auth_provider.client_name)
47 
48     if not oauth_client:
49         raise Exception(f"oauth_client not registered: {verifier.auth_provider.client_name}")
50 
51     logger.debug("Attempting to authorize OAuth access token")
52     token = oauth_client.authorize_access_token(request)
53 
54     if token is None:
55         logger.warning("Could not authorize OAuth access token")
56         return redirect(ROUTE_START)
57 
58     logger.debug("OAuth access token authorized")
59 
60     # We store the id_token in the user's session. This is the minimal amount of information needed later to log the user out.
61     id_token = token["id_token"]
62 
63     # We store the returned claim in case it can be used later in eligibility verification.
64     verifier_claim = verifier.auth_provider.claim
65     stored_claim = None
66 
67     if verifier_claim:
68         userinfo = token.get("userinfo")
69 
70         if userinfo:
71             claim_value = userinfo.get(verifier_claim)
72             # the claim comes back in userinfo like { "claim": "1" | "0" }
73             claim_value = int(claim_value) if claim_value else None
74             if claim_value is None:
75                 logger.warning(f"userinfo did not contain: {verifier_claim}")
76             elif claim_value == 1:
77                 # if userinfo contains our claim and the flag is 1 (true), store the *claim*
78                 stored_claim = verifier_claim
79 
80     session.update(request, oauth_token=id_token, oauth_claim=stored_claim)
81 
82     analytics.finished_sign_in(request)
83 
84     return redirect(ROUTE_CONFIRM)
85 
86 
87 @decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)
88 def cancel(request):
89     """View implementing cancellation of OIDC authorization."""
90 
91     analytics.canceled_sign_in(request)
92 
93     return redirect(ROUTE_UNVERIFIED)
94 
95 
96 @decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)
97 def logout(request):
98     """View implementing OIDC and application sign out."""
99     verifier = session.verifier(request)
100     oauth_client = oauth.create_client(verifier.auth_provider.client_name)
101 
102     if not oauth_client:
103         raise Exception(f"oauth_client not registered: {verifier.auth_provider.client_name}")
104 
105     analytics.started_sign_out(request)
106 
107     # overwrite the oauth session token, the user is signed out of the app
108     token = session.oauth_token(request)
109     session.logout(request)
110 
111     route = reverse(ROUTE_POST_LOGOUT)
112     redirect_uri = redirects.generate_redirect_uri(request, route)
113 
114     logger.debug(f"OAuth end_session_endpoint with redirect_uri: {redirect_uri}")
115 
116     # send the user through the end_session_endpoint, redirecting back to
117     # the post_logout route
118     return redirects.deauthorize_redirect(oauth_client, token, redirect_uri)
119 
120 
121 @decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)
122 def post_logout(request):
123     """View routes the user to their origin after sign out."""
124 
125     analytics.finished_sign_out(request)
126 
127     origin = session.origin(request)
128     return redirect(origin)
129
```
--- 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/benefits/oauth/analytics.py b/benefits/oauth/analytics.py
--- a/benefits/oauth/analytics.py
+++ b/benefits/oauth/analytics.py
@@ -32,8 +32,10 @@
 class FinishedSignInEvent(OAuthEvent):
     """Analytics event representing the end of the OAuth sign in flow."""
 
-    def __init__(self, request):
+    def __init__(self, request, error=None):
         super().__init__(request, "finished sign in")
+        if error is not None:
+            self.update_event_properties(error_code=error)
 
 
 class StartedSignOutEvent(OAuthEvent):
@@ -61,9 +63,9 @@
     core.send_event(CanceledSignInEvent(request))
 
 
-def finished_sign_in(request):
+def finished_sign_in(request, error=None):
     """Send the "finished sign in" analytics event."""
-    core.send_event(FinishedSignInEvent(request))
+    core.send_event(FinishedSignInEvent(request, error))
 
 
 def started_sign_out(request):
diff --git a/benefits/oauth/views.py b/benefits/oauth/views.py
--- a/benefits/oauth/views.py
+++ b/benefits/oauth/views.py
@@ -64,6 +64,8 @@
     verifier_claim = verifier.auth_provider.claim
     stored_claim = None
 
+    error_claim = None
+
     if verifier_claim:
         userinfo = token.get("userinfo")
 
@@ -76,10 +78,11 @@
             elif claim_value == 1:
                 # if userinfo contains our claim and the flag is 1 (true), store the *claim*
                 stored_claim = verifier_claim
+            elif claim_value >= 10:
+                error_claim = claim_value
 
     session.update(request, oauth_token=id_token, oauth_claim=stored_claim)
-
-    analytics.finished_sign_in(request)
+    analytics.finished_sign_in(request, error=error_claim)
 
     return redirect(ROUTE_CONFIRM)

{"golden_diff": "diff --git a/benefits/oauth/analytics.py b/benefits/oauth/analytics.py\n--- a/benefits/oauth/analytics.py\n+++ b/benefits/oauth/analytics.py\n@@ -32,8 +32,10 @@\n class FinishedSignInEvent(OAuthEvent):\n     \"\"\"Analytics event representing the end of the OAuth sign in flow.\"\"\"\n \n-    def __init__(self, request):\n+    def __init__(self, request, error=None):\n         super().__init__(request, \"finished sign in\")\n+        if error is not None:\n+            self.update_event_properties(error_code=error)\n \n \n class StartedSignOutEvent(OAuthEvent):\n@@ -61,9 +63,9 @@\n     core.send_event(CanceledSignInEvent(request))\n \n \n-def finished_sign_in(request):\n+def finished_sign_in(request, error=None):\n     \"\"\"Send the \"finished sign in\" analytics event.\"\"\"\n-    core.send_event(FinishedSignInEvent(request))\n+    core.send_event(FinishedSignInEvent(request, error))\n \n \n def started_sign_out(request):\ndiff --git a/benefits/oauth/views.py b/benefits/oauth/views.py\n--- a/benefits/oauth/views.py\n+++ b/benefits/oauth/views.py\n@@ -64,6 +64,8 @@\n     verifier_claim = verifier.auth_provider.claim\n     stored_claim = None\n \n+    error_claim = None\n+\n     if verifier_claim:\n         userinfo = token.get(\"userinfo\")\n \n@@ -76,10 +78,11 @@\n             elif claim_value == 1:\n                 # if userinfo contains our claim and the flag is 1 (true), store the *claim*\n                 stored_claim = verifier_claim\n+            elif claim_value >= 10:\n+                error_claim = claim_value\n \n     session.update(request, oauth_token=id_token, oauth_claim=stored_claim)\n-\n-    analytics.finished_sign_in(request)\n+    analytics.finished_sign_in(request, error=error_claim)\n \n     return redirect(ROUTE_CONFIRM)\n", "issue": "Improve analytics for auth claims flow\nWith the move to integer claims in #2046, IdG will return error codes in place of True (`0`) or False (`1`) when an error occurs in processing the user's eligibility. Any integer that is greater than or equal to `10` is considered an error code.\n\nWe want to improve our analytics around the auth flow, in particular to capture any errors that occur as described by IdG error codes.\n\n## Acceptance Criteria\n\n<!-- Remember to consider edge cases -->\n\n- [x] The [`FinishedSignInEvent`](https://github.com/cal-itp/benefits/blob/dev/benefits/oauth/analytics.py#L32) is updated to allow an optional `error_code` event property.\n- [x] The `error_code` property is the integer value of the claim error code (originally transmitted as a string)\n\n## Additional context\n\nIn #2046, we will handle the regular True (`0`) / False (`1`) cases.\n\nThis issue has been scoped back to exclude lookup of the error message associated with a given code. This needs further discussion and design with CDT.\n", "before_files": [{"content": "\"\"\"\nThe oauth application: analytics implementation.\n\"\"\"\n\nfrom benefits.core import analytics as core, session\n\n\nclass OAuthEvent(core.Event):\n    \"\"\"Base OAuth analytics event.\"\"\"\n\n    def __init__(self, request, event_type):\n        super().__init__(request, event_type)\n        verifier = session.verifier(request)\n        if verifier and verifier.uses_auth_verification:\n            self.update_event_properties(auth_provider=verifier.auth_provider.client_name)\n\n\nclass StartedSignInEvent(OAuthEvent):\n    \"\"\"Analytics event representing the beginning of the OAuth sign in flow.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"started sign in\")\n\n\nclass CanceledSignInEvent(OAuthEvent):\n    \"\"\"Analytics event representing the canceling of application sign in.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"canceled sign in\")\n\n\nclass FinishedSignInEvent(OAuthEvent):\n    \"\"\"Analytics event representing the end of the OAuth sign in flow.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"finished sign in\")\n\n\nclass StartedSignOutEvent(OAuthEvent):\n    \"\"\"Analytics event representing the beginning of application sign out.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"started sign out\")\n\n\nclass FinishedSignOutEvent(OAuthEvent):\n    \"\"\"Analytics event representing the end of application sign out.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"finished sign out\")\n        self.update_event_properties(origin=session.origin(request))\n\n\ndef started_sign_in(request):\n    \"\"\"Send the \"started sign in\" analytics event.\"\"\"\n    core.send_event(StartedSignInEvent(request))\n\n\ndef canceled_sign_in(request):\n    \"\"\"Send the \"canceled sign in\" analytics event.\"\"\"\n    core.send_event(CanceledSignInEvent(request))\n\n\ndef finished_sign_in(request):\n    \"\"\"Send the \"finished sign in\" analytics event.\"\"\"\n    core.send_event(FinishedSignInEvent(request))\n\n\ndef started_sign_out(request):\n    \"\"\"Send the \"started signed out\" analytics event.\"\"\"\n    core.send_event(StartedSignOutEvent(request))\n\n\ndef finished_sign_out(request):\n    \"\"\"Send the \"finished sign out\" analytics event.\"\"\"\n    core.send_event(FinishedSignOutEvent(request))\n", "path": "benefits/oauth/analytics.py"}, {"content": "import logging\n\nfrom django.shortcuts import redirect\nfrom django.urls import reverse\nfrom django.utils.decorators import decorator_from_middleware\n\nfrom benefits.core import session\nfrom . import analytics, redirects\nfrom .client import oauth\nfrom .middleware import VerifierUsesAuthVerificationSessionRequired\n\n\nlogger = logging.getLogger(__name__)\n\n\nROUTE_AUTH = \"oauth:authorize\"\nROUTE_START = \"eligibility:start\"\nROUTE_CONFIRM = \"eligibility:confirm\"\nROUTE_UNVERIFIED = \"eligibility:unverified\"\nROUTE_POST_LOGOUT = \"oauth:post_logout\"\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef login(request):\n    \"\"\"View implementing OIDC authorize_redirect.\"\"\"\n    verifier = session.verifier(request)\n    oauth_client = oauth.create_client(verifier.auth_provider.client_name)\n\n    if not oauth_client:\n        raise Exception(f\"oauth_client not registered: {verifier.auth_provider.client_name}\")\n\n    route = reverse(ROUTE_AUTH)\n    redirect_uri = redirects.generate_redirect_uri(request, route)\n\n    logger.debug(f\"OAuth authorize_redirect with redirect_uri: {redirect_uri}\")\n\n    analytics.started_sign_in(request)\n\n    return oauth_client.authorize_redirect(request, redirect_uri)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef authorize(request):\n    \"\"\"View implementing OIDC token authorization.\"\"\"\n    verifier = session.verifier(request)\n    oauth_client = oauth.create_client(verifier.auth_provider.client_name)\n\n    if not oauth_client:\n        raise Exception(f\"oauth_client not registered: {verifier.auth_provider.client_name}\")\n\n    logger.debug(\"Attempting to authorize OAuth access token\")\n    token = oauth_client.authorize_access_token(request)\n\n    if token is None:\n        logger.warning(\"Could not authorize OAuth access token\")\n        return redirect(ROUTE_START)\n\n    logger.debug(\"OAuth access token authorized\")\n\n    # We store the id_token in the user's session. This is the minimal amount of information needed later to log the user out.\n    id_token = token[\"id_token\"]\n\n    # We store the returned claim in case it can be used later in eligibility verification.\n    verifier_claim = verifier.auth_provider.claim\n    stored_claim = None\n\n    if verifier_claim:\n        userinfo = token.get(\"userinfo\")\n\n        if userinfo:\n            claim_value = userinfo.get(verifier_claim)\n            # the claim comes back in userinfo like { \"claim\": \"1\" | \"0\" }\n            claim_value = int(claim_value) if claim_value else None\n            if claim_value is None:\n                logger.warning(f\"userinfo did not contain: {verifier_claim}\")\n            elif claim_value == 1:\n                # if userinfo contains our claim and the flag is 1 (true), store the *claim*\n                stored_claim = verifier_claim\n\n    session.update(request, oauth_token=id_token, oauth_claim=stored_claim)\n\n    analytics.finished_sign_in(request)\n\n    return redirect(ROUTE_CONFIRM)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef cancel(request):\n    \"\"\"View implementing cancellation of OIDC authorization.\"\"\"\n\n    analytics.canceled_sign_in(request)\n\n    return redirect(ROUTE_UNVERIFIED)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef logout(request):\n    \"\"\"View implementing OIDC and application sign out.\"\"\"\n    verifier = session.verifier(request)\n    oauth_client = oauth.create_client(verifier.auth_provider.client_name)\n\n    if not oauth_client:\n        raise Exception(f\"oauth_client not registered: {verifier.auth_provider.client_name}\")\n\n    analytics.started_sign_out(request)\n\n    # overwrite the oauth session token, the user is signed out of the app\n    token = session.oauth_token(request)\n    session.logout(request)\n\n    route = reverse(ROUTE_POST_LOGOUT)\n    redirect_uri = redirects.generate_redirect_uri(request, route)\n\n    logger.debug(f\"OAuth end_session_endpoint with redirect_uri: {redirect_uri}\")\n\n    # send the user through the end_session_endpoint, redirecting back to\n    # the post_logout route\n    return redirects.deauthorize_redirect(oauth_client, token, redirect_uri)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef post_logout(request):\n    \"\"\"View routes the user to their origin after sign out.\"\"\"\n\n    analytics.finished_sign_out(request)\n\n    origin = session.origin(request)\n    return redirect(origin)\n", "path": "benefits/oauth/views.py"}], "after_files": [{"content": "\"\"\"\nThe oauth application: analytics implementation.\n\"\"\"\n\nfrom benefits.core import analytics as core, session\n\n\nclass OAuthEvent(core.Event):\n    \"\"\"Base OAuth analytics event.\"\"\"\n\n    def __init__(self, request, event_type):\n        super().__init__(request, event_type)\n        verifier = session.verifier(request)\n        if verifier and verifier.uses_auth_verification:\n            self.update_event_properties(auth_provider=verifier.auth_provider.client_name)\n\n\nclass StartedSignInEvent(OAuthEvent):\n    \"\"\"Analytics event representing the beginning of the OAuth sign in flow.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"started sign in\")\n\n\nclass CanceledSignInEvent(OAuthEvent):\n    \"\"\"Analytics event representing the canceling of application sign in.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"canceled sign in\")\n\n\nclass FinishedSignInEvent(OAuthEvent):\n    \"\"\"Analytics event representing the end of the OAuth sign in flow.\"\"\"\n\n    def __init__(self, request, error=None):\n        super().__init__(request, \"finished sign in\")\n        if error is not None:\n            self.update_event_properties(error_code=error)\n\n\nclass StartedSignOutEvent(OAuthEvent):\n    \"\"\"Analytics event representing the beginning of application sign out.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"started sign out\")\n\n\nclass FinishedSignOutEvent(OAuthEvent):\n    \"\"\"Analytics event representing the end of application sign out.\"\"\"\n\n    def __init__(self, request):\n        super().__init__(request, \"finished sign out\")\n        self.update_event_properties(origin=session.origin(request))\n\n\ndef started_sign_in(request):\n    \"\"\"Send the \"started sign in\" analytics event.\"\"\"\n    core.send_event(StartedSignInEvent(request))\n\n\ndef canceled_sign_in(request):\n    \"\"\"Send the \"canceled sign in\" analytics event.\"\"\"\n    core.send_event(CanceledSignInEvent(request))\n\n\ndef finished_sign_in(request, error=None):\n    \"\"\"Send the \"finished sign in\" analytics event.\"\"\"\n    core.send_event(FinishedSignInEvent(request, error))\n\n\ndef started_sign_out(request):\n    \"\"\"Send the \"started signed out\" analytics event.\"\"\"\n    core.send_event(StartedSignOutEvent(request))\n\n\ndef finished_sign_out(request):\n    \"\"\"Send the \"finished sign out\" analytics event.\"\"\"\n    core.send_event(FinishedSignOutEvent(request))\n", "path": "benefits/oauth/analytics.py"}, {"content": "import logging\n\nfrom django.shortcuts import redirect\nfrom django.urls import reverse\nfrom django.utils.decorators import decorator_from_middleware\n\nfrom benefits.core import session\nfrom . import analytics, redirects\nfrom .client import oauth\nfrom .middleware import VerifierUsesAuthVerificationSessionRequired\n\n\nlogger = logging.getLogger(__name__)\n\n\nROUTE_AUTH = \"oauth:authorize\"\nROUTE_START = \"eligibility:start\"\nROUTE_CONFIRM = \"eligibility:confirm\"\nROUTE_UNVERIFIED = \"eligibility:unverified\"\nROUTE_POST_LOGOUT = \"oauth:post_logout\"\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef login(request):\n    \"\"\"View implementing OIDC authorize_redirect.\"\"\"\n    verifier = session.verifier(request)\n    oauth_client = oauth.create_client(verifier.auth_provider.client_name)\n\n    if not oauth_client:\n        raise Exception(f\"oauth_client not registered: {verifier.auth_provider.client_name}\")\n\n    route = reverse(ROUTE_AUTH)\n    redirect_uri = redirects.generate_redirect_uri(request, route)\n\n    logger.debug(f\"OAuth authorize_redirect with redirect_uri: {redirect_uri}\")\n\n    analytics.started_sign_in(request)\n\n    return oauth_client.authorize_redirect(request, redirect_uri)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef authorize(request):\n    \"\"\"View implementing OIDC token authorization.\"\"\"\n    verifier = session.verifier(request)\n    oauth_client = oauth.create_client(verifier.auth_provider.client_name)\n\n    if not oauth_client:\n        raise Exception(f\"oauth_client not registered: {verifier.auth_provider.client_name}\")\n\n    logger.debug(\"Attempting to authorize OAuth access token\")\n    token = oauth_client.authorize_access_token(request)\n\n    if token is None:\n        logger.warning(\"Could not authorize OAuth access token\")\n        return redirect(ROUTE_START)\n\n    logger.debug(\"OAuth access token authorized\")\n\n    # We store the id_token in the user's session. This is the minimal amount of information needed later to log the user out.\n    id_token = token[\"id_token\"]\n\n    # We store the returned claim in case it can be used later in eligibility verification.\n    verifier_claim = verifier.auth_provider.claim\n    stored_claim = None\n\n    error_claim = None\n\n    if verifier_claim:\n        userinfo = token.get(\"userinfo\")\n\n        if userinfo:\n            claim_value = userinfo.get(verifier_claim)\n            # the claim comes back in userinfo like { \"claim\": \"1\" | \"0\" }\n            claim_value = int(claim_value) if claim_value else None\n            if claim_value is None:\n                logger.warning(f\"userinfo did not contain: {verifier_claim}\")\n            elif claim_value == 1:\n                # if userinfo contains our claim and the flag is 1 (true), store the *claim*\n                stored_claim = verifier_claim\n            elif claim_value >= 10:\n                error_claim = claim_value\n\n    session.update(request, oauth_token=id_token, oauth_claim=stored_claim)\n    analytics.finished_sign_in(request, error=error_claim)\n\n    return redirect(ROUTE_CONFIRM)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef cancel(request):\n    \"\"\"View implementing cancellation of OIDC authorization.\"\"\"\n\n    analytics.canceled_sign_in(request)\n\n    return redirect(ROUTE_UNVERIFIED)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef logout(request):\n    \"\"\"View implementing OIDC and application sign out.\"\"\"\n    verifier = session.verifier(request)\n    oauth_client = oauth.create_client(verifier.auth_provider.client_name)\n\n    if not oauth_client:\n        raise Exception(f\"oauth_client not registered: {verifier.auth_provider.client_name}\")\n\n    analytics.started_sign_out(request)\n\n    # overwrite the oauth session token, the user is signed out of the app\n    token = session.oauth_token(request)\n    session.logout(request)\n\n    route = reverse(ROUTE_POST_LOGOUT)\n    redirect_uri = redirects.generate_redirect_uri(request, route)\n\n    logger.debug(f\"OAuth end_session_endpoint with redirect_uri: {redirect_uri}\")\n\n    # send the user through the end_session_endpoint, redirecting back to\n    # the post_logout route\n    return redirects.deauthorize_redirect(oauth_client, token, redirect_uri)\n\n\n@decorator_from_middleware(VerifierUsesAuthVerificationSessionRequired)\ndef post_logout(request):\n    \"\"\"View routes the user to their origin after sign out.\"\"\"\n\n    analytics.finished_sign_out(request)\n\n    origin = session.origin(request)\n    return redirect(origin)\n", "path": "benefits/oauth/views.py"}]}