Documentation
¶
Index ¶
- func GeneratePKCEChallenge() (verifier, challenge string, err error)
- func SetLogger(l schemas.Logger)
- func ValidatePKCEChallenge(verifier, challenge string) bool
- type DynamicClientRegistrationRequest
- type DynamicClientRegistrationResponse
- type OAuth2Provider
- func (p *OAuth2Provider) BuildAdminUpstreamAuthorizeURL(ctx context.Context, flowID string) (string, error)
- func (p *OAuth2Provider) BuildUpstreamAuthorizeURL(ctx context.Context, flowID string) (string, error)
- func (p *OAuth2Provider) CompleteOAuthFlow(ctx context.Context, state, code string) error
- func (p *OAuth2Provider) CompleteUserOAuthFlow(ctx context.Context, state string, code string) (string, error)
- func (p *OAuth2Provider) EvictExchangedToken(mode schemas.MCPAuthMode, identity, mcpClientID string)
- func (p *OAuth2Provider) EvictUserToken(mode schemas.MCPAuthMode, identity, mcpClientID string)
- func (p *OAuth2Provider) EvictUserTokenByID(tokenID string)
- func (p *OAuth2Provider) EvictUserTokensByMCPClient(mcpClientID string)
- func (p *OAuth2Provider) EvictUserTokensByUser(userID string)
- func (p *OAuth2Provider) EvictUserTokensByVirtualKey(virtualKeyID string)
- func (p *OAuth2Provider) ExchangeAdminCredential(ctx context.Context, config *schemas.MCPClientConfig, subjectToken string) (*schemas.OAuth2TokenExchangeResponse, error)
- func (p *OAuth2Provider) FlushUserTokenCache()
- func (p *OAuth2Provider) ForceRefreshAccessToken(ctx *schemas.BifrostContext, config *schemas.MCPClientConfig) error
- func (p *OAuth2Provider) GetAccessToken(ctx context.Context, oauthConfigID string) (string, error)
- func (p *OAuth2Provider) GetAdminAccessToken(ctx context.Context, mcpClientID string) (string, error)
- func (p *OAuth2Provider) GetExchangedAccessToken(ctx *schemas.BifrostContext, config *schemas.MCPClientConfig) (string, error)
- func (p *OAuth2Provider) GetPendingMCPClient(oauthConfigID string) (*schemas.MCPClientConfig, error)
- func (p *OAuth2Provider) GetUserAccessTokenByMode(ctx context.Context, mode schemas.MCPAuthMode, identity, mcpClientID string) (string, error)
- func (p *OAuth2Provider) InitiateOAuthFlow(ctx context.Context, config *schemas.OAuth2Config) (*schemas.OAuth2FlowInitiation, error)
- func (p *OAuth2Provider) InitiateUserOAuthFlow(ctx context.Context, oauthConfigID string, mcpClientID string, ...) (*schemas.OAuth2FlowInitiation, string, error)
- func (p *OAuth2Provider) RefreshAccessToken(ctx context.Context, tokenID string) error
- func (p *OAuth2Provider) RemovePendingMCPClient(oauthConfigID string) error
- func (p *OAuth2Provider) RetainExchangeAdminCredential(ctx context.Context, config *schemas.MCPClientConfig, ...) error
- func (p *OAuth2Provider) RevokeToken(ctx context.Context, oauthConfigID string) error
- func (p *OAuth2Provider) SetTempTokenService(svc *temptoken.Service)
- func (p *OAuth2Provider) SetTokenExchangeIdPResolver(r schemas.TokenExchangeIdPResolver)
- func (p *OAuth2Provider) StorePendingMCPClient(oauthConfigID string, mcpClientConfig schemas.MCPClientConfig) error
- func (p *OAuth2Provider) TokenExchangeAvailable() bool
- func (p *OAuth2Provider) ValidateToken(ctx context.Context, oauthConfigID string) (bool, error)
- type OAuthMetadata
- type OAuthTokenRefreshWorker
- func (w *OAuthTokenRefreshWorker) SetLookAheadWindow(window time.Duration)
- func (w *OAuthTokenRefreshWorker) SetOnTokenRefreshed(cb func(mcpClientID, authMode string))
- func (w *OAuthTokenRefreshWorker) SetRefreshInterval(interval time.Duration)
- func (w *OAuthTokenRefreshWorker) SetShouldRefreshGate(gate func(ctx context.Context) bool)
- func (w *OAuthTokenRefreshWorker) Start(ctx context.Context)
- func (w *OAuthTokenRefreshWorker) Stop()
- type PerUserOAuthSweepWorker
- type PermanentOAuthError
- type ResourceMetadata
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func GeneratePKCEChallenge ¶
GeneratePKCEChallenge generates code_verifier and code_challenge for PKCE (RFC 7636) Returns:
- verifier: Random 128-character string (stored securely, never sent to server)
- challenge: SHA256 hash of verifier, base64url encoded (sent in authorization request)
func ValidatePKCEChallenge ¶
ValidatePKCEChallenge validates that a code_verifier matches the expected code_challenge Used during testing or debugging
Types ¶
type DynamicClientRegistrationRequest ¶
type DynamicClientRegistrationRequest struct {
ClientName string `json:"client_name"`
RedirectURIs []string `json:"redirect_uris"`
GrantTypes []string `json:"grant_types"`
ResponseTypes []string `json:"response_types"`
TokenEndpointAuthMethod string `json:"token_endpoint_auth_method"`
Scope string `json:"scope,omitempty"`
LogoURI string `json:"logo_uri,omitempty"`
ClientURI string `json:"client_uri,omitempty"`
Contacts []string `json:"contacts,omitempty"`
}
DynamicClientRegistrationRequest represents the client registration request (RFC 7591)
type DynamicClientRegistrationResponse ¶
type DynamicClientRegistrationResponse struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"`
ClientIDIssuedAt int64 `json:"client_id_issued_at,omitempty"`
ClientSecretExpiresAt int64 `json:"client_secret_expires_at,omitempty"`
RegistrationAccessToken string `json:"registration_access_token,omitempty"`
RegistrationClientURI string `json:"registration_client_uri,omitempty"`
}
DynamicClientRegistrationResponse represents the server's response (RFC 7591)
func RegisterDynamicClient ¶
func RegisterDynamicClient(ctx context.Context, registrationURL string, req *DynamicClientRegistrationRequest) (*DynamicClientRegistrationResponse, error)
RegisterDynamicClient performs dynamic client registration with the OAuth provider (RFC 7591) This allows Bifrost to automatically register as an OAuth client without manual setup.
Parameters:
- ctx: Context for the registration request
- registrationURL: The registration endpoint (discovered or user-provided)
- req: Client registration details
Returns client_id and optional client_secret that can be used for OAuth flows.
type OAuth2Provider ¶
type OAuth2Provider struct {
// contains filtered or unexported fields
}
OAuth2Provider implements the schemas.OAuth2Provider interface It provides OAuth 2.0 authentication functionality with database persistence
func NewOAuth2Provider ¶
func NewOAuth2Provider(configStore configstore.ConfigStore, logger schemas.Logger) *OAuth2Provider
NewOAuth2Provider creates a new OAuth provider instance
func (*OAuth2Provider) BuildAdminUpstreamAuthorizeURL ¶ added in v1.5.9
func (p *OAuth2Provider) BuildAdminUpstreamAuthorizeURL(ctx context.Context, flowID string) (string, error)
BuildAdminUpstreamAuthorizeURL is BuildUpstreamAuthorizeURL's admin-mode counterpart: reconstructs the upstream provider authorization URL for a pending flow_mode='admin' row, used by the MCP client reauthorize endpoint to hand OAuth2Authorizer's popup a real provider URL to open directly (unlike the per-user page-based flow, which navigates to a Bifrost page that itself resolves the upstream URL later). Reads through GetOauthFlowByID rather than widening BuildUpstreamAuthorizeURL's own GetOauthUserSessionByID call: that lookup is deliberately scoped away from admin-mode rows (see its doc comment) so a caller-supplied flow ID from a per-user-facing endpoint can never reach an admin flow's PKCE state.
func (*OAuth2Provider) BuildUpstreamAuthorizeURL ¶ added in v1.3.11
func (p *OAuth2Provider) BuildUpstreamAuthorizeURL(ctx context.Context, flowID string) (string, error)
BuildUpstreamAuthorizeURL reconstructs the upstream provider authorization URL for a pending per-user OAuth flow. Called by the frontend sessions tab when the user clicks "Authenticate" — at which point the flow row already exists (from a prior InitiateUserOAuthFlow), the CSRF state + PKCE verifier are stored on it, and we just need to hand the user the upstream redirect.
The code_challenge is recomputed deterministically from the stored verifier so we don't have to persist it separately.
func (*OAuth2Provider) CompleteOAuthFlow ¶
func (p *OAuth2Provider) CompleteOAuthFlow(ctx context.Context, state, code string) error
CompleteOAuthFlow handles the OAuth callback and exchanges code for tokens Supports PKCE verification. Handles the admin-mode flow — the shared client's production authorize and a per-user client's bootstrap-test authorize alike (see the FlowMode field comment on TableMCPOauthFlow).
func (*OAuth2Provider) CompleteUserOAuthFlow ¶ added in v1.3.1
func (p *OAuth2Provider) CompleteUserOAuthFlow(ctx context.Context, state string, code string) (string, error)
CompleteUserOAuthFlow handles the OAuth callback for a per-user flow. It looks up the session by state, exchanges code for tokens, and returns a session token.
func (*OAuth2Provider) EvictExchangedToken ¶ added in v1.5.9
func (p *OAuth2Provider) EvictExchangedToken(mode schemas.MCPAuthMode, identity, mcpClientID string)
EvictExchangedToken removes every cached exchanged token for one binding, regardless of which subject bearer token each entry was cached under (see userTokenCacheKey's doc comment on subjectDiscriminator) — the caller here (ForceRefreshAccessToken) knows the binding but not a specific token's fingerprint.
func (*OAuth2Provider) EvictUserToken ¶ added in v1.5.9
func (p *OAuth2Provider) EvictUserToken(mode schemas.MCPAuthMode, identity, mcpClientID string)
EvictUserToken drops the cached access token for one (mode, identity, mcp client) binding. Side-effect only and safe to call when the cache is absent; the next lookup for the binding reads the database.
func (*OAuth2Provider) EvictUserTokenByID ¶ added in v1.5.9
func (p *OAuth2Provider) EvictUserTokenByID(tokenID string)
EvictUserTokenByID drops the cached access token backed by the given token row ID, if any binding currently holds it. Side-effect only and safe to call when the cache is absent or the ID is not cached.
func (*OAuth2Provider) EvictUserTokensByMCPClient ¶ added in v1.5.9
func (p *OAuth2Provider) EvictUserTokensByMCPClient(mcpClientID string)
EvictUserTokensByMCPClient drops every cached access token bound to the given MCP client, across all auth modes and identities. Used after client-level mutations that invalidate its token rows as a set, such as credential rotation, access reconciliation, or client deletion. Side-effect only and safe to call when the cache is absent.
func (*OAuth2Provider) EvictUserTokensByUser ¶ added in v1.5.9
func (p *OAuth2Provider) EvictUserTokensByUser(userID string)
EvictUserTokensByUser drops every cached user-mode access token bound to the given user, across all MCP clients. Used after user-level mutations that orphan or delete the user's token rows as a set. Side-effect only and safe to call when the cache is absent.
func (*OAuth2Provider) EvictUserTokensByVirtualKey ¶ added in v1.5.9
func (p *OAuth2Provider) EvictUserTokensByVirtualKey(virtualKeyID string)
EvictUserTokensByVirtualKey drops every cached vk-mode access token bound to the given virtual key, across all MCP clients. Used after virtual key mutations that orphan or delete its token rows as a set. Side-effect only and safe to call when the cache is absent.
func (*OAuth2Provider) ExchangeAdminCredential ¶ added in v1.5.9
func (p *OAuth2Provider) ExchangeAdminCredential(ctx context.Context, config *schemas.MCPClientConfig, subjectToken string) (*schemas.OAuth2TokenExchangeResponse, error)
ExchangeAdminCredential performs a single uncached exchange of the admin's own token (a sample caller token, never associated with any identity binding), producing the admin bootstrap credential used for verification + tool discovery. The full token response is returned so the caller can retain it via RetainExchangeAdminCredential once verification succeeds.
func (*OAuth2Provider) FlushUserTokenCache ¶ added in v1.5.9
func (p *OAuth2Provider) FlushUserTokenCache()
FlushUserTokenCache drops every cached per-user access token. The coarse fallback for mutations whose blast radius cannot be scoped to one client or virtual key. Side-effect only.
func (*OAuth2Provider) ForceRefreshAccessToken ¶ added in v1.5.9
func (p *OAuth2Provider) ForceRefreshAccessToken(ctx *schemas.BifrostContext, config *schemas.MCPClientConfig) error
ForceRefreshAccessToken resolves the MCP OAuth token row backing config — the shared token linked to config.OauthConfigID for MCPAuthTypeOauth (same lookup GetAccessToken performs), or the caller's per-identity token for MCPAuthTypePerUserOauth (same lookup GetUserAccessTokenByMode performs, with (mode, identity) derived from ctx) — and refreshes it unconditionally via RefreshAccessToken, regardless of whether the token's own ExpiresAt says it's still good. RefreshAccessToken itself never consults ExpiresAt — only its callers (GetAccessToken, GetUserAccessTokenByMode) gate on it before deciding to call it — so resolving the right token row and going straight to RefreshAccessToken is the entire "force" behavior.
func (*OAuth2Provider) GetAccessToken ¶
GetAccessToken retrieves the access token for a given oauth_config_id
func (*OAuth2Provider) GetAdminAccessToken ¶ added in v1.5.9
func (p *OAuth2Provider) GetAdminAccessToken(ctx context.Context, mcpClientID string) (string, error)
GetAdminAccessToken is GetAccessToken's admin-mode counterpart: resolves the retained bootstrap-verification credential for a per-user client's periodic tool-discovery refresh (ClientToolSyncer.performSync), rather than the shared-mode production credential. Keyed by the MCP client ID, which every admin row carries regardless of whether an oauth_configs template sits behind the credential.
func (*OAuth2Provider) GetExchangedAccessToken ¶ added in v1.5.9
func (p *OAuth2Provider) GetExchangedAccessToken(ctx *schemas.BifrostContext, config *schemas.MCPClientConfig) (string, error)
GetExchangedAccessToken returns an upstream access token for a token_exchange client, exchanging the caller's identity-provider token for one scoped to the client's audience. Cached per (auth mode, identity, mcp client) binding in the same in-memory cache as per-user OAuth lookups — exchanged tokens have no database row, so the cached entry (with the expiry-as-miss validator) is the only local state, and a miss simply performs a fresh exchange.
func (*OAuth2Provider) GetPendingMCPClient ¶
func (p *OAuth2Provider) GetPendingMCPClient(oauthConfigID string) (*schemas.MCPClientConfig, error)
GetPendingMCPClient retrieves an MCP client config by oauth_config_id. Returns nil if no pending config is found. Unlike before PKCE/expiry fields moved off TableOauthConfig, this no longer applies its own expiry gate: the only caller (completeMCPClientOAuth) already requires oauthConfig.Status=="authorized" before reaching this call, which is a stronger, more truthful signal than a raw timestamp comparison — a config row that reached "authorized" represents a real completed OAuth exchange regardless of how much wall-clock time has passed since the bootstrap stash was written.
func (*OAuth2Provider) GetUserAccessTokenByMode ¶ added in v1.3.11
func (p *OAuth2Provider) GetUserAccessTokenByMode(ctx context.Context, mode schemas.MCPAuthMode, identity, mcpClientID string) (string, error)
GetUserAccessTokenByMode retrieves the upstream access token using exactly one identity column determined by mode. No fallback chain. Filters status='active' so orphaned rows never satisfy a lookup.
Reads are served from an in-memory cache when possible: a cached entry whose expiry has passed is dropped and the lookup falls through to the database path, which owns every expiry and refresh decision. Failed lookups are never cached, so a caller completing OAuth (or a token being reactivated) becomes visible on the very next call.
func (*OAuth2Provider) InitiateOAuthFlow ¶
func (p *OAuth2Provider) InitiateOAuthFlow(ctx context.Context, config *schemas.OAuth2Config) (*schemas.OAuth2FlowInitiation, error)
InitiateOAuthFlow creates an OAuth config and returns the authorization URL Supports OAuth discovery and PKCE
func (*OAuth2Provider) InitiateUserOAuthFlow ¶ added in v1.3.1
func (p *OAuth2Provider) InitiateUserOAuthFlow(ctx context.Context, oauthConfigID string, mcpClientID string, redirectURI string, flowMode schemas.MCPAuthMode) (*schemas.OAuth2FlowInitiation, string, error)
InitiateUserOAuthFlow creates or refreshes the per-user OAuth flow row for a given (mode, identity, mcp_client) binding and returns the auth landing URL.
Determinism: there is exactly one flow row per binding. If one already exists (from a prior auth attempt), it's updated in place — fresh CSRF state, fresh PKCE verifier, status reset to 'pending'. Otherwise a new row is inserted. Reauth never duplicates rows; revoke deletes them.
The function errors out cleanly on any misconfig (missing identity, unknown mode, missing template config) — no fallbacks, no generated identities.
func (*OAuth2Provider) RefreshAccessToken ¶
func (p *OAuth2Provider) RefreshAccessToken(ctx context.Context, tokenID string) error
RefreshAccessToken refreshes any MCP OAuth token row — the single shared client credential (AuthMode="shared") or a per-identity credential (AuthMode "user"/"vk"/"session") alike — looked up by the token row's own primary-key ID. This is the one refresh path for every kind of MCP OAuth credential: GetAccessToken and GetUserAccessTokenByMode both funnel their lazy pre-flight refresh through here, unifying what used to be two separate functions (one keyed by oauth_config_id and reachable only via TableOauthConfig.TokenID, one keyed by token ID directly).
Never writes to TableOauthConfig: the template config row (client_id, token_url, etc.) is read-only input to the token exchange here. Credential health lives entirely on the token row's own Status field.
The actual refresh runs on a context detached from any single caller — via DoChan rather than Do — because it is shared work: with Do, the first caller's ctx backs the whole call, so that caller disconnecting (client abort, gateway timeout) would cancel the in-flight upstream request and deliver that same cancellation error to every other concurrent caller waiting on the same token, even though their own requests are still live. Each caller here instead only ever stops waiting on its own ctx; the shared refresh keeps running to completion (bounded by refreshAccessTokenTimeout) for whoever else still needs its result.
func (*OAuth2Provider) RemovePendingMCPClient ¶
func (p *OAuth2Provider) RemovePendingMCPClient(oauthConfigID string) error
RemovePendingMCPClient clears the pending MCP client config from the oauth config This is called after OAuth completion to clean up
func (*OAuth2Provider) RetainExchangeAdminCredential ¶ added in v1.5.9
func (p *OAuth2Provider) RetainExchangeAdminCredential(ctx context.Context, config *schemas.MCPClientConfig, response *schemas.OAuth2TokenExchangeResponse) error
RetainExchangeAdminCredential persists the outcome of a successful admin verification as the retained auth_mode='admin' token row for config — the discovery credential the tool syncer and OAuthTokenRefreshWorker keep alive, mirroring what PromoteSharedOauthTokenToAdmin does for per-user OAuth bootstrap. Upserts: a repair replaces the existing row's credential.
func (*OAuth2Provider) RevokeToken ¶
func (p *OAuth2Provider) RevokeToken(ctx context.Context, oauthConfigID string) error
RevokeToken revokes the OAuth token
func (*OAuth2Provider) SetTempTokenService ¶ added in v1.3.11
func (p *OAuth2Provider) SetTempTokenService(svc *temptoken.Service)
SetTempTokenService installs the temp-token service used by InitiateUserOAuthFlow to mint the mcp_auth token embedded in the auth-page URL fragment. Called by server startup once both services have been constructed (the provider is built first by lib/config.go, the service later by the HTTP transport).
func (*OAuth2Provider) SetTokenExchangeIdPResolver ¶ added in v1.5.9
func (p *OAuth2Provider) SetTokenExchangeIdPResolver(r schemas.TokenExchangeIdPResolver)
SetTokenExchangeIdPResolver installs the identity-provider resolver that backs delegated token exchange. Called once at server startup after the identity integration is constructed; nil (never installed) leaves the token_exchange auth type unavailable.
func (*OAuth2Provider) StorePendingMCPClient ¶
func (p *OAuth2Provider) StorePendingMCPClient(oauthConfigID string, mcpClientConfig schemas.MCPClientConfig) error
StorePendingMCPClient stores an MCP client config that's waiting for OAuth completion The config is persisted in the database (oauth_configs.mcp_client_config_json) to support multi-instance deployments where OAuth callback may hit a different server instance.
func (*OAuth2Provider) TokenExchangeAvailable ¶ added in v1.5.9
func (p *OAuth2Provider) TokenExchangeAvailable() bool
TokenExchangeAvailable reports whether delegated token exchange can run.
func (*OAuth2Provider) ValidateToken ¶
ValidateToken checks if the token is still valid
type OAuthMetadata ¶
type OAuthMetadata struct {
AuthorizationURL string `json:"authorization_endpoint"`
TokenURL string `json:"token_endpoint"`
RegistrationURL *string `json:"registration_endpoint,omitempty"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
Resource string `json:"resource,omitempty"`
Issuer string `json:"issuer,omitempty"`
ResponseTypes []string `json:"response_types_supported,omitempty"`
GrantTypes []string `json:"grant_types_supported,omitempty"`
TokenAuthMethods []string `json:"token_endpoint_auth_methods_supported,omitempty"`
PKCEMethods []string `json:"code_challenge_methods_supported,omitempty"`
}
OAuthMetadata contains discovered OAuth configuration from authorization server
func DiscoverOAuthMetadata ¶
func DiscoverOAuthMetadata(ctx context.Context, serverURL string) (*OAuthMetadata, error)
DiscoverOAuthMetadata performs OAuth 2.0 discovery for the given MCP server URL Following RFC 8414 (Authorization Server Discovery) and RFC 9728 (Protected Resource Metadata)
Parameters:
- ctx: Context for the discovery requests
- serverURL: The MCP server URL to discover OAuth configuration from
- logger: Logger for discovery progress (can be nil for silent operation)
The discovery process: 1. Attempt to connect to MCP server, expect 401 with WWW-Authenticate header 2. Parse WWW-Authenticate header for resource_metadata URL and scopes 3. Fetch resource metadata to get authorization server URLs 4. Try .well-known discovery if resource metadata is not available 5. Fetch authorization server metadata from discovered URLs 6. Return complete OAuth configuration
type OAuthTokenRefreshWorker ¶ added in v1.5.9
type OAuthTokenRefreshWorker struct {
// AuthModes restricts proactive refresh to tokens whose AuthMode is in
// this set. Defaults to {"shared", "admin"} — shared-client tokens and
// retained per_user_oauth bootstrap credentials (auth_mode='admin') are
// the only ones with no live caller to trigger a lazy/inline refresh:
// admin-mode tokens back only the periodic tool-discovery syncer, never
// real end-user traffic, so nothing else would ever refresh them.
// Widening this further (e.g. to include "user"/"vk"/"session") opts
// specific per-identity auth modes into the same proactive sweep.
//
// Set this before calling Start, not after: the background goroutine
// reads this field directly on every sweep with no synchronization, so a
// mutation concurrent with a running sweep is a data race. Every current
// caller already treats this as write-once-before-Start; there is no
// supported way to change an already-started worker's scope short of
// Stop and constructing a new worker.
AuthModes []string
// contains filtered or unexported fields
}
OAuthTokenRefreshWorker manages automatic token refresh for expiring OAuth tokens
func NewOAuthTokenRefreshWorker ¶ added in v1.5.9
func NewOAuthTokenRefreshWorker(provider *OAuth2Provider, logger schemas.Logger) *OAuthTokenRefreshWorker
NewOAuthTokenRefreshWorker creates a new token refresh worker
func (*OAuthTokenRefreshWorker) SetLookAheadWindow ¶ added in v1.5.9
func (w *OAuthTokenRefreshWorker) SetLookAheadWindow(window time.Duration)
SetLookAheadWindow updates the look-ahead window for token expiry (for testing)
func (*OAuthTokenRefreshWorker) SetOnTokenRefreshed ¶ added in v1.5.9
func (w *OAuthTokenRefreshWorker) SetOnTokenRefreshed(cb func(mcpClientID, authMode string))
SetOnTokenRefreshed registers a callback invoked after each successful proactive token refresh, with the owning MCP client ID and the token's auth mode. It lets the serving layer react to a freshened credential, for example by recycling a connection that captured the old one. Tokens with no MCP client ID (legacy rows) never fire the callback. Safe to call at any time, including while the worker is running; passing nil clears the callback.
func (*OAuthTokenRefreshWorker) SetRefreshInterval ¶ added in v1.5.9
func (w *OAuthTokenRefreshWorker) SetRefreshInterval(interval time.Duration)
SetRefreshInterval updates the refresh check interval (for testing)
func (*OAuthTokenRefreshWorker) SetShouldRefreshGate ¶ added in v1.5.9
func (w *OAuthTokenRefreshWorker) SetShouldRefreshGate(gate func(ctx context.Context) bool)
SetShouldRefreshGate installs a predicate consulted at the start of every sweep tick; a tick proceeds only when the gate is unset or returns true. Lets a deployment with multiple workers sharing the same token store restrict sweeps to one at a time, avoiding concurrent refreshes of the same token. Safe to call at any time, including while the worker is running; passing nil restores the default (always run).
func (*OAuthTokenRefreshWorker) Start ¶ added in v1.5.9
func (w *OAuthTokenRefreshWorker) Start(ctx context.Context)
Start begins the token refresh worker in a background goroutine
func (*OAuthTokenRefreshWorker) Stop ¶ added in v1.5.9
func (w *OAuthTokenRefreshWorker) Stop()
Stop gracefully stops the token refresh worker. Safe to call multiple times — guarded by sync.Once so a redundant call from a secondary shutdown path can't panic by re-closing the channel.
type PerUserOAuthSweepWorker ¶ added in v1.3.11
type PerUserOAuthSweepWorker struct {
// contains filtered or unexported fields
}
PerUserOAuthSweepWorker periodically purges stale per-user OAuth state:
- expired pending flow rows (oauth_user_sessions where ExpiresAt < now and status='pending')
- orphaned token rows older than OrphanRetention (oauth_user_tokens where status='orphaned')
Pending-flow expiry is short (driven by the row's own ExpiresAt, default 15min) so the flow tick is fast. Orphan retention is operator-tunable (default 30 days) and the orphan tick is slow.
func NewPerUserOAuthSweepWorker ¶ added in v1.3.11
func NewPerUserOAuthSweepWorker(provider *OAuth2Provider, orphanRetention time.Duration, logger schemas.Logger) *PerUserOAuthSweepWorker
NewPerUserOAuthSweepWorker creates a sweep worker with sensible defaults. orphanRetention <= 0 disables the orphan-token sweep.
func (*PerUserOAuthSweepWorker) SetFlowSweepInterval ¶ added in v1.3.11
func (w *PerUserOAuthSweepWorker) SetFlowSweepInterval(d time.Duration)
SetFlowSweepInterval updates the pending-flow sweep cadence (for testing). Non-positive durations are ignored — run() feeds the field straight into time.NewTicker, which panics on d <= 0.
func (*PerUserOAuthSweepWorker) SetOrphanSweepInterval ¶ added in v1.3.11
func (w *PerUserOAuthSweepWorker) SetOrphanSweepInterval(d time.Duration)
SetOrphanSweepInterval updates the orphan-token sweep cadence (for testing). Same non-positive guard as SetFlowSweepInterval.
func (*PerUserOAuthSweepWorker) Start ¶ added in v1.3.11
func (w *PerUserOAuthSweepWorker) Start(ctx context.Context)
Start begins the sweep worker in a background goroutine.
func (*PerUserOAuthSweepWorker) Stop ¶ added in v1.3.11
func (w *PerUserOAuthSweepWorker) Stop()
Stop gracefully stops the sweep worker. sync.Once guards against double-close panics when called from multiple shutdown paths.
type PermanentOAuthError ¶ added in v1.2.37
PermanentOAuthError indicates the OAuth provider rejected the request in a way that requires user re-authorization (e.g. revoked refresh token, invalid_grant). Distinct from transient network failures which should be retried.
func (*PermanentOAuthError) Error ¶ added in v1.2.37
func (e *PermanentOAuthError) Error() string
type ResourceMetadata ¶
type ResourceMetadata struct {
Resource string `json:"resource,omitempty"`
AuthorizationServers []string `json:"authorization_servers"`
ScopesSupported []string `json:"scopes_supported,omitempty"`
Scopes []string `json:"scopes,omitempty"` // Alternative field name
}
ResourceMetadata contains metadata from protected resource