Gated catalogs: adopt STAC Authentication incl. the tokenExchange flow (was: access: extension proposal)#551
Conversation
📝 WalkthroughWalkthroughChangesThis PR adds documentation for a new "auth:" STAC extension. It introduces spec/extensions/authentication.md describing gated catalog access using OIDC identity tokens exchanged for short-lived, prefix-scoped credentials via OAuth 2.0 Token Exchange, along with validation expectations for portolan check. An example STAC Collection JSON (authentication-collection.json) demonstrates auth:schemes and auth:refs usage on assets. spec/README.md gains a new "Extensions" navigation entry linking to the new documentation page. Sequence Diagram(s)sequenceDiagram
participant Client
participant publisher_oidc
participant credential_exchange
participant Storage
Client->>publisher_oidc: Request identity token
publisher_oidc-->>Client: OIDC identity token
Client->>credential_exchange: OAuth2 tokenExchange with identity token
credential_exchange-->>Client: Short-lived scoped credentials
Client->>Storage: Read asset with credentials
Estimated code review effort: Low Related issues: None provided. Related PRs: None provided. Suggested labels: documentation, spec Suggested reviewers: None provided. Poem: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
aad398a to
d10e9c4
Compare
portolan:access extension — authenticated access to gated data assetsaccess: extension — authenticated access to gated data assets
A small, open, vendor-neutral companion to the STAC Authentication extension. It adds the one thing that extension does not model: a credential-vending endpoint where a client exchanges a verified identity token for short-lived, scoped storage credentials to read otherwise-private data bytes directly from object storage. Identity is NOT reinvented: how to authenticate (OIDC/OAuth2) is declared with the STAC Authentication extension (auth:schemes / auth:refs). This extension adds only access:credentials (endpoint + protocol), access:tier, and access:register. Reconciled with portolan-sdi#120 (Access Control & Visibility): this is the consumer-facing wire contract for the brokered credential-vending enforcement path, complementary to the export-only IAM model portolan-sdi#120 describes. The spec stays neutral about which enforcement a publisher picks; publishers using export-only IAM simply omit this extension. Conforms to ADR-0037 (dedicated 'access:' namespace, not portolan:) and the ADR-0042 extension/schema-host precedent. - spec/extensions/access.md extension spec (builds on auth:) - spec/schema/access/v1.0.0/schema.json JSON Schema (draft 2020-12) - spec/examples/access-collection.json example: auth:schemes + access:credentials - spec/README.md index entry (Extensions) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
d10e9c4 to
c216992
Compare
access: extension — authenticated access to gated data assetsaccess: extension — credential vending for gated data assets (builds on STAC auth:)
- protocol enum gains 'presigned' (per-object presigned URLs — universal, simplest client) alongside 'portolan-broker/1.0' / 'opensharing' (short-lived scoped creds, better for Iceberg/multi-file). Reconciles with jatorre's presigned-URL 'Option B'. - Security note: the referenced auth:schemes entry SHOULD point at the CONSUMER IdP, never an operator/editor IdP (data-reader vs catalog-admin are distinct populations). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Scope the open contract to only what a client needs to READ a gated dataset:
reuse STAC auth: for identity (no new fields) + one field, access:credentials
{endpoint, protocol, scheme}, for the credential-vending step STAC lacks.
Drop access:tier, access:register, and credentials.audience from the open spec:
visibility/tiers, registration UX, and analytics are the publisher's own concern
(and portolan-sdi#120's --visibility discussion), not the read-time interop contract. Keeps
the extension laser-focused and vendor-neutral; CARTO keeps the rest closed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Do I understand correctly, that is is only meant to provide another token for object storage access? It feels like this should be solvable via the auth extension natively, but I'm also not sure whether I understand the usecase/issue correctly yet. Is this a somewhat two-step auth process? |
… to STAC once proven - Maturity path line: incubating within Portolan; once stable, propose to the STAC community with a working end-to-end implementation. - portolan-sdi#120 section: align wording with the PR description (export-only IAM is the recommendation; brokered vending is the separate managed layer — no "two enforcement paths" framing). - Open question 3 (upstream as tokenExchange scheme type): marked deferred to the upstream-proposal moment, not open now. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Yes — two steps, and the key nuance is that the second token is a different kind of credential:
The reason step 2 returns storage credentials rather than another bearer token: the readers are query engines (DuckDB, GDAL On "solvable via the auth extension natively" — we mapped our case onto the existing scheme types before adding anything:
The missing piece is the bridge: exchange a verified identity token for temporary, scoped storage credentials, with entitlement semantics (grant → creds, no grant → 403). That exchange step is the entire extension. And honestly, upstream is where we'd love this to end up — our open question 3 is exactly "contribute this as a new scheme |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@spec/extensions/access.md`:
- Around line 62-63: The wording in the access extension description uses
“datasets,” which conflicts with the STAC terminology guideline. Update the text
in the extension docs to use STAC terms consistently, especially in the sentence
about public content, and choose the appropriate STAC object term such as
Catalog or Collection instead of dataset.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4bd1011c-ef4c-4f87-82ac-b98ca5daf434
📒 Files selected for processing (4)
spec/README.mdspec/examples/access-collection.jsonspec/extensions/access.mdspec/schema/access/v1.0.0/schema.json
| - **Additive / backward-compatible.** A client that doesn't understand the | ||
| extension still reads valid STAC. Public datasets omit it. |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Use STAC terminology instead of "datasets".
✏️ Proposed fix
- extension. Public datasets omit it.
+ extension. Public Collections/Catalogs omit it.As per coding guidelines, **/*.{py,md,yaml,yml,json}: "Use STAC terminology exclusively: use 'Catalog', 'Collection', 'Item', and 'Asset' instead of 'dataset'".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - **Additive / backward-compatible.** A client that doesn't understand the | |
| extension still reads valid STAC. Public datasets omit it. | |
| - **Additive / backward-compatible.** A client that doesn't understand the | |
| extension still reads valid STAC. Public Collections/Catalogs omit it. |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@spec/extensions/access.md` around lines 62 - 63, The wording in the access
extension description uses “datasets,” which conflicts with the STAC terminology
guideline. Update the text in the extension docs to use STAC terms consistently,
especially in the sentence about public content, and choose the appropriate STAC
object term such as Catalog or Collection instead of dataset.
Source: Coding guidelines
|
Thanks, this is helpful and makes the use case clearer to me. One question to help decide the right home: how common is this exact two-step pattern across providers in practice (OIDC/OAuth login, then exchange for short-lived storage credentials), versus this being specific to a specific platform? If this is broadly common, I wonder whether the best long-term path is to standardize the pattern upstream first (for example in the OpenAPI/OAuth ecosystem, if not already covered there), and then bring it into STAC Authentication downstream. STAC Authentication is based on OpenAPI and has no two-step semantic, it's encoded implicitly in the specific authentication types such as OIDC. |
|
Broadly common — and the exchange itself is already standardized; it's the discovery that isn't:
So the plan your framing suggests: incubate here, profile the endpoint on RFC 8693 (that also answers our open question 2), and bring the proven descriptor to STAC Authentication downstream — likely as a scheme |
|
As RFC 8693 exists, it should probably be easy to propose an addition to OpenAPI and then once they have something in a draft (doesn't necessarily need to be released), we can downstream it to STAC. That would be the ideal way, indeed. Whether this needs to go through IETF or not, I'm not sure. Edit: I just found OAI/OpenAPI-Specification#4807, but it wasn't really picked up yet. I guess the most promising path would be to open a PR to https://github.com/OAI/OpenAPI-Specification with a specific proposal for discussion. PS: No offence, but I prefer to communicate with a human directly. |
|
Thanks for finding openapi's PR 4807 , I did some digging on that side:
What do you think? Some thoughts about "how common is this and why it wasn't added to open specs": I think the exchange itself is everywhere (cloud STS, Iceberg REST vended credentials, Delta Sharing, and I see it first-hand at CARTO: in custom apps we build for clients, this exact pattern PS: not offended at all, I'm using AI to explore and write faster responses, something common in this Project (but I wrote this response directly). Anyway, we'll be talking in person in 2 days :) |
|
Thanks for the additional context on industry usage. Also finding it in the OpenAPI forum and the RFC adds enough weight that it's worth implementing it. I agree with your plan. Let's create an OpenAPI PR, then a STAC Authentication extension PR that mirrors the OpenAPI PR (potentially tagging a beta release so that we have validation) and then we can implement/use it in Portolan. I think that makes the access extension obsolete, right? PS: Appreciated. |
Great, thanks for your feedback. I'll prepare the PRs. |
…catalogs Repurposes this proposal after the upstream agreement: the vending step is standardized upstream (OAI/OpenAPI-Specification#5428 mirrored by stac-extensions/authentication#44), so Portolan adopts the Authentication extension wholesale instead of owning an access: namespace. - spec/extensions/authentication.md: profile note — two-step gated read (openIdConnect identity + oauth2/tokenExchange vending), fields used, client algorithm, chaining convention (pending upstream), validation rules, security considerations. - spec/examples/authentication-collection.json: gated collection with two schemes and two gated assets (GeoParquet + Iceberg metadata) on one exchange; validates against the v1.1.0 schema. - access: extension files removed (shape preserved in history as the recorded fallback).
access: extension — credential vending for gated data assets (builds on STAC auth:)
Status (2026-07-07) — repurposed after upstream agreement
This PR began as a proposal for a Portolan-owned
access:extension (one field,access:credentials, carrying the credential-vending pointer). The discussion below with @m-mohr (STAC Authentication maintainer) resolved into a better path: standardize the missing piece upstream, then adopt the upstream extension wholesale. Both upstream PRs are open:tokenExchangeOAuth flow (RFC 8693) in the OAuth Flows ObjectWhat this PR now does
Adopts STAC Authentication (
auth:) into the Portolan profile for gated catalogs — no Portolan-owned authentication namespace:spec/extensions/authentication.md— profile note: the two-step gated read (identity viaopenIdConnect, credential vending viaoauth2/tokenExchange), fields used (all upstream), client algorithm, the chaining convention (machine-readable linkage deliberately left to the upstream discussion on feat(hooks): add auto-fetch for core dependency docs via gitingest #44), validation rules forportolan check, security considerations (consumer IdP, no secrets in metadata, least-privilege credentials).spec/examples/authentication-collection.json— a real-world-shaped example (anonymized from a running implementation): two schemes, two gated assets (GeoParquet + Apache Iceberg table metadata) sharing one exchange. Validates against the released v1.1.0 schema as-is.access:files are removed; the shape remains in this PR's history as the recorded fallback if the upstream path stalls.Export-only-IAM publishers (#120) are unaffected: they omit the exchange scheme (optionally declaring an
s3hint); presigned-URL publishers use the extension's existingsignedUrltype. Enforcement stays outside Portolan — this is discovery metadata only.Draft until
stac-extensions/authentication#44 is merged and a version is tagged (the example pins
v1.1.0for now — unknown flow keys validate as generic flow objects; stricttokenUrlenforcement arrives with the new version). Per ADR-0048, the CLI implementation (emission + the validation rules above) joins this PR before it leaves draft.Open questions from the original proposal — reconciled
auth:refsis already per-asset; nothing to add.Relates to #120 (Access Control & Visibility) and #485 (Git-Backed Catalog extension).
Summary by CodeRabbit