radiantearth / stac-browser

A full-fledged UI in Vue for browsing and searching static STAC catalogs and STAC APIs
https://radiantearth.github.io/stac-browser
ISC License
275 stars 136 forks source link

Use of OpenID Connect access token in query strings #466

Closed tschaub closed 3 days ago

tschaub commented 4 weeks ago

We have a STAC API where resource access requires an Access Token retrieved with OpenID Connect. The catalog uses the authentication extension and has an auth:schemes member that looks like this:

{
  "openId": {
    "type": "openIdConnect",
    "openIdConnectUrl": "https://example.com/.well-known/openid-configuration"
  }
}

I have configured STAC Browser with an authConfig that has type: 'openIdConnect' and an oidcConfig that includes a client_id. This works well for retrieving an Access Token for use with collection and item metadata requests. I've included auth:ref properties in the links for these resources.

For thumbnail assets and map tiles, we support including the Access Token in the query string using access_token as the name. I'm trying to understand if the authentication extension provides a way to describe this (use of an OpenID Connect Access Token in a query string) and if STAC Browser might have support for the same (using an Access Token in a query string when creating URLs for Image objects like thumbnails or map tiles).

I can envision adding an apiKey type scheme to the auth:schemes like this:

{
  "openIdQueryParam": {
    "type": "apiKey",
    "in": "query",
    "name": "access_token"
  }
}

Then I could include openIdQueryParam in the list of auth:refs for thumbnail assets and links to map tile URL templates. But I'm not sure if STAC Browser would know that this should be the Access Token retrieved via OpenID Connect (instead of an API key collected in an <input> box).

Maybe this is a question for the authentication extension, but I'm curious if there is a pattern for using an OpenID Connect Access Token in query parameters for assets and map tiles.

m-mohr commented 2 weeks ago

STAC Browser wouldn't reuse an existing token for another scheme. You could in principle define two different mechanisms via the authentication extension, but then you need to authenticate twice, of course. Maybe the authentication extension needs some kind of a scope field (asset, link, metadata, ...) and that you can provide multiple mechanisms per identity provider? Seems rather complicated though. Maybe it's easier to unify the authentication on the provider side? 😅

tschaub commented 2 weeks ago

The OpenID Connect spec only describes how clients can retrieve tokens. It doesn't specify how clients use those tokens. The OAuth 2 spec describes how clients can use access tokens to access protected resources in RFC 6750. There it describes three options: 1) in an Authorization header, 2) in a form-encoded body, and 3) in a URI query parameter.

It looks to me like STAC Browser assumes that OIDC-retrieved access tokens are used in an Authorization header. I was just curious if there might be a mechanism for hinting that a different method should be used for a specific resources.

Maybe it's easier to unify the authentication on the provider side? 😅

Not sure I get this. In our case, the resource server supports multiple ways of accessing a protected resource (as described in the spec).

I only brought this up here since it is a browser-specific client issue. It looks to me like STAC Browser will create an <img> to display a thumbnail, providing the URL as the src. In this case, it doesn't have the opportunity to set an Authorization header. I thought I might be able to suggest that STAC Browser use a query string parameter for a thumbnail asset (for example) by including something in the auth:ref.

I'll ask on the auth extension repo to see if anybody has thought about it there.

m-mohr commented 2 weeks ago

Hmm, I think I misunderstood it first, too many tasks at the same time...

I think I meant to allow it in a flexible way, but I guess I just followed the authentication extension. The authentication is based on OpenAPI and it seems OpenAPI assumes Bearer, indeed. Nevertheless, I think STAC Browser should be a little more flexible.

Could you try whether this works for you? https://github.com/radiantearth/stac-browser/pull/468

Completely untested due to 11pm, but I hope it works ;-)

Config should something along this line (add oidcConfig as needed):

{
  "type": "openIdConnect",
  "openIdConnectUrl": "https://example.com/.well-known/openid-configuration"
  "in": "query",
  "name": "access_token"
}

You might need to whitelist domains (allowedDomains), depending on your setup. It might also be that it doesn't attach to everything, but it should attach it to the STAC metadata requests and assets at least, probably not to map tiles.

tschaub commented 1 week ago

Thanks for following up on this, @m-mohr. I'm wondering if this might require a change to the auth extension. What I was hoping to achieve is to have STAC Browser use the OIDC access token in different ways depending on the resource being accessed.

For example, for collection metadata, the access token would be used in an Authorization header. And for a thumbnail or a tile, the access token would be used in an access_token query parameter. I was envisioning using different auth:refs on links and assets to control this. This would mean STAC Browser would set the header where it can (e.g. using fetch) and would set the access_token query parameter where it cannot set a header (e.g. in an image src). And I think this conforms with the suggestions in the OAuth spec (avoid using access_token unless a client cannot set headers).

I appreciate the work you've put into this already, but don't want to consume more of your time on it if others aren't running into the same (trying to use OIDC tokens with STAC Browser thumbnails and tiles). I'll likely work on an alternative solution.

m-mohr commented 1 week ago

Yeah, this would probably need more than what we have defined and implemented right now.

You can use the Auth extension to provide auth details on a per asset/link level, but then it's going to be challenging to tell STAC Browser to re-use the token in a secure manner. That needs to be somehow communicated, e.g. by specifying a "token identifier" per auth methods and if the token identifier is the same, it can be re-used?!