Credential Storage
Auth providers rely on a CredentialStore to keep user tokens around between flow runs. The default InMemoryCredentialStore is great for local development, while production environments should implement the same async contract against a real database or secrets manager.
CredentialStore Protocol
from integrations.auth.storage import CredentialStore, SubjectLike, StoredData
class MyStore(CredentialStore):
async def get(self, provider: str, subject: SubjectLike) -> StoredData | None:
...
async def set(self, provider: str, subject: SubjectLike, data: StoredData) -> None:
...
async def delete(self, provider: str, subject: SubjectLike) -> None:
...
provideris the normalized auth provider name (e.g."github").subjectis either a string or JSON-serializable mapping that scopes credentials to a user, team, or service account.StoredDatais a mapping of primitive values. The manager will coerce it back into the provider’sUserCredentialsmodel before bindings run.
Implementations should be thread- and async-safe; the store may be accessed concurrently from multiple sessions.
In-Memory Reference
InMemoryCredentialStore demonstrates the expected behavior:
- Uses an
asyncio.Lockto serialize access. - Deep-copies data in and out so callers cannot mutate internal state.
- Normalizes mapping subjects via
json.dumps(..., sort_keys=True)to keep keys stable.
Swap it out by passing credential_store=MyStore() to AuthManager(...).
Persistence Tips
- Persist the provider name and subject alongside the credential payload so revocation becomes easy.
- Consider storing additional metadata (issued at, expires at) next to the raw token for auditing, but keep it outside the credential payload you return to the manager.
- Remember to call
delete_credentialswhen the user disconnects, otherwise future sessions will keep using the stale token.