feat: Read JWT from query params - #556
Merged
Merged
Conversation
…query param `Session.object_url` now accepts an optional `read_only_token_validity`. When provided, it mints an `object.read`-only JWT scoped to the session's usecase and scope, valid for that duration, base64url-encodes it, and appends it to the URL as the `os_auth` query parameter. The resulting URL is self-contained: the recipient can fetch the object without supplying an auth header. The server now reads the auth token from the base64url-encoded `os_auth` query parameter in addition to the `x-os-auth`/`Authorization` headers. The header takes precedence when both are present. Unlike a pre-signed URL, which authorizes a single request on one object, a read-only token authorizes reads on any object in the session's usecase and scope for the duration of its validity. Co-Authored-By: Claude <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #556 +/- ##
==========================================
+ Coverage 87.45% 87.51% +0.05%
==========================================
Files 93 93
Lines 14760 14784 +24
==========================================
+ Hits 12909 12938 +29
+ Misses 1851 1846 -5
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
lcian
marked this pull request as draft
July 15, 2026 12:28
jan-auer
reviewed
Jul 15, 2026
Address review feedback: - Restore test_smoke.py (smoke coverage not needed here) - Fix object_url to emit the `os_auth` query param matching the server - Trim the README Object URLs section to the essentials - Simplify query_auth.rs: build claims with serde_json instead of structs, drop the redundant garbage-base64 e2e case (covered by the token_from_query unit test) Co-Authored-By: Claude <noreply@anthropic.com>
A JWT's compact serialization is already base64url, whose alphabet is URL-safe, so the token needs no extra encoding to sit in a query string. Put the raw JWT in the `os_auth` param directly on both client and server, removing the encode/decode round-trip and the base64 dependency from the server crate. `token_from_query` is now an infallible extractor returning a borrowed `&str`. A malformed query token now surfaces as a 401 (JWT parse failure) rather than a 400, consistent with the header path. Co-Authored-By: Claude <noreply@anthropic.com>
…atch Per review: run the URL through a real parser and extract os_auth from the parsed query string, rather than a naive substring check. This adds coverage for structural breakage such as a duplicate `?` or wrong query encoding. Co-Authored-By: Claude <noreply@anthropic.com>
Per review: the manual query split did not URL-decode the value, so a proxy
that re-encodes the query string could corrupt the token. Deserialize into a
minimal `AuthParams { os_auth }` struct via axum's `Query::try_from_uri`, which
runs the proper URL-decoding path.
A missing query string (e.g. a tokenless request) deserializes gracefully to
`os_auth: None`, so this stays a no-op for unauthenticated requests.
Co-Authored-By: Claude <noreply@anthropic.com>
lcian
marked this pull request as ready for review
July 15, 2026 13:46
jan-auer
approved these changes
Jul 15, 2026
lcian
added a commit
that referenced
this pull request
Jul 16, 2026
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extends the Python client's
Session.object_urlto optionally produce a self-contained, token-carrying read URL, and teaches the server to accept the auth token from a query parameter so such URLs work.clients/python):object_url(key, read_only_token_validity=timedelta | None). Whenread_only_token_validityis provided, it mints anobject.read-only JWT scoped to the session's usecase and scope (via the existingmint_token), valid for that duration, base64url-encodes it, and appends it as theos_authquery parameter. Requires aSecretKey; raisesValueErrorotherwise. Default behavior (no arg) is unchanged.objectstore-server):from_tokennow falls back to theos_authquery parameter when nox-os-auth/Authorizationheader token is present. The header takes precedence when both are present. Presigned URLs (os_sig) still take their own path.Design notes
os_auth, consistent with the existingos_-prefixed presign params (os_sig,os_kid, …)..-separated.resclaim carries usecase+scope, not the object key), whereas a presigned URL binds the exact path+method. Documented in the docstring and README.object_url's existinghttp://host:portURL building (scheme/IPv6 handling) is intentionally left unchanged — that's a separate fix.🤖 Generated with Claude Code