Skip to content

Plugin hook to allow issuing of API tokens #2649

@simonw

Description

@simonw

Currently Datasette core can issue API tokens as signed values:

datasette/datasette/app.py

Lines 716 to 753 in 6a2c27b

def create_token(
self,
actor_id: str,
*,
expires_after: int | None = None,
restrict_all: Iterable[str] | None = None,
restrict_database: Dict[str, Iterable[str]] | None = None,
restrict_resource: Dict[str, Dict[str, Iterable[str]]] | None = None,
):
token = {"a": actor_id, "t": int(time.time())}
if expires_after:
token["d"] = expires_after
def abbreviate_action(action):
# rename to abbr if possible
action_obj = self.actions.get(action)
if not action_obj:
return action
return action_obj.abbr or action
if expires_after:
token["d"] = expires_after
if restrict_all or restrict_database or restrict_resource:
token["_r"] = {}
if restrict_all:
token["_r"]["a"] = [abbreviate_action(a) for a in restrict_all]
if restrict_database:
token["_r"]["d"] = {}
for database, actions in restrict_database.items():
token["_r"]["d"][database] = [abbreviate_action(a) for a in actions]
if restrict_resource:
token["_r"]["r"] = {}
for database, resources in restrict_resource.items():
for resource, actions in resources.items():
token["_r"]["r"].setdefault(database, {})[resource] = [
abbreviate_action(a) for a in actions
]
return "dstok_{}".format(self.sign(token, namespace="token"))

And then datasette-auth-tokens can issue API tokens that are database-backed (and can hence be audited and revoked): https://github.com/simonw/datasette-auth-tokens

Problem: I'm building a datasette-oauth plugin and it needs to be able to issue tokens. I'd like it to be able to use signed tokens by default but, if dataette-auth-tokens is configured, I'd like them to be database-backed tokens instead.

I tried figuring out how to do that with a new hook in datasette-auth-tokens itself but it felt messy, because I didn't want datasette-oauth to have to depend on that plugin.

So it needs to be a new hook in core, with the existing create_token() mechanism as a default plugin hook implementation.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions