Skip to content

Commit 71a0032

Browse files
committed
oidc-exchange: render claims if exchange fails
Signed-off-by: William Woodruff <william@trailofbits.com>
1 parent 413a8d5 commit 71a0032

File tree

1 file changed

+45
-1
lines changed

1 file changed

+45
-1
lines changed

oidc-exchange.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import base64
2+
import json
13
import os
24
import sys
35
from http import HTTPStatus
@@ -50,6 +52,25 @@
5052
Token request failed: the server refused the request for the following reasons:
5153
5254
{reasons}
55+
56+
This generally indicates a trusted publisher configuration error, but could
57+
also indicate an internal error on GitHub or PyPI's part.
58+
59+
{rendered_claims}
60+
"""
61+
62+
_RENDERED_CLAIMS = """
63+
The claims rendered below are **for debugging purposes only**. You should **not**
64+
use them to configure a trusted publisher unless they already match your expectations.
65+
66+
If a claim is not present in the claim set, then it is rendered as `MISSING`.
67+
68+
* `sub`: `{sub}`
69+
* `repository`: `{repository}`
70+
* `repository_owner`: `{repository_owner}`
71+
* `repository_owner_id`: `{repository_owner_id}`
72+
* `job_workflow_ref`: `{job_workflow_ref}`
73+
* `ref`: `{ref}`
5374
"""
5475

5576
# Rendered if the package index's token response isn't valid JSON.
@@ -121,6 +142,23 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):
121142
)
122143

123144

145+
def render_claims(oidc_token: str) -> str:
146+
_, payload, _ = oidc_token.split(".", 2)
147+
claims = json.loads(base64.urlsafe_b64decode(payload))
148+
149+
def _get(name: str) -> str:
150+
return claims.get(name, "MISSING")
151+
152+
return _RENDERED_CLAIMS.format(
153+
sub=_get("sub"),
154+
repository=_get("repository"),
155+
repository_owner=_get("repository_owner"),
156+
repository_owner_id=_get("repository_owner_id"),
157+
job_workflow_ref=_get("job_workflow_ref"),
158+
ref=_get("ref"),
159+
)
160+
161+
124162
repository_url = get_normalized_input("repository-url")
125163
repository_domain = urlparse(repository_url).netloc
126164
token_exchange_url = f"https://{repository_domain}/_/oidc/github/mint-token"
@@ -165,7 +203,13 @@ def assert_successful_audience_call(resp: requests.Response, domain: str):
165203
for error in mint_token_payload["errors"]
166204
)
167205

168-
die(_SERVER_REFUSED_TOKEN_EXCHANGE_MESSAGE.format(reasons=reasons))
206+
rendered_claims = render_claims(oidc_token)
207+
208+
die(
209+
_SERVER_REFUSED_TOKEN_EXCHANGE_MESSAGE.format(
210+
reasons=reasons, rendered_claims=rendered_claims
211+
)
212+
)
169213

170214
pypi_token = mint_token_payload.get("token")
171215
if pypi_token is None:

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy