-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: re-work API a little in preparation for release
Re-work the API from the old componentsdb interface to streamline it a bit. We lose the ability to "refresh" an issuer once created but that can be added back at a later date.
- Loading branch information
Showing
17 changed files
with
515 additions
and
352 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
title: Exceptions | ||
--- | ||
# Exceptions | ||
|
||
::: federatedidentity.exceptions |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
title: HTTP Transport | ||
--- | ||
# HTTP transport providers | ||
|
||
::: federatedidentity.transport | ||
|
||
::: federatedidentity.transport.requests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,8 @@ | ||
from .exceptions import ( | ||
FederatedIdentityError, | ||
InvalidClaimsError, | ||
InvalidIssuerError, | ||
InvalidJWKSUrlError, | ||
InvalidOIDCDiscoveryDocumentError, | ||
InvalidTokenError, | ||
TransportError, | ||
) | ||
from .oidc import AsyncOIDCTokenIssuer, OIDCTokenIssuer | ||
from ._oidc import Issuer | ||
from ._verify import ClaimVerifier, verify_id_token | ||
|
||
__all__ = [ | ||
"FederatedIdentityError", | ||
"InvalidClaimsError", | ||
"InvalidIssuerError", | ||
"InvalidJWKSUrlError", | ||
"InvalidOIDCDiscoveryDocumentError", | ||
"InvalidTokenError", | ||
"TransportError", | ||
"OIDCTokenIssuer", | ||
"AsyncOIDCTokenIssuer", | ||
"Issuer", | ||
"ClaimVerifier", | ||
"verify_id_token", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import json | ||
from collections.abc import Callable, Iterable | ||
from typing import Any, Optional, Union | ||
|
||
from . import _oidc | ||
from .exceptions import InvalidClaimsError | ||
|
||
__all__ = [ | ||
"ClaimVerifier", | ||
"verify_id_token", | ||
] | ||
|
||
|
||
ClaimVerifier = Union[dict[str, Any], Callable[[dict[str, Any]], None]] | ||
""" | ||
Type representing a claim verifier. A claim verifier may be a dictionary of acceptable claim values | ||
or a callable which takes the claims dictionary. A claims verifier callable should raise | ||
[`InvalidClaimsError`][federatedidentity.exceptions.InvalidClaimsError] if the claims do not match | ||
the expected values. | ||
""" | ||
|
||
|
||
def verify_id_token( | ||
token: Union[str, bytes], | ||
valid_issuers: Iterable[_oidc.Issuer], | ||
valid_audiences: Iterable[str], | ||
*, | ||
required_claims: Optional[Iterable[ClaimVerifier]] = None, | ||
) -> dict[str, Any]: | ||
""" | ||
Verify an OIDC identity token. | ||
Returns: | ||
the token's claims dictionary. | ||
Parameters: | ||
token: OIDC token to verify. If a [bytes][] object is passed it is decoded using the ASCII | ||
codec before verification. | ||
valid_issuers: Iterable of valid issuers. At least one Issuer must match the token issuer | ||
for verification to succeed. | ||
valid_audiences: Iterable of valid audiences. At least one audience must match the `aud` | ||
claim for verification to succeed. | ||
required_claims: Iterable of required claim verifiers. Claims are passed to verifiers after | ||
the token's signature has been verified. Claims required by OIDC are always | ||
validated. All claim verifiers must pass for verification to succeed. | ||
Raises: | ||
federatedidentity.exceptions.FederatedIdentityError: The token failed verification. | ||
UnicodeDecodeError: The token could not be decoded into an ASCII string. | ||
""" | ||
if isinstance(token, bytes): | ||
token = token.decode("ascii") | ||
|
||
unvalidated_claims = _oidc.unvalidated_claims_from_token(token) | ||
|
||
# For required claims, see: https://openid.net/specs/openid-connect-core-1_0.html#IDToken | ||
for claim in ["iss", "sub", "aud", "exp", "iat"]: | ||
if claim not in unvalidated_claims: | ||
raise InvalidClaimsError(f"'{claim}' claim not present in token") | ||
|
||
# Check that the token "aud" claim matches at least one of our expected audiences. | ||
if not any(unvalidated_claims["aud"] == audience for audience in valid_audiences): | ||
raise InvalidClaimsError( | ||
f"Token issuer '{unvalidated_claims['aud']}' did not match any valid issuer" | ||
) | ||
|
||
# Determine which issuer matches the token. | ||
for issuer in valid_issuers: | ||
if issuer.name == unvalidated_claims["iss"]: | ||
break | ||
else: | ||
# No issuer matched the token if the for loop exited without "break". | ||
raise InvalidClaimsError( | ||
f"Token issuer '{unvalidated_claims['iss']}' did not match any valid issuer" | ||
) | ||
|
||
# Note: validate_token() validates "exp", "iat" and "nbf" claims and that the "alg" header has | ||
# an appropriate value. | ||
verified_claims = json.loads(_oidc.validate_token(token, issuer.key_set).claims) | ||
|
||
required_claims = required_claims if required_claims is not None else [] | ||
for claims_verifier in required_claims: | ||
if callable(claims_verifier): | ||
claims_verifier(verified_claims) | ||
else: | ||
for claim, value in claims_verifier.items(): | ||
if claim not in verified_claims: | ||
raise InvalidClaimsError(f"Required claim '{claim}' not present in token") | ||
if verified_claims[claim] != value: | ||
raise InvalidClaimsError( | ||
f"Required claim '{claim}' has invalid value {value!r}" | ||
) | ||
|
||
return verified_claims |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.