Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ All versions prior to 0.9.0 are untracked.

* Added support for ed25519 keys.
[#1377](https://github.com/sigstore/sigstore-python/pull/1377)
* Added client_id as the audience (aud) claim when initializing IdentityToken
[#1402](https://github.com/sigstore/sigstore-python/pull/1402)


### Fixed

Expand Down
3 changes: 1 addition & 2 deletions sigstore/_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def _add_shared_oidc_options(
"--oidc-client-id",
metavar="ID",
type=str,
default=os.getenv("SIGSTORE_OIDC_CLIENT_ID", "sigstore"),
default=os.getenv("SIGSTORE_OIDC_CLIENT_ID"),
help="The custom OpenID Connect client ID to use during OAuth2",
)
group.add_argument(
Expand Down Expand Up @@ -238,7 +238,6 @@ def _add_shared_oidc_options(
help="Force an out-of-band OAuth flow and do not automatically start the default web browser",
)


def _parser() -> argparse.ArgumentParser:
# Arguments in parent_parser can be used for both commands and subcommands
parent_parser = argparse.ArgumentParser(add_help=False)
Expand Down
20 changes: 13 additions & 7 deletions sigstore/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
"https://oauth2.sigstage.dev/auth": "email",
"https://token.actions.githubusercontent.com": "sub",
}
_DEFAULT_AUDIENCE = "sigstore"

_DEFAULT_CLIENT_ID = "sigstore"

class _OpenIDConfiguration(BaseModel):
"""
Expand All @@ -66,7 +66,7 @@ class IdentityToken:
a sensible subject, issuer, and audience for Sigstore purposes.
"""

def __init__(self, raw_token: str) -> None:
def __init__(self, raw_token: str, client_id: str) -> None:
"""
Create a new `IdentityToken` from the given OIDC token.
"""
Expand All @@ -90,7 +90,7 @@ def __init__(self, raw_token: str) -> None:
# See: https://openid.net/specs/openid-connect-basic-1_0.html#IDToken
"require": ["aud", "sub", "iat", "exp", "iss"],
},
audience=_DEFAULT_AUDIENCE,
audience=client_id,
# NOTE: This leeway shouldn't be strictly necessary, but is
# included to preempt any (small) skew between the host
# and the originating IdP.
Expand Down Expand Up @@ -270,7 +270,7 @@ def __init__(self, base_url: str) -> None:

def identity_token( # nosec: B107
self,
client_id: str = "sigstore",
client_id: str = None,
client_secret: str = "",
force_oob: bool = False,
) -> IdentityToken:
Expand All @@ -284,6 +284,8 @@ def identity_token( # nosec: B107
an out-of-band flow. When `True`, the out-of-band flow is always used.
"""

if client_id is None:
client_id = _DEFAULT_CLIENT_ID
# This function and the components that it relies on are based off of:
# https://github.com/psteniusubi/python-sample

Expand Down Expand Up @@ -350,7 +352,7 @@ def identity_token( # nosec: B107
if token_error is not None:
raise IdentityError(f"Error response from token endpoint: {token_error}")

return IdentityToken(token_json["access_token"])
return IdentityToken(token_json["access_token"], client_id)


class IdentityError(Error):
Expand Down Expand Up @@ -402,9 +404,13 @@ def diagnostics(self) -> str:
"""


def detect_credential() -> Optional[str]:
def detect_credential(client_id: Optional[str] = None) -> Optional[str]:
"""Calls `id.detect_credential`, but wraps exceptions with our own exception type."""

if client_id is None:
client_id = _DEFAULT_CLIENT_ID

try:
return cast(Optional[str], id.detect_credential(_DEFAULT_AUDIENCE))
return cast(Optional[str], id.detect_credential(client_id))
except id.IdentityError as exc:
IdentityError.raise_from_id(exc)
3 changes: 1 addition & 2 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
detect_credential,
)

from sigstore.oidc import _DEFAULT_AUDIENCE

_ASSETS = (Path(__file__).parent / "assets").resolve()
assert _ASSETS.is_dir()
Expand All @@ -44,7 +43,7 @@ def _has_oidc_id():
return True

try:
token = detect_credential(_DEFAULT_AUDIENCE)
token = detect_credential()
if token is None:
return False
except GitHubOidcPermissionCredentialError:
Expand Down
6 changes: 3 additions & 3 deletions test/unit/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
from sigstore._internal.rekor.client import RekorClient
from sigstore._utils import sha256_digest
from sigstore.models import Bundle
from sigstore.oidc import _DEFAULT_AUDIENCE, IdentityToken
from sigstore.oidc import IdentityToken
from sigstore.sign import SigningContext
from sigstore.verify.verifier import Verifier

Expand Down Expand Up @@ -198,7 +198,7 @@ def sign_ctx_and_ident_for_env(
token = os.getenv(f"SIGSTORE_IDENTITY_TOKEN_{env}")
if not token:
# If the variable is not defined, try getting an ambient token.
token = detect_credential(_DEFAULT_AUDIENCE)
token = detect_credential()

return ctx_cls, IdentityToken(token)

Expand All @@ -212,7 +212,7 @@ def staging() -> tuple[type[SigningContext], type[Verifier], IdentityToken]:
token = os.getenv("SIGSTORE_IDENTITY_TOKEN_staging")
if not token:
# If the variable is not defined, try getting an ambient token.
token = detect_credential(_DEFAULT_AUDIENCE)
token = detect_credential()

return signer, verifier, IdentityToken(token)

Expand Down
Loading