Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add flag to skip JWT validation #28

Merged
merged 1 commit into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions project/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class MinioBucketConfig(MinioConnection):
class OIDCConfig(BaseModel):
certs_url: HttpUrl
client_id_claim_name: str = "client_id"
skip_jwt_validation: bool = False

model_config = ConfigDict(frozen=True)

Expand Down
26 changes: 26 additions & 0 deletions project/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ def get_settings():


def get_auth_jwks(settings: Annotated[Settings, Depends(get_settings)]):
if settings.oidc.skip_jwt_validation:
logger.warning("Since JWT validation is skipped, an empty JWKS is returned")
return jwk.JWKSet()

jwks_url = str(settings.oidc.certs_url)

try:
r = httpx.get(jwks_url)
r.raise_for_status()
except HTTPError:
logger.exception("Failed to read OIDC config")

raise HTTPException(
status_code=status.HTTP_502_BAD_GATEWAY,
detail="Auth provider is unavailable",
Expand Down Expand Up @@ -67,6 +72,27 @@ def get_client_id(
jwks: Annotated[jwk.JWKSet, Depends(get_auth_jwks)],
credentials: Annotated[HTTPAuthorizationCredentials, Depends(security)],
):
# TODO here be dragons!
if settings.oidc.skip_jwt_validation:
logger.warning(
"JWT validation is skipped, so JWT could be signed by an untrusted party "
"or be expired"
)

token = jwt.JWT(
jwt=credentials.credentials,
check_claims={
settings.oidc.client_id_claim_name: None,
},
)

# this hurts to write but there's no other way. token.token is an instance of JWS, and accessing
# the payload property expects that it is validated. but it isn't since we're skipping validation.
# so we have to access the undocumented property objects and read the payload from there.
return json.loads(token.token.objects["payload"])[
settings.oidc.client_id_claim_name
]

try:
token = jwt.JWT(
jwt=credentials.credentials,
Expand Down