oauth

package
v0.29.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: AGPL-3.0, AGPL-3.0-or-later Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	VaultKeyGitHub = "GH_OAUTH"
	VaultKeyLark   = "LARK_CLI_OAUTH"
	VaultKeyFeishu = "FEISHU_CLI_OAUTH"
)

Vault key names for the supported providers.

Variables

This section is empty.

Functions

func DeleteBundle

func DeleteBundle(ctx context.Context, vs VaultStore, userID int64, key string) error

DeleteBundle removes the vault entry identified by key for userID.

func SaveOAuthBundle

func SaveOAuthBundle(ctx context.Context, vs VaultStore, userID int64, key string, bundle OAuthBundle) error

SaveOAuthBundle serializes bundle to JSON and stores it under the given vault key for userID.

Types

type AuthCodeBroker

type AuthCodeBroker struct {
	// contains filtered or unexported fields
}

AuthCodeBroker implements the OAuth2 authorization-code flow. The user visits VerificationURI (an auth-code URL) and the callback handler calls Complete with the code returned by the provider.

func NewAuthCodeBroker

func NewAuthCodeBroker(cfg *oauth2.Config, store *FlowStore, pkce bool) *AuthCodeBroker

NewAuthCodeBroker creates an AuthCodeBroker backed by store. When pkce is true, PKCE (RFC 7636) is enabled: a verifier is generated per flow and the S256 challenge is included in the authorization URL.

func (*AuthCodeBroker) Complete

func (b *AuthCodeBroker) Complete(ctx context.Context, flowID string, code string) (*oauth2.Token, error)

Complete exchanges an authorization code for tokens and returns the token. The code comes from the OAuth callback handler's query parameter.

func (*AuthCodeBroker) Poll

func (b *AuthCodeBroker) Poll(ctx context.Context, flowID string) (FlowStatus, error)

Poll checks whether the flow has been completed externally.

func (*AuthCodeBroker) StartFlow

func (b *AuthCodeBroker) StartFlow(ctx context.Context, provider Provider, userID int64) (FlowStatus, error)

StartFlow generates a state token, constructs the authorization URL, and stores a pending FlowStatus. The user must navigate to VerificationURI.

type DeviceCodeBroker

type DeviceCodeBroker struct {
	// contains filtered or unexported fields
}

DeviceCodeBroker implements the OAuth2 device-code flow. It spawns a background goroutine that polls the token endpoint until the user authorizes the device.

func NewDeviceCodeBroker

func NewDeviceCodeBroker(cfg *oauth2.Config, store *FlowStore) *DeviceCodeBroker

NewDeviceCodeBroker creates a DeviceCodeBroker backed by store. cfg.Endpoint must have DeviceAuthEndpoint set.

func (*DeviceCodeBroker) Poll

func (b *DeviceCodeBroker) Poll(ctx context.Context, flowID string) (FlowStatus, error)

Poll checks whether the user has completed authorization for flowID.

func (*DeviceCodeBroker) StartFlow

func (b *DeviceCodeBroker) StartFlow(ctx context.Context, provider Provider, userID int64) (FlowStatus, error)

StartFlow requests a device code, stores pending state, and returns the FlowStatus the caller should display. A background goroutine polls the token endpoint until the user authorizes or the flow expires.

type FlowBroker

type FlowBroker interface {
	StartFlow(ctx context.Context, provider Provider, userID int64) (FlowStatus, error)
	Poll(ctx context.Context, flowID string) (FlowStatus, error)
}

FlowBroker is the common interface for both device-code and authorization-code OAuth flows.

type FlowState

type FlowState string

FlowState is the lifecycle state of a device-flow authorization.

const (
	FlowStatePending    FlowState = "pending"
	FlowStateAuthorized FlowState = "authorized"
	FlowStateFailed     FlowState = "failed"
	FlowStateExpired    FlowState = "expired"
)

type FlowStatus

type FlowStatus struct {
	Provider        Provider
	FlowID          string
	UserID          int64
	VerificationURI string
	UserCode        string
	ExpiresAt       time.Time
	State           FlowState
	FlowType        string        // "device_code" or "authorization_code"
	Token           *oauth2.Token // set by DeviceCodeBroker when authorized
	PKCEVerifier    string        // PKCE code verifier; set when PKCE is enabled
}

FlowStatus is the public view of an in-flight device-flow session.

type FlowStore

type FlowStore struct {
	// contains filtered or unexported fields
}

FlowStore is an in-memory store of in-flight device-flow sessions. Known limitation: a process restart loses all pending flows.

func NewFlowStore

func NewFlowStore() *FlowStore

NewFlowStore returns an empty FlowStore.

func (*FlowStore) Create

func (s *FlowStore) Create(status FlowStatus)

Create stores a new FlowStatus keyed by its FlowID.

func (*FlowStore) Delete

func (s *FlowStore) Delete(flowID string)

