How is third-party authentication implemented?
OAuth2 flows, API keys, token refresh, credential storage and encryption, multi-tenant connected accounts.
Verdict
ACI has a full credential system. Each end user’s account is a LinkedAccount keyed by your own linked_account_owner_id. The secret fields (API key, access and refresh tokens, client secret) are encrypted field by field with AWS KMS envelope encryption. Platform API keys are found by an HMAC-SHA256 lookup. OAuth2 runs through Authlib with PKCE. An expired token is refreshed when a function runs, and a rotated refresh token is saved. One weak point: the PKCE verifier travels in a signed but unencrypted state JWT that has no expiry.
Klavis has no credential store in the open code. Each MCP server reads a token from the AUTH_DATA env var or from a base64 x-auth-data header. The -oauth Docker images get that token from the hosted api.klavis.ai, so they need a Klavis API key. The Strata router can do standard MCP OAuth by itself, with a localhost:3030 callback, but it keeps the tokens as plaintext JSON in .tokens/ and serves a single user.
Choose ACI if you need many end users with stored, refreshed credentials on your own infrastructure. Choose Klavis if one developer or one workload passes in tokens it already has, or if you are happy to let the Klavis cloud run OAuth.
More projects in this category are being researched.
Per-project answers
Klavis-AI/klavis
answeredThird-party auth uses two approaches. OAuth2 via Klavis cloud (_oauth_support/oauth_acquire.sh:1-93): Docker wrapper calls api.klavis.ai to create OAuth instance, shows URL, polls until authorized. Strata OAuth provider (open-strata/src/strata/mcp_proxy/auth_provider.py:160-200): OAuthClientProvider with authorization_code/refresh_token grants. LocalTokenStorage (auth_provider.py:27-54) persists tokens to .tokens/{name}/tokens.json. CallbackServer on port 3030 (auth_provider.py:110-154). HTTPTransport (transport/http.py:46-80) passes provider when auth=oauth. Multi-tenant: per-server OAuth instances. Servers like Airtable (mcp_servers/airtable/server.py:43-70) extract tokens from AUTH_DATA or x-auth-data header.
aipotheosis-labs/aci
answeredThird-party authentication uses three mechanisms. PropelAuth handles web portal auth (JWT tokens via HTTPBearer) — every user-facing route depends on auth.require_user (main.py:136, acl.py:15-19). API keys are for agent/programmatic access: validated by validate_api_key in dependencies.py (lines 48-69), which looks up the key via crud.projects.get_api_key, checks status (active/disabled/deleted), and returns a UUID key ID. API keys are stored encrypted at rest via the Key SQLAlchemy type decorator (custom_sql_types.py:29-48) which calls encryption.encrypt() using AWS KMS. A SHA-256 HMAC of the key is also stored for lookups. Linked accounts store end-user credentials per app per project (sql_models.py:398-455). The security_credentials JSONB column uses EncryptedSecurityCredentials (custom_sql_types.py:84-157) which encrypts individual fields (secret_key, access_token, refresh_token) via AWS KMS. The OAuth2Manager (oauth2_manager.py:16-162) handles the full OAuth2 code flow — create_authorization_url builds state-JWT-encoded redirect URLs, fetch_token exchanges codes with PKCE (S256), and refresh_token rotates expired tokens. Token expiry is checked in security_credentials_manager.py:213-216 and auto-refreshed at execution time (lines 98-132). App-level OAuth2 client credentials can be overridden per configuration via security_scheme_overrides (sql_models.py:351-354). The multi-tenant model links each API key → agent → project → org (sql_models.py:69-127).