Skip to main content
Hookfish exposes one connection abstraction for OAuth tokens and static credentials. Trusted server code asks for access to a path. Hookfish either returns a usable secret or reports what the user must authorize.

Connection identity

A connection path ends with a trusted provider implementation:
Concrete providers can appear directly after an optional namespace, as in user/personal/github. Generic providers use an identity segment before the implementation, as in user/personal/gmail/mcp or service/prod/openai/secret. The final segment always selects trusted code. Provider IDs are slash-free, non-reserved lower-camel JavaScript identifiers such as gmail, githubEnterprise, mcp, or secret. Folder and identity names may equal provider names. Their position removes ambiguity. Hookfish stores the prefix as the namespace internally; provider metadata tells a connection UI whether part of that prefix is a required resource identity. Hookfish stores identity as (namespace, providerId) with a unique constraint. For a multi-tenant application, include the tenant in the namespace, such as organizations/acme/user/personal/github. This also lets broker resource scopes enforce tenant isolation. Hookfish does not accept caller-generated opaque IDs, slots, or provider templates in request bodies.

One access operation

For a usable connection, Hookfish returns { path, secret, scopes, expires_at, refreshed }. For an OAuth-backed connection that is not ready, @hookfish/sdk throws HookfishError with:
Each unready access creates new state, PKCE material when required, and a fresh authorization URL. It supersedes earlier pending URLs for that connection. Call connections.authorize() to start a fresh flow unconditionally, such as after an upstream MCP server rejects a credential whose stored expiration has not passed.

Lifecycle

1

Resolve the provider

Hookfish parses the final path segment and resolves only that trusted provider implementation.
2

Ensure the connection

Hookfish creates the structured connection if it does not exist. Supplying different immutable configuration later returns 409.
3

Return or acquire a secret

Secret providers read an encrypted value set with setSecret. OAuth providers refresh when possible, otherwise return authorization_required with a new URL.
4

Complete authorization

The public callback claims single-use state, exchanges the code, encrypts the returned credentials, and marks the connection ready.
5

Disconnect

Hookfish attempts upstream revocation when supported and deletes the local connection.

Connection-owned state

Each connection owns its non-secret configuration, OAuth client fallback credentials when needed, user token, refresh token, and metadata. Hookfish does not create shared runtime provider records. MCP is the resource protocol, not an authentication kind. The built-in mcp provider acquires credentials with OAuth and uses the connection’s URL to discover the protected resource and authorization server. It prefers a deployment-level Client ID Metadata Document (CIMD) when advertised and uses Dynamic Client Registration (DCR) only as a compatibility fallback. Any DCR credentials belong to that connection. The generic secret provider acquires a credential supplied by trusted code. Both provider types return the usable credential through connections.access(). A resource that does not require a credential does not need a Hookfish connection.

Security boundary

connections.access() is server-only. The authenticated application API can start authorization and accept a write-only secret, but never returns a usable credential. Its auth provider verifies the current tenant before Hookfish creates a short-lived, tenant-scoped internal capability. Continue with resource scopes or remote MCP servers.