Delete removes the flow with the given ID from the store.

func (*FlowStore) Get

func (s *FlowStore) Get(flowID string) (FlowStatus, bool)

Get returns the FlowStatus for flowID, or false if not found.

func (*FlowStore) Update

func (s *FlowStore) Update(flowID string, state FlowState, update func(*FlowStatus))

Update sets state on the named flow and then calls update (if non-nil) to allow further mutation. The state is applied first so callers can inspect or override it inside update.

type OAuthBundle

type OAuthBundle struct {
	Version          int       `json:"version"`
	ClientID         string    `json:"client_id"`
	ClientSecret     string    `json:"client_secret"`
	AccessToken      string    `json:"access_token"`
	RefreshToken     string    `json:"refresh_token,omitempty"`
	AccessExpiresAt  time.Time `json:"access_expires_at"`
	RefreshExpiresAt time.Time `json:"refresh_expires_at,omitzero"`
	Brand            string    `json:"brand,omitempty"` // e.g. "lark" or "feishu"
}

OAuthBundle is the generic versioned vault payload for all YAML-driven OAuth providers. It replaces provider-specific bundles so TokenManager and brokers can work uniformly.

func LoadOAuthBundle

func LoadOAuthBundle(ctx context.Context, vs VaultStore, userID int64, key string) (*OAuthBundle, error)

LoadOAuthBundle retrieves and deserializes the OAuth bundle for userID under the given vault key. Returns nil, nil if no entry exists yet.

type Provider

type Provider string

Provider identifies an OAuth provider.

const (
	ProviderGitHub Provider = "github"
	ProviderLark   Provider = "lark"
)

type ProviderConfig

type ProviderConfig struct {
	ID           string
	Scopes       []string
	VaultKey     string
	Flows        []ProviderFlowConfig
	ClientID     string
	ClientSecret string
}

ProviderConfig holds the static configuration for an OAuth provider read from manifest YAML. ClientID and ClientSecret are YAML defaults; DB overrides take precedence at flow-start time.

type ProviderFlowConfig

type ProviderFlowConfig struct {
	Type          string
	AuthURL       string
	DeviceAuthURL string
	TokenURL      string
	AuthStyle     oauth2.AuthStyle
	PKCE          bool
}

ProviderFlowConfig holds the static configuration for one OAuth flow type (authorization_code or device_code) read from manifest YAML.

type ProviderRegistry

type ProviderRegistry struct {
	// contains filtered or unexported fields
}

ProviderRegistry maps OAuth provider IDs to their static ProviderConfig. It is populated from manifest oauth_providers at runtime.

func NewProviderRegistry

func NewProviderRegistry() *ProviderRegistry

NewProviderRegistry returns an empty registry.

func (*ProviderRegistry) Get

func (r *ProviderRegistry) Get(providerID string) (ProviderConfig, bool)

Get returns the ProviderConfig for providerID, or false if not registered.

func (*ProviderRegistry) GetToken

func (r *ProviderRegistry) GetToken(ctx context.Context, vs VaultStore, providerID string, userID int64) (*OAuthBundle, error)

GetToken loads the OAuthBundle for userID from vault. If the access token expires within tokenRefreshWindow and a refresh token is available, it proactively refreshes and persists the new bundle before returning. On refresh failure the existing bundle is returned so callers can decide what to do with a soon-to-expire or already-expired token.

func (*ProviderRegistry) IDs

func (r *ProviderRegistry) IDs() []string

IDs returns all registered provider IDs in sorted order.

func (*ProviderRegistry) Register

func (r *ProviderRegistry) Register(cfg ProviderConfig)

Register adds a provider's static configuration to the registry.

func (*ProviderRegistry) VaultKey

func (r *ProviderRegistry) VaultKey(providerID string) (string, bool)

VaultKey returns the vault key for providerID, or false if not registered.

type TokenManager

type TokenManager struct {
	// contains filtered or unexported fields
}

TokenManager provides host-side token validation and reads from/writes to the vault.

func NewTokenManager

func NewTokenManager(vs VaultStore) *TokenManager

NewTokenManager constructs a TokenManager backed by vs.

func (*TokenManager) GetOAuthToken

func (m *TokenManager) GetOAuthToken(ctx context.Context, providerID string, userID int64) (*OAuthBundle, error)

GetOAuthToken returns the generic OAuthBundle for providerID and userID. It delegates to the ProviderRegistry to load the bundle from vault.

func (*TokenManager) SetRegistry

func (m *TokenManager) SetRegistry(r *ProviderRegistry)

SetRegistry wires the provider registry used by GetOAuthToken.

type VaultStore

type VaultStore interface {
	Set(ctx context.Context, userID int64, name string, plaintext string) error
	Delete(ctx context.Context, userID int64, name string) error
	LoadEnv(ctx context.Context, userID int64) (map[string]string, error)
}

VaultStore is the narrow interface this package needs from the vault service.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL