This is an automated email from the ASF dual-hosted git repository.
sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-trusted-release.git
The following commit(s) were added to refs/heads/main by this push:
new 23b4093 Use JWKS validation for GitHub OIDC JWTs
23b4093 is described below
commit 23b4093cb66fcd26a28ffc8b69d1d2700abdc98c
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Aug 14 20:03:16 2025 +0100
Use JWKS validation for GitHub OIDC JWTs
---
atr/blueprints/api/api.py | 10 ++++++----
atr/jwtoken.py | 27 +++++++++++++++++++++++++++
2 files changed, 33 insertions(+), 4 deletions(-)
diff --git a/atr/blueprints/api/api.py b/atr/blueprints/api/api.py
index 2bec872..c4dcd87 100644
--- a/atr/blueprints/api/api.py
+++ b/atr/blueprints/api/api.py
@@ -18,7 +18,6 @@
import base64
import hashlib
-import json
import pathlib
from typing import Any
@@ -360,9 +359,12 @@ async def jwt_github(data: models.api.JwtGithubArgs) ->
DictResponse:
The payload must include a valid GitHub OIDC JWT.
"""
# TODO: This is a placeholder for the actual implementation
- unverified_header_and_payload =
jwtoken.unverified_header_and_payload(data.jwt)
- unverified_header_and_payload_json =
json.dumps(unverified_header_and_payload).encode("utf-8")
- log.secret("GitHub OIDC JWT header and payload",
unverified_header_and_payload_json)
+ payload = await jwtoken.verify_github_oidc(data.jwt)
+ del payload["actor_id"]
+ del payload["repository_id"]
+ del payload["repository_owner_id"]
+ del payload["run_id"]
+ log.info(f"GitHub OIDC JWT payload: {payload}")
return models.api.JwtGithubResults(
endpoint="/jwt/github",
diff --git a/atr/jwtoken.py b/atr/jwtoken.py
index eb2857f..934f8d3 100644
--- a/atr/jwtoken.py
+++ b/atr/jwtoken.py
@@ -22,6 +22,7 @@ import functools
import secrets as secrets
from typing import TYPE_CHECKING, Any, Final
+import aiohttp
import asfquart.base as base
import jwt
import quart
@@ -76,6 +77,32 @@ def verify(token: str) -> dict[str, Any]:
return jwt.decode(token, _SECRET_KEY, algorithms=[_ALGORITHM])
+async def verify_github_oidc(token: str) -> dict[str, Any]:
+ issuer = "token.actions.githubusercontent.com"
+ try:
+ async with aiohttp.ClientSession() as session:
+ r = await session.get(
+ f"https://{issuer}/.well-known/openid-configuration",
+ timeout=aiohttp.ClientTimeout(total=5),
+ )
+ r.raise_for_status()
+ jwks_uri = (await r.json())["jwks_uri"]
+ except Exception:
+ jwks_uri = f"https://{issuer}/.well-known/jwks"
+
+ jwks_client = jwt.PyJWKClient(jwks_uri)
+ signing_key = jwks_client.get_signing_key_from_jwt(token)
+ payload = jwt.decode(
+ token,
+ key=signing_key.key,
+ algorithms=["RS256"],
+ audience="atr-test",
+ issuer=f"https://{issuer}",
+ options={"require": ["exp", "iat"]},
+ )
+ return payload
+
+
def _extract_bearer_token(request: quart.Request) -> str:
header = request.headers.get("Authorization", "")
scheme, _, token = header.partition(" ")
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]