8000 feat:(oidc) derive audience claim from client_id in IdentityToken (#1… · SequeI/sigstore-python@33e2765 · GitHub
[go: up one dir, main page]

Skip to content

Commit 33e2765

Browse files
authored
feat:(oidc) derive audience claim from client_id in IdentityToken (sigstore#1402)
1 parent 0fcbdc7 commit 33e2765

File tree

6 files changed

+22
-17
lines changed

6 files changed

+22
-17
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ All versions prior to 0.9.0 are untracked.
1616

1717
* Added support for ed25519 keys.
1818
[#1377](https://github.com/sigstore/sigstore-python/pull/1377)
19+
* API: `IdentityToken` now supports `client_id` for audience claim validation.
20+
[#1402](https://github.com/sigstore/sigstore-python/pull/1402)
21+
1922

2023
### Fixed
2124

mkdocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,4 @@ extra:
8080
- icon: fontawesome/brands/slack
8181
link: https://sigstore.slack.com
8282
- icon: fontawesome/brands/x-twitter
83-
link: https://twitter.com/projectsigstore
83+
link: https://twitter.com/projectsigstore

sigstore/_cli.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ def _sign_common(
659659
# 3) Interactive OAuth flow
660660
identity: IdentityToken | None
661661
if args.identity_token:
662-
identity = IdentityToken(args.identity_token)
662+
identity = IdentityToken(args.identity_token, args.oidc_client_id)
663663
else:
664664
identity = _get_identity(args, trust_config)
665665

@@ -1181,11 +1181,11 @@ def _get_identity(
11811181
) -> Optional[IdentityToken]:
11821182
token = None
11831183
if not args.oidc_disable_ambient_providers:
1184-
token = detect_credential()
1184+
token = detect_credential(args.oidc_client_id)
11851185

11861186
# Happy path: we've detected an ambient credential, so we can return early.
11871187
if token:
1188-
return IdentityToken(token)
1188+
return IdentityToken(token, args.oidc_client_id)
11891189

11901190
if args.oidc_issuer is not None:
11911191
issuer = Issuer(args.oidc_issuer)

sigstore/oidc.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
"https://oauth2.sigstage.dev/auth": "email",
4242
"https://token.actions.githubusercontent.com": "sub",
4343
}
44-
_DEFAULT_AUDIENCE = "sigstore"
44+
45+
_DEFAULT_CLIENT_ID = "sigstore"
4546

4647

4748
class _OpenIDConfiguration(BaseModel):
@@ -66,7 +67,7 @@ class IdentityToken:
6667
a sensible subject, issuer, and audience for Sigstore purposes.
6768
"""
6869

69-
def __init__(self, raw_token: str) -> None:
70+
def __init__(self, raw_token: str, client_id: str = _DEFAULT_CLIENT_ID) -> None:
7071
"""
7172
Create a new `IdentityToken` from the given OIDC token.
7273
"""
@@ -90,7 +91,7 @@ def __init__(self, raw_token: str) -> None:
9091
# See: https://openid.net/specs/openid-connect-basic-1_0.html#IDToken
9192
"require": ["aud", "sub", "iat", "exp", "iss"],
9293
},
93-
audience=_DEFAULT_AUDIENCE,
94+
audience=client_id,
9495
# NOTE: This leeway shouldn't be strictly necessary, but is
9596
# included to preempt any (small) skew between the host
9697
# and the originating IdP.
@@ -270,7 +271,7 @@ def __init__(self, base_url: str) -> None:
270271

271272
def identity_token( # nosec: B107
272273
self,
273-
client_id: str = "sigstore",
274+
client_id: str = _DEFAULT_CLIENT_ID,
274275
client_secret: str = "",
275276
force_oob: bool = False,
276277
) -> IdentityToken:
@@ -350,7 +351,7 @@ def identity_token( # nosec: B107
350351
if token_error is not None:
351352
raise IdentityError(f"Error response from token endpoint: {token_error}")
352353

353-
return IdentityToken(token_json["access_token"])
354+
return IdentityToken(token_json["access_token"], client_id)
354355

355356

356357
class IdentityError(Error):
@@ -402,9 +403,10 @@ def diagnostics(self) -> str:
402403
"""
403404

404405

405-
def detect_credential() -> Optional[str]:
406+
def detect_credential(client_id: str = _DEFAULT_CLIENT_ID) -> Optional[str]:
406407
"""Calls `id.detect_credential`, but wraps exceptions with our own exception type."""
408+
407409
try:
408-
return cast(Optional[str], id.detect_credential(_DEFAULT_AUDIENCE))
410+
return cast(Optional[str], id.detect_credential(client_id))
409411
except id.IdentityError as exc:
410412
IdentityError.raise_from_id(exc)

test/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
detect_credential,
2323
)
2424

25-
from sigstore.oidc import _DEFAULT_AUDIENCE
26-
2725
_ASSETS = (Path(__file__).parent / "assets").resolve()
2826
assert _ASSETS.is_dir()
2927

28+
TEST_CLIENT_ID = "sigstore"
29+
3030

3131
@pytest.fixture
3232
def asset():
@@ -44,7 +44,7 @@ def _has_oidc_id():
4444
return True
4545

4646
try:
47-
token = detect_credential(_DEFAULT_AUDIENCE)
47+
token = detect_credential(TEST_CLIENT_ID)
4848
if token is None:
4949
return False
5050
except GitHubOidcPermissionCredentialError:

test/unit/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
from sigstore._internal.trust import ClientTrustConfig
4141
from sigstore._utils import sha256_digest
4242
from sigstore.models import Bundle
43-
from sigstore.oidc import _DEFAULT_AUDIENCE, IdentityToken
43+
from sigstore.oidc import IdentityToken
4444
from sigstore.sign import SigningContext
4545
from sigstore.verify.verifier import Verifier
4646

@@ -209,7 +209,7 @@ def ctx_cls():
209209
token = os.getenv(f"SIGSTORE_IDENTITY_TOKEN_{env}")
210210
if not token:
211211
# If the variable is not defined, try getting an ambient token.
212-
token = detect_credential(_DEFAULT_AUDIENCE)
212+
token = detect_credential()
213213

214214
return ctx_cls, IdentityToken(token)
215215

@@ -230,7 +230,7 @@ def signer():
230230
token = os.getenv("SIGSTORE_IDENTITY_TOKEN_staging")
231231
if not token:
232232
# If the variable is not defined, try getting an ambient token.
233-
token = detect_credential(_DEFAULT_AUDIENCE)
233+
token = detect_credential()
234234

235235
return signer, verifier, IdentityToken(token)
236236

0 commit comments

Comments
 (0)
0