Documentation
¶
Index ¶
- Constants
- Variables
- func CanonicalWorkspaceProvider(cfg *Config, provider string) string
- func DefineOAuthLinkStateComponents(ctx context.Context, dao *datly.Service) error
- func DelegatedProviderStorageKey(workspaceNamespace, providerRef string) string
- func EffectiveUserID(ctx context.Context) string
- func InjectTokens(ctx context.Context, tokens *scyauth.Token) context.Context
- func InjectUser(ctx context.Context, subject string) context.Context
- func IsDelegatedProviderKey(provider string) bool
- func IsWorkspaceProviderAlias(cfg *Config, provider string) bool
- func MCPAuthToken(ctx context.Context, useIDToken bool) string
- func NewCreatedByUserTokenProvider(cfg *Config, dao *datly.Service) token.Provider
- func NewTokenStoreAdapter(store TokenStore, users UserService) token.TokenStore
- func NotifyMCPAuthChange(event MCPAuthChangeEvent)
- func OAuthScopesForHeadless(client *OAuthClient) []string
- func Protect(cfg *Config, sessions *Manager, opts ...ProtectOption) func(http.Handler) http.Handler
- func ProtectWithTokenProvider(cfg *Config, sessions *Manager, tp token.Provider, opts ...ProtectOption) func(http.Handler) http.Handler
- func RegisterMCPAuthChangeListener(listener func(MCPAuthChangeEvent))
- func ValidateOAuthTokenScopes(expected []string, token *scyauth.Token) error
- func WithAuthExtensions(base http.Handler, runtime *Runtime) http.Handler
- func WithAuthProtection(base http.Handler, runtime *Runtime) http.Handler
- type CanonicalUserResolver
- type Config
- type DatlyUserService
- func (s *DatlyUserService) GetByID(ctx context.Context, id string) (*User, error)
- func (s *DatlyUserService) GetBySubjectAndProvider(ctx context.Context, subject, provider string) (*User, error)
- func (s *DatlyUserService) GetByUsername(ctx context.Context, username string) (*User, error)
- func (s *DatlyUserService) UpdateHashIPByID(ctx context.Context, id, hash string) error
- func (s *DatlyUserService) UpdatePreferences(ctx context.Context, username string, patch *PreferencesPatch) error
- func (s *DatlyUserService) Upsert(ctx context.Context, user *User) error
- func (s *DatlyUserService) UpsertWithProvider(ctx context.Context, username, displayName, email, provider, subject string) (string, error)
- type DelegatedCredentialResolver
- func (r *DelegatedCredentialResolver) Invalidate(ctx context.Context, requirement authcfg.Requirement) error
- func (r *DelegatedCredentialResolver) MaxRefreshLead(ctx context.Context) time.Duration
- func (r *DelegatedCredentialResolver) Refresh(ctx context.Context, requirement authcfg.Requirement) (*authcfg.Credential, error)
- func (r *DelegatedCredentialResolver) RefreshStoredDelegatedToken(ctx context.Context, stored *OAuthToken) error
- func (r *DelegatedCredentialResolver) Resolve(ctx context.Context, requirement authcfg.Requirement) (*authcfg.Credential, error)
- type DelegatedMCPAuth
- func (d *DelegatedMCPAuth) CleanupDelegatedCredentials(ctx context.Context, canonicalUserID string) error
- func (d *DelegatedMCPAuth) ClearResolverCooldown(canonicalUserID, storageKey string)
- func (d *DelegatedMCPAuth) ProviderRegistry() *providerregistry.Registry
- func (d *DelegatedMCPAuth) Registry() authcfg.ProviderRegistry
- func (d *DelegatedMCPAuth) Resolver() authcfg.CredentialResolver
- func (d *DelegatedMCPAuth) SetUserLookup(users interface{})
- func (d *DelegatedMCPAuth) TokenRefresher() DelegatedTokenRefresher
- type DelegatedTokenLister
- type DelegatedTokenRefresher
- type DelegatedTokenStore
- type ExpiringTokenScanner
- type Handler
- type HandlerOption
- type JWT
- type JWTService
- type Local
- type MCPAuthChangeEvent
- type MCPAuthConfigProvider
- type MCPAuthState
- type Manager
- type OAuth
- type OAuthClient
- type OAuthStateRecord
- type OAuthStateStore
- type OAuthStateStoreDatly
- func (s *OAuthStateStoreDatly) Consume(ctx context.Context, stateHash, canonicalUserID, sessionHash string) error
- func (s *OAuthStateStoreDatly) CreateOrGetPending(ctx context.Context, record *OAuthStateRecord) (*OAuthStateRecord, bool, error)
- func (s *OAuthStateStoreDatly) DeleteExpired(ctx context.Context, before time.Time) (int64, time.Time, error)
- func (s *OAuthStateStoreDatly) GetPending(ctx context.Context, flowHash string) (*OAuthStateRecord, error)
- type OAuthToken
- type PreferencesPatch
- type ProtectOption
- type Runtime
- type Session
- type SessionRecord
- type SessionStore
- type SessionStoreDAO
- type TokenStore
- type TokenStoreDAO
- func (s *TokenStoreDAO) CASPut(ctx context.Context, token *OAuthToken, expectedVersion int64, owner string) (bool, error)
- func (s *TokenStoreDAO) Delete(ctx context.Context, username, provider string) error
- func (s *TokenStoreDAO) Get(ctx context.Context, username, provider string) (*OAuthToken, error)
- func (s *TokenStoreDAO) GetExact(ctx context.Context, username, provider string) (*OAuthToken, error)
- func (s *TokenStoreDAO) ListDelegated(ctx context.Context, userID string) ([]*OAuthToken, error)
- func (s *TokenStoreDAO) Put(ctx context.Context, token *OAuthToken) error
- func (s *TokenStoreDAO) ReleaseRefreshLease(ctx context.Context, username, provider, owner string) error
- func (s *TokenStoreDAO) ScanExpiring(ctx context.Context, horizon time.Time) ([]*OAuthToken, error)
- func (s *TokenStoreDAO) TryAcquireRefreshLease(ctx context.Context, username, provider, owner string, ttl time.Duration) (int64, bool, error)
- func (s *TokenStoreDAO) ValidateProviderColumnWidth(ctx context.Context, width int) error
- type TokenStoreOption
- type User
- type UserByIDLookup
- type UserInfo
- type UserService
- type VerifiedWorkspaceIdentity
Constants ¶
const DelegatedProviderKeyLength = len(DelegatedProviderKeyPrefix) + sha256.Size*2
DelegatedProviderKeyLength is the fixed length of a delegated storage key: len("mcp:v1:") + 64 hex characters of an untruncated SHA-256 digest.
const DelegatedProviderKeyPrefix = "mcp:v1:"
DelegatedProviderKeyPrefix marks provider column values holding delegated (per-MCP-provider) tokens rather than workspace provider names.
const MCPLinkCSRFHeader = "X-Agently-Csrf"
MCPLinkCSRFHeader carries the per-session CSRF token required on the cookie-authenticated POST initiate and DELETE disconnect endpoints. Clients obtain the token from the status response.
Variables ¶
var ErrOAuthStateInvalid = errors.New("oauth link state is invalid")
ErrOAuthStateInvalid is the single non-enumerable failure returned for every rejected state consume: absent, expired, replayed, cross-user and cross-session states are indistinguishable to callers. The classification is recorded in audit logs only.
Functions ¶
func CanonicalWorkspaceProvider ¶ added in v0.1.29
CanonicalWorkspaceProvider normalizes trusted workspace provider aliases ("", "jwt", "oauth", "default") to the configured workspace provider name. Delegated storage keys and unknown provider names pass through unchanged.
func DefineOAuthLinkStateComponents ¶ added in v0.1.29
DefineOAuthLinkStateComponents registers the read, create-or-get-pending, atomic consume and delete-expired linkstate components with datly.Service. Called during auth runtime initialization.
func DelegatedProviderStorageKey ¶ added in v0.1.29
DelegatedProviderStorageKey derives the fixed-length, globally unambiguous user_oauth_token.provider value for a delegated provider reference:
mcp:v1:<hex sha256(workspaceNamespace + NUL + providerRef)>
The digest is never truncated. workspaceNamespace is an immutable configured identifier; changing it requires an explicit token-key migration.
func EffectiveUserID ¶
EffectiveUserID returns a stable user identifier from context. Delegates to the internal auth package.
func InjectTokens ¶
InjectTokens stores OAuth tokens in context so that MCPAuthToken and downstream MCP clients can forward the logged-in user's token. External auth middleware (outside this module) should call this after authenticating the user from a session or JWT.
func InjectUser ¶
InjectUser stores user identity in context using the agently-core auth key. External middleware (outside this module) can call this to bridge their own auth context into the context key that EffectiveUserID reads.
func IsDelegatedProviderKey ¶ added in v0.1.29
IsDelegatedProviderKey reports whether a provider column value is a delegated storage key. Delegated rows require exact lookup and per-provider broker routing; they must never be served by workspace fallback or sent to the workspace refresh broker.
func IsWorkspaceProviderAlias ¶ added in v0.1.29
IsWorkspaceProviderAlias reports whether provider names the workspace identity provider (directly or through a trusted legacy alias).
func MCPAuthToken ¶
MCPAuthToken selects a single token string suitable for outbound MCP calls. Delegates to the internal auth package.
func NewCreatedByUserTokenProvider ¶ added in v0.1.7
NewCreatedByUserTokenProvider returns a store-backed token provider suitable for scheduler created_by_user_id auth restoration. It only restores tokens already persisted in user_oauth_token; it does not enable any broader auth flow.
func NewTokenStoreAdapter ¶
func NewTokenStoreAdapter(store TokenStore, users UserService) token.TokenStore
NewTokenStoreAdapter wraps a service/auth.TokenStore to satisfy token.TokenStore.
func NotifyMCPAuthChange ¶ added in v0.1.29
func NotifyMCPAuthChange(event MCPAuthChangeEvent)
NotifyMCPAuthChange publishes a credential change to every listener.
func OAuthScopesForHeadless ¶ added in v0.1.20
func OAuthScopesForHeadless(client *OAuthClient) []string
OAuthScopesForHeadless returns the grant a non-interactive user-owned runtime should request. A dedicated CLI scope wins; otherwise legacy browser-created schedules inherit the web scope, with mobile as the final compatibility fallback.
func ProtectWithTokenProvider ¶
func ProtectWithTokenProvider(cfg *Config, sessions *Manager, tp token.Provider, opts ...ProtectOption) func(http.Handler) http.Handler
Protect returns middleware that extracts auth credentials from the request (Bearer token or session cookie) and populates the request context with authenticated user identity and tokens.
Requests to /v1/api/auth/* and OPTIONS are passed through without auth. When JWT auth is configured, Bearer tokens are cryptographically verified.
ProtectWithTokenProvider is like Protect but also stores session tokens in the given token.Provider so they are available for subsequent requests from that user.
func RegisterMCPAuthChangeListener ¶ added in v0.1.29
func RegisterMCPAuthChangeListener(listener func(MCPAuthChangeEvent))
RegisterMCPAuthChangeListener subscribes to delegated MCP credential changes. Wiring code (e.g. the executor builder) registers MCP manager pool eviction here.
func ValidateOAuthTokenScopes ¶ added in v0.1.22
ValidateOAuthTokenScopes validates a newly obtained OAuth token against the exact scopes requested for that authorization flow.
func WithAuthExtensions ¶ added in v0.1.3
Types ¶
type CanonicalUserResolver ¶ added in v0.1.29
type CanonicalUserResolver struct {
// contains filtered or unexported fields
}
CanonicalUserResolver maps verified workspace identities to the canonical Agently users.id. It is shared by the session and bearer entry paths so both apply identical provider/subject checks; the bearer path must not implement a second, weaker subject-to-user mapping.
func NewCanonicalUserResolver ¶ added in v0.1.29
func NewCanonicalUserResolver(users UserService) *CanonicalUserResolver
NewCanonicalUserResolver creates a resolver over the given user service.
func (*CanonicalUserResolver) Invalidate ¶ added in v0.1.29
func (r *CanonicalUserResolver) Invalidate()
Invalidate drops all cached subject mappings. Call on provider reload and on local user-status changes (disable/delete).
func (*CanonicalUserResolver) ResolveCanonicalWorkspaceUser ¶ added in v0.1.29
func (r *CanonicalUserResolver) ResolveCanonicalWorkspaceUser(ctx context.Context, identity VerifiedWorkspaceIdentity) (string, error)
ResolveCanonicalWorkspaceUser returns the canonical users.id for a verified workspace identity. It accepts only already-verified identities, never creates or upserts a user, and fails closed (returns an error) when the canonical owner cannot be determined reliably.
type Config ¶ added in v0.1.3
type Config struct {
Enabled bool `yaml:"enabled" json:"enabled"`
CookieName string `yaml:"cookieName" json:"cookieName"`
SessionTTLHours int `yaml:"sessionTTLHours,omitempty" json:"sessionTTLHours,omitempty"`
TokenRefreshLeadMinutes int `yaml:"tokenRefreshLeadMinutes,omitempty" json:"tokenRefreshLeadMinutes,omitempty"`
DefaultUsername string `yaml:"defaultUsername" json:"defaultUsername"`
IpHashKey string `yaml:"ipHashKey" json:"ipHashKey"`
TrustedProxies []string `yaml:"trustedProxies" json:"trustedProxies"`
RedirectPath string `yaml:"redirectPath" json:"redirectPath"`
// WorkspaceNamespace is the immutable identifier mixed into delegated MCP
// token storage keys. It is not a filesystem path or display name;
// changing it requires an explicit token-key migration. Empty selects
// "default".
WorkspaceNamespace string `yaml:"workspaceNamespace,omitempty" json:"workspaceNamespace,omitempty"`
// TokenEncryptionKey is the explicit (env-expandable) encryption key for
// delegated MCP token storage. When empty, delegated storage falls back to
// the legacy workspace OAuth client configURL-derived salt. It lets
// JWT/local-auth workspaces (no OAuth client) use delegated MCP OAuth.
TokenEncryptionKey string `yaml:"tokenEncryptionKey,omitempty" json:"tokenEncryptionKey,omitempty"`
// StateEncryptionKey is the active AEAD key material for delegated MCP
// OAuth callback state (env-expandable). When empty, the delegated token
// encryption salt is used. StateEncryptionKeyPrevious keeps the retired
// key decryptable for at least the state TTL plus clock skew after a
// rotation; new state always seals with the active key.
StateEncryptionKey string `yaml:"stateEncryptionKey,omitempty" json:"stateEncryptionKey,omitempty"`
StateEncryptionKeyPrevious string `yaml:"stateEncryptionKeyPrevious,omitempty" json:"stateEncryptionKeyPrevious,omitempty"`
// MCPLinkStateTTLMinutes bounds the delegated MCP OAuth state lifetime;
// values are clamped to the mandated 5–10 minute window (default 7).
MCPLinkStateTTLMinutes int `yaml:"mcpLinkStateTTLMinutes,omitempty" json:"mcpLinkStateTTLMinutes,omitempty"`
OAuth *OAuth `yaml:"oauth" json:"oauth"`
Local *Local `yaml:"local" json:"local"`
JWT *JWT `yaml:"jwt,omitempty" json:"jwt,omitempty"`
}
Config defines global authentication settings for public embedders.
func DecodeConfigFromRoot ¶ added in v0.1.8
DecodeConfigFromRoot decodes the `auth:` section from an already- loaded workspace Root. Returns (nil, nil) when the root is nil or the auth section is empty — callers treat that as "auth disabled". Env-template expansion and the "effectively empty" check live here so the two entry points (LoadConfig / DecodeConfigFromRoot) behave identically.
func LoadConfig ¶ added in v0.1.8
LoadConfig reads `<workspaceRoot>/config.yaml` and decodes the `auth:` section into a *Config. Returns (nil, nil) when no auth section is present or all fields are zero.
Callers that have already loaded the workspace `Root` (e.g. the executor bootstrap that also reads `default:` / `mcpServer`) should prefer DecodeConfigFromRoot to avoid re-reading and re-parsing config.yaml.
func LoadWorkspaceConfig
deprecated
added in
v0.1.3
LoadWorkspaceConfig is a thin compatibility shim over LoadConfig.
Deprecated: use LoadConfig for new code, or DecodeConfigFromRoot when the workspace Root is already in hand. Kept so external callers that still reference the old name keep compiling; will be removed once the tree is fully migrated.
func (*Config) DelegatedTokenEncryptionSalt ¶ added in v0.1.29
DelegatedTokenEncryptionSalt returns the salt encrypting delegated MCP token rows: the explicit auth.tokenEncryptionKey when configured, otherwise the legacy workspace OAuth client configURL. Empty means delegated storage has no usable key; delegated configuration must then fail loudly rather than silently disable.
func (*Config) IsBearerAccepted ¶ added in v0.1.3
func (*Config) IsCookieAccepted ¶ added in v0.1.3
func (*Config) IsLocalAuth ¶ added in v0.1.3
type DatlyUserService ¶ added in v0.1.5
type DatlyUserService struct {
// contains filtered or unexported fields
}
func NewDatlyUserService ¶ added in v0.1.5
func NewDatlyUserService(dao *datly.Service) *DatlyUserService
func (*DatlyUserService) GetByID ¶ added in v0.1.29
GetByID resolves a canonical user by users.id, including its active status. It implements UserByIDLookup for delegated-credential active checks.
func (*DatlyUserService) GetBySubjectAndProvider ¶ added in v0.1.5
func (*DatlyUserService) GetByUsername ¶ added in v0.1.5
func (*DatlyUserService) UpdateHashIPByID ¶ added in v0.1.5
func (s *DatlyUserService) UpdateHashIPByID(ctx context.Context, id, hash string) error
func (*DatlyUserService) UpdatePreferences ¶ added in v0.1.5
func (s *DatlyUserService) UpdatePreferences(ctx context.Context, username string, patch *PreferencesPatch) error
func (*DatlyUserService) Upsert ¶ added in v0.1.5
func (s *DatlyUserService) Upsert(ctx context.Context, user *User) error
func (*DatlyUserService) UpsertWithProvider ¶ added in v0.1.5
type DelegatedCredentialResolver ¶ added in v0.1.29
type DelegatedCredentialResolver struct {
// contains filtered or unexported fields
}
DelegatedCredentialResolver implements the viant/mcp CredentialResolver for Agently: canonical-user-keyed encrypted storage, validated workspace-token reuse, provider-exact refresh with distributed leases and CAS, and safe invalidation. Resolution returns outbound credentials only — it never installs values into the Agently authentication context.
func NewDelegatedCredentialResolver ¶ added in v0.1.29
func NewDelegatedCredentialResolver(cfg *Config, store DelegatedTokenStore, registry *providerregistry.Registry, namespace string) *DelegatedCredentialResolver
NewDelegatedCredentialResolver builds the resolver. namespace is the immutable workspace namespace used in storage-key derivation.
func (*DelegatedCredentialResolver) Invalidate ¶ added in v0.1.29
func (r *DelegatedCredentialResolver) Invalidate(ctx context.Context, requirement authcfg.Requirement) error
Invalidate implements config.CredentialResolver. It deletes only the exact canonical-user/provider row. Unknown providers or a missing canonical owner must never delete credentials.
func (*DelegatedCredentialResolver) MaxRefreshLead ¶ added in v0.1.29
func (r *DelegatedCredentialResolver) MaxRefreshLead(ctx context.Context) time.Duration
MaxRefreshLead implements DelegatedTokenRefresher.
func (*DelegatedCredentialResolver) Refresh ¶ added in v0.1.29
func (r *DelegatedCredentialResolver) Refresh(ctx context.Context, requirement authcfg.Requirement) (*authcfg.Credential, error)
Refresh implements config.CredentialResolver. Per contract it bypasses any cached access token and mints a fresh credential while retaining the stored refresh credential.
func (*DelegatedCredentialResolver) RefreshStoredDelegatedToken ¶ added in v0.1.29
func (r *DelegatedCredentialResolver) RefreshStoredDelegatedToken(ctx context.Context, stored *OAuthToken) error
RefreshStoredDelegatedToken implements DelegatedTokenRefresher for the background watcher. Unknown providers, malformed metadata and disabled providers are skipped without modifying stored credentials; provider failures are isolated to the row.
func (*DelegatedCredentialResolver) Resolve ¶ added in v0.1.29
func (r *DelegatedCredentialResolver) Resolve(ctx context.Context, requirement authcfg.Requirement) (*authcfg.Credential, error)
Resolve implements config.CredentialResolver.
type DelegatedMCPAuth ¶ added in v0.1.29
type DelegatedMCPAuth struct {
// contains filtered or unexported fields
}
DelegatedMCPAuth bundles the workspace OAuth provider registry and the Agently credential resolver installed into viant/mcp for MCP definitions with auth.mode=oauth. Legacy MCP auth configurations are unaffected: the manager installs these only for delegated configs.
func NewDelegatedMCPAuth ¶ added in v0.1.29
func NewDelegatedMCPAuth(cfg *Config, dao *datly.Service) *DelegatedMCPAuth
NewDelegatedMCPAuth builds the delegated MCP auth stack over the encrypted user_oauth_token store. It returns nil only when the required persistence layer (datly DAO) is unavailable — delegated configs then fail loudly at client creation because no credential resolver is installed. When storage exists but no encryption key can be derived (neither auth.tokenEncryptionKey nor a workspace OAuth client configURL), the resolver is installed in a fail-loud state: every delegated resolution returns an actionable configuration error instead of silently disabling delegated auth.
func (*DelegatedMCPAuth) CleanupDelegatedCredentials ¶ added in v0.1.29
func (d *DelegatedMCPAuth) CleanupDelegatedCredentials(ctx context.Context, canonicalUserID string) error
CleanupDelegatedCredentials is the user-lifecycle hook for deactivation and deletion: it deletes every delegated (mcp:v1) token row belonging to the canonical user after attempting best-effort provider-side revocation. Providers without revocation support are audited and cleaned locally.
func (*DelegatedMCPAuth) ClearResolverCooldown ¶ added in v0.1.29
func (d *DelegatedMCPAuth) ClearResolverCooldown(canonicalUserID, storageKey string)
ClearResolverCooldown drops the refresh retry cooldown for one canonical user and delegated storage key on this instance. Used by cache-invalidation wiring so a re-link on another resolver instance takes effect immediately.
func (*DelegatedMCPAuth) ProviderRegistry ¶ added in v0.1.29
func (d *DelegatedMCPAuth) ProviderRegistry() *providerregistry.Registry
ProviderRegistry exposes the Agently registry surface (kill switches, fingerprint, refresh leads).
func (*DelegatedMCPAuth) Registry ¶ added in v0.1.29
func (d *DelegatedMCPAuth) Registry() authcfg.ProviderRegistry
Registry exposes the generic viant/mcp provider registry.
func (*DelegatedMCPAuth) Resolver ¶ added in v0.1.29
func (d *DelegatedMCPAuth) Resolver() authcfg.CredentialResolver
Resolver exposes the generic viant/mcp credential resolver.
func (*DelegatedMCPAuth) SetUserLookup ¶ added in v0.1.29
func (d *DelegatedMCPAuth) SetUserLookup(users interface{})
SetUserLookup installs the canonical by-ID active-status lookup: with it in place, disabled or deleted canonical users cannot resolve or refresh delegated credentials. Any UserService implementing UserByIDLookup applies.
func (*DelegatedMCPAuth) TokenRefresher ¶ added in v0.1.29
func (d *DelegatedMCPAuth) TokenRefresher() DelegatedTokenRefresher
TokenRefresher exposes the watcher-facing delegated refresh surface.
type DelegatedTokenLister ¶ added in v0.1.29
type DelegatedTokenLister interface {
ListDelegated(ctx context.Context, userID string) ([]*OAuthToken, error)
}
DelegatedTokenLister is the optional listing surface used by the user-lifecycle cleanup hook to enumerate a canonical user's delegated rows.
type DelegatedTokenRefresher ¶ added in v0.1.29
type DelegatedTokenRefresher interface {
// RefreshStoredDelegatedToken applies the row's provider-specific refresh
// policy and, when due, refreshes through that provider's exact
// client/token endpoint using the distributed lease and CAS write.
RefreshStoredDelegatedToken(ctx context.Context, stored *OAuthToken) error
// MaxRefreshLead returns the largest configured provider refresh lead used
// as the watcher's broad scan horizon.
MaxRefreshLead(ctx context.Context) time.Duration
}
DelegatedTokenRefresher lets the background watcher refresh delegated rows through their exact provider broker. Until installed, delegated rows are skipped without mutation.
type DelegatedTokenStore ¶ added in v0.1.29
type DelegatedTokenStore interface {
GetExact(ctx context.Context, userID, provider string) (*OAuthToken, error)
Put(ctx context.Context, token *OAuthToken) error
Delete(ctx context.Context, userID, provider string) error
TryAcquireRefreshLease(ctx context.Context, userID, provider, owner string, ttl time.Duration) (version int64, acquired bool, err error)
ReleaseRefreshLease(ctx context.Context, userID, provider, owner string) error
CASPut(ctx context.Context, token *OAuthToken, expectedVersion int64, owner string) (swapped bool, err error)
}
DelegatedTokenStore is the exact, canonical-user-keyed persistence surface used for delegated MCP credentials. It deliberately excludes the legacy fallback Get: delegated storage keys require exact matches and delegated owner resolution uses CanonicalUserID directly, never resolveOAuthTokenOwnerID.
type ExpiringTokenScanner ¶ added in v0.1.7
type ExpiringTokenScanner interface {
// ScanExpiring returns all stored tokens whose expiry is before horizon
// and that carry a refresh token. Only tokens that can actually be
// refreshed need to be returned.
ScanExpiring(ctx context.Context, horizon time.Time) ([]*OAuthToken, error)
}
ExpiringTokenScanner is an optional extension of TokenStore for implementations that can efficiently query the store for tokens expiring before a given horizon. It is used by the background refresh watcher to proactively refresh tokens for users who are idle (no active in-memory session) before they expire. TokenStore implementations that do not embed a queryable DB may omit this.
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler serves auth-related HTTP endpoints. It is designed to be mounted under /v1/api/auth/* on the application router.
func NewHandler ¶
func NewHandler(cfg *Config, sessions *Manager, opts ...HandlerOption) *Handler
NewHandler creates an auth HTTP handler.
func (*Handler) RegisterPreferences ¶
RegisterPreferences mounts preference endpoints on the given mux. These endpoints require the auth middleware to populate user context.
type HandlerOption ¶
type HandlerOption func(*Handler)
HandlerOption customises the auth Handler.
func WithTokenProvider ¶
func WithTokenProvider(tp token.Provider) HandlerOption
WithTokenProvider injects a shared token lifecycle manager.
func WithTokenStore ¶
func WithTokenStore(ts TokenStore) HandlerOption
WithTokenStore injects an OAuth token store.
func WithUserService ¶
func WithUserService(us UserService) HandlerOption
WithUserService injects a user service.
type JWT ¶ added in v0.1.3
type JWT struct {
Enabled bool `yaml:"enabled" json:"enabled"`
RSA []string `yaml:"rsa,omitempty" json:"rsa,omitempty"`
HMAC string `yaml:"hmac,omitempty" json:"hmac,omitempty"`
CertURL string `yaml:"certURL,omitempty" json:"certURL,omitempty"`
RSAPrivateKey string `yaml:"rsaPrivateKey,omitempty" json:"rsaPrivateKey,omitempty"`
}
type JWTService ¶
type JWTService struct {
// contains filtered or unexported fields
}
JWTService wraps scy's JWT signer and verifier for the agently-core auth layer.
func NewJWTService ¶
func NewJWTService(cfg *JWT) *JWTService
NewJWTService creates a JWT service from the given config. Call Init() before use to load keys.
func NewJWTServiceFromConfigValues ¶ added in v0.1.1
func NewJWTServiceFromConfigValues(enabled bool, rsa []string, hmac, certURL, rsaPrivateKey string) *JWTService
NewJWTServiceFromConfigValues creates a JWT service from raw config values for callers outside agently-core that cannot import the internal auth package.
func (*JWTService) Init ¶
func (j *JWTService) Init(ctx context.Context) error
Init loads keys from scy resources. Safe to call multiple times.
func (*JWTService) PublicKeys ¶
func (j *JWTService) PublicKeys() (map[string]*rsa.PublicKey, error)
PublicKeys returns the loaded RSA public keys (for diagnostics/testing).
type MCPAuthChangeEvent ¶ added in v0.1.29
type MCPAuthChangeEvent struct {
// Kind is one of "linked", "disconnected".
Kind string
// CanonicalUserID keys credential storage and resolver cooldowns.
CanonicalUserID string
// EffectiveUserID keys the MCP manager client pool.
EffectiveUserID string
ServerName string
ProviderRef string
StorageKey string
}
MCPAuthChangeEvent describes a delegated MCP credential change (link, disconnect, invalid_grant). Subscribers evict caches only — the event never changes EffectiveUserID, sessions or the workspace provider.
type MCPAuthConfigProvider ¶ added in v0.1.29
type MCPAuthConfigProvider interface {
Options(ctx context.Context, serverName string) (*mcpcfg.MCPClient, error)
}
MCPAuthConfigProvider yields MCP client configurations for the hosted link endpoints. The MCP manager's repository provider satisfies it; the runtime falls back to a workspace repository loader when none is installed.
type MCPAuthState ¶ added in v0.1.29
type MCPAuthState struct {
CanonicalUserID string `json:"canonicalUserId"`
SessionIDHash string `json:"sessionIdHash"`
ServerName string `json:"serverName"`
ProviderRef string `json:"providerRef"`
ClientRef string `json:"clientRef,omitempty"`
Resource string `json:"resource,omitempty"`
Scopes []string `json:"scopes,omitempty"`
CodeVerifier string `json:"codeVerifier"`
ReturnURL string `json:"returnURL,omitempty"`
Nonce string `json:"nonce"`
ExpiresAt time.Time `json:"expiresAt"`
// ConfigFingerprint records the non-secret provider-registry fingerprint
// at initiation; the callback verifies the configuration has not changed
// underneath the flow.
ConfigFingerprint string `json:"configFingerprint,omitempty"`
// RedirectURI pins the exact redirect used on the authorization request so
// the token exchange sends the identical value.
RedirectURI string `json:"redirectURI,omitempty"`
}
MCPAuthState is the encrypted callback state payload for delegated MCP OAuth. It round-trips through the browser only as AEAD ciphertext; the database stores only its hash. The PKCE verifier lives exclusively here.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages user sessions with an in-memory cache and optional persistent store.
func NewManager ¶
func NewManager(ttl time.Duration, store SessionStore) *Manager
NewManager creates a session manager with the given TTL. If store is nil, sessions are stored only in memory.
func (*Manager) ActiveSessions ¶
ActiveSessions returns a snapshot of all non-expired sessions in memory.
type OAuth ¶ added in v0.1.3
type OAuth struct {
Mode string `yaml:"mode" json:"mode"`
Name string `yaml:"name" json:"name"`
Label string `yaml:"label" json:"label"`
UsePopupLogin bool `yaml:"usePopupLogin,omitempty" json:"usePopupLogin,omitempty"`
Client *OAuthClient `yaml:"client" json:"client"`
}
type OAuthClient ¶ added in v0.1.3
type OAuthClient struct {
ConfigURL string `yaml:"configURL" json:"configURL"`
DiscoveryURL string `yaml:"discoveryURL" json:"discoveryURL"`
JWKSURL string `yaml:"jwksURL" json:"jwksURL"`
RedirectURI string `yaml:"redirectURI" json:"redirectURI"`
RedirectURIs []string `yaml:"redirectURIs" json:"redirectURIs"`
ClientID string `yaml:"clientID" json:"clientID"`
Scopes []string `yaml:"scopes" json:"scopes"`
WebUIScopes []string `yaml:"webUIScopes,omitempty" json:"webUIScopes,omitempty"`
MobileUIScopes []string `yaml:"mobileUIScopes,omitempty" json:"mobileUIScopes,omitempty"`
CLIScopes []string `yaml:"cliScopes,omitempty" json:"cliScopes,omitempty"`
Issuer string `yaml:"issuer" json:"issuer"`
Audiences []string `yaml:"audiences" json:"audiences"`
}
type OAuthStateRecord ¶ added in v0.1.29
type OAuthStateRecord struct {
StateHash string
FlowHash string
CanonicalUserID string
SessionHash string
Provider string
ExpiresAt time.Time
ConsumedAt *time.Time
CreatedAt time.Time
}
OAuthStateRecord is the non-secret oauth_link_state row. It never carries authorization codes, PKCE verifiers, client secrets or tokens; the encrypted state blob itself stays with the flow owner (browser round-trip) only.
type OAuthStateStore ¶ added in v0.1.29
type OAuthStateStore interface {
// CreateOrGetPending returns the stored flow row and whether this call
// created (or replaced a consumed/expired) row. The creator owns the flow
// and receives the authorization URL; concurrent callers must poll.
CreateOrGetPending(ctx context.Context, record *OAuthStateRecord) (stored *OAuthStateRecord, created bool, err error)
// Consume atomically transitions the state to consumed. It fails with
// ErrOAuthStateInvalid when the record is absent, expired, already
// consumed, owned by another canonical user or bound to another session.
Consume(ctx context.Context, stateHash, canonicalUserID, sessionHash string) error
// DeleteExpired removes rows expired at or before the horizon and reports
// the deleted count plus the oldest removed expiry for metrics.
DeleteExpired(ctx context.Context, before time.Time) (deleted int64, oldestExpiresAt time.Time, err error)
}
OAuthStateStore is the distributed single-use OAuth state surface used by the MCP link endpoints. Implementations must provide cross-pod CreateOrGetPending deduplication and an atomic pending-to-consumed transition; encryption alone does not make state single-use.
type OAuthStateStoreDatly ¶ added in v0.1.29
type OAuthStateStoreDatly struct {
// contains filtered or unexported fields
}
OAuthStateStoreDatly implements OAuthStateStore exclusively through the registered Datly linkstate components: no raw database/sql access happens here or in any HTTP handler above it.
func NewOAuthStateStoreDatly ¶ added in v0.1.29
func NewOAuthStateStoreDatly(dao *datly.Service) *OAuthStateStoreDatly
NewOAuthStateStoreDatly creates the Datly-backed state store adapter.
func (*OAuthStateStoreDatly) Consume ¶ added in v0.1.29
func (s *OAuthStateStoreDatly) Consume(ctx context.Context, stateHash, canonicalUserID, sessionHash string) error
func (*OAuthStateStoreDatly) CreateOrGetPending ¶ added in v0.1.29
func (s *OAuthStateStoreDatly) CreateOrGetPending(ctx context.Context, record *OAuthStateRecord) (*OAuthStateRecord, bool, error)
func (*OAuthStateStoreDatly) DeleteExpired ¶ added in v0.1.29
func (*OAuthStateStoreDatly) GetPending ¶ added in v0.1.29
func (s *OAuthStateStoreDatly) GetPending(ctx context.Context, flowHash string) (*OAuthStateRecord, error)
GetPending returns the unexpired pending record for a flow hash (status polling); nil when none exists.
type OAuthToken ¶
type OAuthToken struct {
Username string `json:"username"`
Provider string `json:"provider"`
AccessToken string `json:"accessToken"`
IDToken string `json:"idToken,omitempty"`
RefreshToken string `json:"refreshToken,omitempty"`
ExpiresAt time.Time `json:"expiresAt,omitempty"`
// Issuer is the normalized OAuth issuer the token was granted by.
Issuer string `json:"issuer,omitempty"`
// Resource is the protected resource (audience) the token targets.
Resource string `json:"resource,omitempty"`
// Scopes are the granted scopes (authoritative after refresh).
Scopes []string `json:"scopes,omitempty"`
// TokenType records accessToken versus idToken usage intent.
TokenType string `json:"tokenType,omitempty"`
// Subject is the provider subject extracted from the verified token; it is
// credential metadata only and never becomes the effective user.
Subject string `json:"subject,omitempty"`
// ProviderRef/ClientRef record the workspace provider registry references
// for delegated tokens (the row provider column stores a fixed-length
// hashed storage key).
ProviderRef string `json:"providerRef,omitempty"`
ClientRef string `json:"clientRef,omitempty"`
// IDTokenExpiresAt is the verified ID-token exp. ExpiresAt remains the
// access-token expiry for compatibility; tokenType=idToken consumers must
// derive validity and refresh thresholds from this field instead.
IDTokenExpiresAt time.Time `json:"idTokenExpiresAt,omitempty"`
// IssuedAt records when the token set was obtained (login, exchange or
// refresh); the refresh policy uses it to derive the original selected
// token lifetime for the 20% clamp.
IssuedAt time.Time `json:"issuedAt,omitempty"`
}
OAuthToken represents a stored OAuth token set for a user/provider pair. The metadata fields (Issuer, Resource, Scopes, TokenType, Subject, ProviderRef, ClientRef) are optional for backward compatibility with legacy workspace rows; delegated (per-provider MCP) tokens always populate them and every conversion/refresh path must preserve them.
func (*OAuthToken) HasDelegatedMetadata ¶ added in v0.1.29
func (t *OAuthToken) HasDelegatedMetadata() bool
HasDelegatedMetadata reports whether the token carries the delegated credential metadata that refresh/CAS paths must not drop.
func (*OAuthToken) MergeMetadataFrom ¶ added in v0.1.29
func (t *OAuthToken) MergeMetadataFrom(prior *OAuthToken)
MergeMetadataFrom copies missing metadata fields from prior. Populated fields on the receiver win (e.g. an authoritative refreshed scope set).
type PreferencesPatch ¶
type PreferencesPatch struct {
DisplayName *string `json:"displayName,omitempty"`
Timezone *string `json:"timezone,omitempty"`
DefaultAgentRef *string `json:"defaultAgentRef,omitempty"`
DefaultModelRef *string `json:"defaultModelRef,omitempty"`
DefaultEmbedderRef *string `json:"defaultEmbedderRef,omitempty"`
AgentPrefs map[string]map[string]interface{} `json:"agentPrefs,omitempty"`
}
PreferencesPatch describes a partial update to user preferences.
type ProtectOption ¶
type ProtectOption func(*protectConfig)
ProtectOption customises the Protect middleware.
func WithJWTService ¶
func WithJWTService(j *JWTService) ProtectOption
WithJWTService injects a pre-initialised JWTService for Bearer token verification.
type Runtime ¶ added in v0.1.3
type Runtime struct {
// contains filtered or unexported fields
}
func NewRuntime ¶ added in v0.1.3
func (*Runtime) JWTService ¶ added in v0.1.3
func (r *Runtime) JWTService() *JWTService
func (*Runtime) SetDelegatedTokenRefresher ¶ added in v0.1.29
func (r *Runtime) SetDelegatedTokenRefresher(refresher DelegatedTokenRefresher)
SetDelegatedTokenRefresher installs the delegated (per-provider) refresher used by the background watcher for rows stored under delegated provider keys. Until it is installed, delegated rows are skipped without mutation.
func (*Runtime) SetMCPAuthConfigProvider ¶ added in v0.1.29
func (r *Runtime) SetMCPAuthConfigProvider(provider MCPAuthConfigProvider)
SetMCPAuthConfigProvider installs a shared MCP configuration provider (e.g. the MCP manager's repository provider) for the hosted link endpoints.
type Session ¶
type Session struct {
ID string `json:"id"`
UserID string `json:"userId,omitempty"`
Username string `json:"username"`
Email string `json:"email,omitempty"`
Subject string `json:"subject,omitempty"`
Provider string `json:"provider,omitempty"`
Scopes []string `json:"scopes,omitempty"`
Tokens *scyauth.Token `json:"-"`
// TransientRefreshRetryAt suppresses repeated refresh attempts/log spam
// after a temporary token-endpoint failure. Runtime auth code persists the
// cooldown through session metadata when a durable store is configured.
TransientRefreshRetryAt time.Time `json:"-"`
CreatedAt time.Time `json:"createdAt"`
ExpiresAt time.Time `json:"expiresAt"`
}
Session represents an authenticated user session.
Identity model:
- UserID = canonical agently users.id when available
- Subject = raw oauth/jwt subject
- Username = jwt.preferred_username or jwt.name — display name only
- Email = jwt.email — display / contact only
Identity split:
- sess.UserID is the canonical users.id UUID for internal persistence, token storage, token refresh, and session bookkeeping.
- request EffectiveUserID is the provider subject/email/username used by ownership and visibility filters, including created_by_user_id.
Do not feed sess.EffectiveUserID() into request context unless created_by_user_id has been migrated to canonical users.id. Token persistence can use the canonical UserID, but request-scoped ownership must remain subject-compatible.
func (*Session) EffectiveUserID ¶ added in v0.1.7
EffectiveUserID returns the canonical session identity when available. This is intended for session/token persistence. For request-scoped ownership or visibility checks, use Subject/Email/Username directly; those filters still compare against subject-based created_by_user_id values.
type SessionRecord ¶
type SessionRecord struct {
ID string `json:"id"`
UserID string `json:"userId,omitempty"`
Username string `json:"username"`
Email string `json:"email,omitempty"`
Subject string `json:"subject,omitempty"`
Provider string `json:"provider,omitempty"`
Scopes []string `json:"scopes,omitempty"`
AccessToken string `json:"accessToken,omitempty"`
IDToken string `json:"idToken,omitempty"`
RefreshToken string `json:"refreshToken,omitempty"`
TokenExpiresAt time.Time `json:"tokenExpiresAt,omitempty"`
CreatedAt time.Time `json:"createdAt"`
ExpiresAt time.Time `json:"expiresAt"`
}
SessionRecord is the persistent form of a session for external stores.
type SessionStore ¶
type SessionStore interface {
Get(ctx context.Context, id string) (*SessionRecord, error)
Upsert(ctx context.Context, rec *SessionRecord) error
Delete(ctx context.Context, id string) error
}
SessionStore is a pluggable backend for persistent session storage.
type SessionStoreDAO ¶
type SessionStoreDAO struct {
// contains filtered or unexported fields
}
SessionStoreDAO uses Datly to persist sessions.
func NewSessionStoreDAO ¶
func NewSessionStoreDAO(dao *datly.Service) *SessionStoreDAO
NewSessionStoreDAO constructs a Datly-backed session store.
func (*SessionStoreDAO) Delete ¶
func (s *SessionStoreDAO) Delete(ctx context.Context, id string) error
Delete removes a session by id.
func (*SessionStoreDAO) Get ¶
func (s *SessionStoreDAO) Get(ctx context.Context, id string) (*SessionRecord, error)
Get loads a session by id.
func (*SessionStoreDAO) Upsert ¶
func (s *SessionStoreDAO) Upsert(ctx context.Context, rec *SessionRecord) error
Upsert inserts or updates a session record.
type TokenStore ¶
type TokenStore interface {
Get(ctx context.Context, username, provider string) (*OAuthToken, error)
Put(ctx context.Context, token *OAuthToken) error
Delete(ctx context.Context, username, provider string) error
// TryAcquireRefreshLease atomically attempts to acquire a distributed lease
// for refreshing the token identified by (username, provider).
TryAcquireRefreshLease(ctx context.Context, username, provider, owner string, ttl time.Duration) (version int64, acquired bool, err error)
// ReleaseRefreshLease releases a previously acquired lease.
ReleaseRefreshLease(ctx context.Context, username, provider, owner string) error
// CASPut atomically updates the token only if the current version matches
// expectedVersion and the lease is held by owner.
CASPut(ctx context.Context, token *OAuthToken, expectedVersion int64, owner string) (swapped bool, err error)
}
TokenStore abstracts encrypted OAuth token persistence. Implementations may use scy-backed secrets, database storage, etc.
type TokenStoreDAO ¶
type TokenStoreDAO struct {
// contains filtered or unexported fields
}
TokenStoreDAO is a Datly-backed TokenStore with Blowfish encryption.
func NewTokenStoreDAO ¶
func NewTokenStoreDAO(dao *datly.Service, salt string, opts ...TokenStoreOption) *TokenStoreDAO
NewTokenStoreDAO creates a Datly-backed token store.
func (*TokenStoreDAO) CASPut ¶
func (s *TokenStoreDAO) CASPut(ctx context.Context, token *OAuthToken, expectedVersion int64, owner string) (bool, error)
CASPut atomically updates the token only if the current version matches expectedVersion and the lease is held by owner. On success, bumps version and clears the lease. Returns (true, nil) if the swap succeeded.
func (*TokenStoreDAO) Delete ¶
func (s *TokenStoreDAO) Delete(ctx context.Context, username, provider string) error
Delete atomically clears a token while retaining its audit row.
func (*TokenStoreDAO) Get ¶
func (s *TokenStoreDAO) Get(ctx context.Context, username, provider string) (*OAuthToken, error)
Get loads and decrypts a token from DB.
func (*TokenStoreDAO) GetExact ¶ added in v0.1.29
func (s *TokenStoreDAO) GetExact(ctx context.Context, username, provider string) (*OAuthToken, error)
GetExact loads and decrypts the token stored under exactly (username, provider). Unlike Get it never falls back to another provider row: a miss is a miss. Delegated MCP credential code must use this method exclusively.
func (*TokenStoreDAO) ListDelegated ¶ added in v0.1.29
func (s *TokenStoreDAO) ListDelegated(ctx context.Context, userID string) ([]*OAuthToken, error)
ListDelegated returns every delegated (mcp:v1) token row stored for a canonical user. It implements DelegatedTokenLister for the user-lifecycle cleanup hook; workspace rows are never included.
func (*TokenStoreDAO) Put ¶
func (s *TokenStoreDAO) Put(ctx context.Context, token *OAuthToken) error
Put encrypts and saves a token via the Datly write handler.
func (*TokenStoreDAO) ReleaseRefreshLease ¶
func (s *TokenStoreDAO) ReleaseRefreshLease(ctx context.Context, username, provider, owner string) error
ReleaseRefreshLease releases a previously acquired lease, resetting the row to idle. The owner check ensures we only release our own lease.
func (*TokenStoreDAO) ScanExpiring ¶ added in v0.1.7
func (s *TokenStoreDAO) ScanExpiring(ctx context.Context, horizon time.Time) ([]*OAuthToken, error)
ScanExpiring returns all stored tokens expiring before horizon that carry a refresh token. Called by the background watcher to refresh tokens for idle users who have no active in-memory session.
func (*TokenStoreDAO) TryAcquireRefreshLease ¶
func (s *TokenStoreDAO) TryAcquireRefreshLease(ctx context.Context, username, provider, owner string, ttl time.Duration) (int64, bool, error)
TryAcquireRefreshLease atomically attempts to acquire a distributed lease for refreshing the token identified by (username, provider). The lease is granted only when the row is idle or has an expired lease. All timestamp comparisons use the DB server's CURRENT_TIMESTAMP to avoid clock-skew issues.
func (*TokenStoreDAO) ValidateProviderColumnWidth ¶ added in v0.1.29
func (s *TokenStoreDAO) ValidateProviderColumnWidth(ctx context.Context, width int) error
ValidateProviderColumnWidth verifies the live user_oauth_token.provider column can hold at least width characters (the fixed 71-character delegated storage key). MySQL silently truncating a delegated key is never accepted; dialects without declared column widths (sqlite) pass.
type TokenStoreOption ¶ added in v0.1.29
type TokenStoreOption func(*TokenStoreDAO)
TokenStoreOption configures a TokenStoreDAO.
func WithDelegatedSalt ¶ added in v0.1.29
func WithDelegatedSalt(salt string) TokenStoreOption
WithDelegatedSalt sets the encryption salt used for delegated (mcp:v1) token rows. Workspace rows keep using the base salt.
type User ¶
type User struct {
ID string `json:"id,omitempty"`
Username string `json:"username"`
Email string `json:"email,omitempty"`
DisplayName string `json:"displayName,omitempty"`
Provider string `json:"provider,omitempty"`
Subject string `json:"subject,omitempty"`
Preferences map[string]interface{} `json:"preferences,omitempty"`
// Disabled marks a deactivated canonical user: disabled users cannot use
// stored delegated credentials and fail canonical resolution.
Disabled bool `json:"disabled,omitempty"`
}
User represents a registered user.
type UserByIDLookup ¶ added in v0.1.29
UserByIDLookup is the optional by-ID active-status lookup used by the delegated credential resolver, the background refresh watcher and the link endpoints: a disabled or deleted canonical user cannot use delegated tokens. It is a separate interface so existing UserService implementations remain compatible.
type UserInfo ¶ added in v0.1.3
UserInfo carries minimal identity extracted from auth context or JWT claims.
func RuntimeUserFromContext ¶ added in v0.1.3
type UserService ¶
type UserService interface {
GetByUsername(ctx context.Context, username string) (*User, error)
GetBySubjectAndProvider(ctx context.Context, subject, provider string) (*User, error)
Upsert(ctx context.Context, user *User) error
UpsertWithProvider(ctx context.Context, username, displayName, email, provider, subject string) (string, error)
UpdateHashIPByID(ctx context.Context, id, hash string) error
UpdatePreferences(ctx context.Context, username string, patch *PreferencesPatch) error
}
UserService abstracts user CRUD. Implementations may use Datly, SQL, or an in-memory store.
type VerifiedWorkspaceIdentity ¶ added in v0.1.29
VerifiedWorkspaceIdentity carries an already-verified workspace identity. Both session and bearer authentication paths must build this value only after token/session verification and pass it to the shared canonical resolver; the resolver never verifies credentials itself.
Source Files
¶
- canonical_identity.go
- config.go
- context.go
- datly_store_logging.go
- delegated_key.go
- extension_core.go
- extension_session_handlers.go
- handler.go
- jwt.go
- jwt_handlers.go
- mcp_auth_invalidation.go
- mcp_credential_resolver.go
- mcp_delegated_auth.go
- mcp_link_service.go
- mcp_oauth_callback.go
- mcp_oauth_handlers.go
- mcp_oauth_state.go
- mcp_rate_limit.go
- middleware.go
- oauth_handlers.go
- oauth_state_store.go
- oauth_support.go
- preferences.go
- runtime_auth.go
- runtime_loader.go
- runtime_refresh.go
- runtime_types.go
- session.go
- sessionstore_datly.go
- token_owner.go
- token_store.go
- tokenprovider_factory.go
- tokenstore_adapter.go
- tokenstore_datly.go
- user.go
- user_datly.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package providerregistry implements the workspace OAuth provider registry.
|
Package providerregistry implements the workspace OAuth provider registry. |