Skip to content

add optional router dependencies for TransactionExtension and BulkTransactionsExtension to facilitate adding authentication to those endpoints #884

@hrodmn

Description

@hrodmn

It is currently possible to add dependencies to a StacApi with the add_route_dependencies method, as shown in this test:

def test_add_route_dependencies_after_building_api(self, collection, item):
routes = [
{"path": "/collections", "method": "POST", "payload": collection},
{
"path": "/collections/{collectionId}",
"method": "PUT",
"payload": collection,
},
{"path": "/collections/{collectionId}", "method": "DELETE", "payload": ""},
{
"path": "/collections/{collectionId}/items",
"method": "POST",
"payload": item,
},
{
"path": "/collections/{collectionId}/items/{itemId}",
"method": "PUT",
"payload": item,
},
{
"path": "/collections/{collectionId}/items/{itemId}",
"method": "DELETE",
"payload": "",
},
]
api = self._build_api()
api.add_route_dependencies(scopes=routes, dependencies=[Depends(must_be_bob)])
self._assert_dependency_applied(api, routes)

This works but it is tricky because you need to enumerate all of the route paths/methods that you want to cover. Would it make sense to add an optional route_dependencies attribute to the TransactionsExtension and BulkTransactionExtension that would be included in all of the router.add_api_route calls?

If we did this, then a user could easily define some kind of auth function and apply it as a dependency to all of the routes that are managed by the transaction extensions.

It could look something like this:

from fastapi import Depends
from fastapi.security import HTTPBasic, HTTPBasicCredentials

from stac_fastapi.api.app import StacApi
from stac_fastapi.extensions.core import TransactionExtension


def must_be_bob(
    credentials: HTTPBasicCredentials = Depends(HTTPBasic()),
):
    if credentials.username == "bob":
        return True

    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="You're not Bob",
        headers={"WWW-Authenticate": "Basic"},
    )


api = StacApi(
    ...
    extensions=[
        TransactionExtension(..., route_dependencies=[Depends(must_be_bob)])
    ],
    ...
)

On the TransactionExtension we would just add the new route_dependencies attribute and provide it in all calls to self.router.add_api_route().

cc @vincentsarago @gadomski

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions