memory

package
v0.2.87 Latest Latest
Warning

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

Go to latest
Published: Mar 17, 2026 License: Apache-2.0 Imports: 17 Imported by: 1

Documentation

Overview

Package memory provides an in-memory implementation of the OAuth storage interfaces.

This package implements TokenStore, ClientStore, and FlowStore interfaces using Go's built-in maps with mutex protection for thread safety. It is suitable for development, testing, and single-instance deployments where persistence is not required.

Features:

  • Thread-safe operations using sync.RWMutex
  • Automatic cleanup of expired tokens, codes, and flows
  • Configurable cleanup intervals
  • Token encryption support via Encryptor
  • Audit logging support via Auditor

For production deployments requiring persistence or multi-instance deployments, use the storage/valkey package instead.

Example usage:

store := memory.New()
defer store.Stop()

// Use store for TokenStore, ClientStore, and FlowStore interfaces
server, _ := oauth.NewServer(provider, store, store, store, config, logger)

Package memory provides an in-memory implementation of all storage interfaces. It is suitable for development, testing, and single-instance deployments.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type RefreshTokenFamily

type RefreshTokenFamily struct {
	FamilyID   string    // Unique identifier for this token family
	UserID     string    // User who owns this family
	ClientID   string    // Client who owns this family
	Generation int       // Increments with each rotation
	IssuedAt   time.Time // When this generation was issued
	Revoked    bool      // True if family has been revoked due to reuse detection
	RevokedAt  time.Time // When this family was revoked (for cleanup purposes)
}

RefreshTokenFamily tracks a family of refresh tokens for reuse detection (OAuth 2.1)

type Store

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

Store is an in-memory implementation of all storage interfaces. It implements TokenStore, ClientStore, FlowStore, RefreshTokenFamilyStore, and TokenRevocationStore.

func New

func New() *Store

New creates a new in-memory store with default cleanup interval (1 minute) and default revoked family retention (90 days)

func NewWithInterval

func NewWithInterval(cleanupInterval time.Duration) *Store

NewWithInterval creates a new in-memory store with custom cleanup interval. If cleanupInterval is 0 or negative, uses default of 1 minute.

func (*Store) AtomicCheckAndMarkAuthCodeUsed added in v0.1.11

func (s *Store) AtomicCheckAndMarkAuthCodeUsed(_ context.Context, code string) (*storage.AuthorizationCode, error)

AtomicCheckAndMarkAuthCodeUsed atomically checks if a code is unused and marks it as used. This prevents race conditions in authorization code reuse detection. Returns the auth code if successful, or an error if code is already used.

SECURITY: This operation is atomic - only ONE concurrent request can succeed. All other concurrent requests will receive an "already used" error.

IMPORTANT: The authCode is ONLY returned on reuse errors (Used=true) to enable detection and revocation. For other errors (not found, expired), nil is returned to prevent information leakage.

func (*Store) AtomicGetAndDeleteRefreshToken added in v0.1.11

func (s *Store) AtomicGetAndDeleteRefreshToken(_ context.Context, refreshToken string) (string, string, *oauth2.Token, error)

AtomicGetAndDeleteRefreshToken atomically retrieves and deletes a refresh token. This prevents race conditions in refresh token rotation and reuse detection. Returns the userID, clientID, and provider token if successful.

SECURITY: This operation is atomic - only ONE concurrent request can succeed. All other concurrent requests will receive a "token not found" error. SECURITY: Returns clientID for client binding validation per OAuth 2.1 Section 6.

func (*Store) CheckIPLimit

func (s *Store) CheckIPLimit(_ context.Context, ip string, maxClientsPerIP int) error

CheckIPLimit checks if an IP has reached the client registration limit

func (*Store) DeleteAuthorizationCode

func (s *Store) DeleteAuthorizationCode(_ context.Context, code string) error

DeleteAuthorizationCode removes an authorization code

func (*Store) DeleteAuthorizationState

func (s *Store) DeleteAuthorizationState(_ context.Context, stateID string) error

DeleteAuthorizationState removes an authorization state Removes both client state and provider state entries

func (*Store) DeleteRefreshToken

func (s *Store) DeleteRefreshToken(_ context.Context, refreshToken string) error

DeleteRefreshToken removes a refresh token (used for rotation)

func (*Store) DeleteToken

func (s *Store) DeleteToken(ctx context.Context, userID string) error

DeleteToken removes a token for a user

func (*Store) GetAuthorizationCode

func (s *Store) GetAuthorizationCode(_ context.Context, code string) (*storage.AuthorizationCode, error)

GetAuthorizationCode retrieves an authorization code without modifying it. The code is kept marked as "Used" to detect reuse attempts (OAuth 2.1 requirement). Expired/used codes are cleaned up by the background cleanup goroutine.

NOTE: For actual code exchange, use AtomicCheckAndMarkAuthCodeUsed instead to prevent race conditions.

func (*Store) GetAuthorizationState

func (s *Store) GetAuthorizationState(_ context.Context, stateID string) (*storage.AuthorizationState, error)

GetAuthorizationState retrieves an authorization state by client state

func (*Store) GetAuthorizationStateByProviderState

func (s *Store) GetAuthorizationStateByProviderState(_ context.Context, providerState string) (*storage.AuthorizationState, error)

GetAuthorizationStateByProviderState retrieves an authorization state by provider state This is used during provider callback validation (separate from client state)

func (*Store) GetClient

func (s *Store) GetClient(ctx context.Context, clientID string) (*storage.Client, error)

GetClient retrieves a client by ID

func (*Store) GetRefreshTokenFamily

func (s *Store) GetRefreshTokenFamily(_ context.Context, refreshToken string) (*storage.RefreshTokenFamilyMetadata, error)

GetRefreshTokenFamily retrieves family metadata for a refresh token

func (*Store) GetRefreshTokenInfo

func (s *Store) GetRefreshTokenInfo(_ context.Context, refreshToken string) (string, error)

GetRefreshTokenInfo retrieves the user ID for a refresh token Returns error if token is not found or expired (with clock skew grace)

func (*Store) GetToken

func (s *Store) GetToken(ctx context.Context, userID string) (*oauth2.Token, error)

GetToken retrieves an oauth2.Token for a user and decrypts if necessary

func (*Store) GetTokenMetadata added in v0.1.34

func (s *Store) GetTokenMetadata(tokenID string) (*storage.TokenMetadata, error)

GetTokenMetadata retrieves metadata for a token (including RFC 8707 audience)

func (*Store) GetTokensByUserClient added in v0.1.9

func (s *Store) GetTokensByUserClient(_ context.Context, userID, clientID string) ([]string, error)

GetTokensByUserClient retrieves all token IDs for a user+client combination. This is primarily for testing and debugging purposes.

func (*Store) GetUserInfo

func (s *Store) GetUserInfo(ctx context.Context, userID string) (*providers.UserInfo, error)

GetUserInfo retrieves user information

func (*Store) ListClients

func (s *Store) ListClients(_ context.Context) ([]*storage.Client, error)

ListClients lists all registered clients

func (*Store) RevokeAllTokensForUserClient added in v0.1.9

func (s *Store) RevokeAllTokensForUserClient(_ context.Context, userID, clientID string) (int, error)

RevokeAllTokensForUserClient revokes all tokens (access + refresh) for a specific user+client combination. This implements the OAuth 2.1 requirement for authorization code reuse detection. Returns the number of tokens revoked and any error encountered.

func (*Store) RevokeRefreshTokenFamily

func (s *Store) RevokeRefreshTokenFamily(_ context.Context, familyID string) error

RevokeRefreshTokenFamily revokes all tokens in a family (for reuse detection) This is called when token reuse is detected (OAuth 2.1 security requirement)

func (*Store) SaveAuthorizationCode

func (s *Store) SaveAuthorizationCode(ctx context.Context, code *storage.AuthorizationCode) error

SaveAuthorizationCode saves an issued authorization code

func (*Store) SaveAuthorizationState

func (s *Store) SaveAuthorizationState(_ context.Context, state *storage.AuthorizationState) error

SaveAuthorizationState saves the state of an ongoing authorization flow Stores by both client state (StateID) and provider state (ProviderState) for dual lookup

func (*Store) SaveClient

func (s *Store) SaveClient(ctx context.Context, client *storage.Client) error

SaveClient saves a registered client and tracks IP for DoS protection

func (*Store) SaveRefreshToken

func (s *Store) SaveRefreshToken(_ context.Context, refreshToken, userID string, expiresAt time.Time) error

SaveRefreshToken saves a refresh token mapping to user ID with expiry For OAuth 2.1 compliance, also tracks token family for reuse detection

func (*Store) SaveRefreshTokenWithFamily

func (s *Store) SaveRefreshTokenWithFamily(_ context.Context, refreshToken, userID, clientID, familyID string, generation int, expiresAt time.Time) error

SaveRefreshTokenWithFamily saves a refresh token with family tracking for reuse detection This is the OAuth 2.1 compliant version that enables token theft detection

func (*Store) SaveToken

func (s *Store) SaveToken(ctx context.Context, userID string, token *oauth2.Token) error

SaveToken saves an oauth2.Token for a user with optional encryption

func (*Store) SaveTokenMetadata added in v0.1.9

func (s *Store) SaveTokenMetadata(tokenID, userID, clientID, tokenType string) error

SaveTokenMetadata saves metadata for a token (for revocation tracking) This should be called whenever a token is issued to a user for a client

func (*Store) SaveTokenMetadataWithAudience added in v0.1.34

func (s *Store) SaveTokenMetadataWithAudience(tokenID, userID, clientID, tokenType, audience string) error

SaveTokenMetadataWithAudience saves metadata for a token including RFC 8707 audience This should be called whenever a token is issued to a user for a client

func (*Store) SaveTokenMetadataWithFamily added in v0.2.81

func (s *Store) SaveTokenMetadataWithFamily(tokenID, userID, clientID, tokenType, audience, familyID string, scopes []string) error

SaveTokenMetadataWithFamily saves metadata for a token including audience, scopes, and refresh token family ID. The familyID links the token to a session (refresh token family) for per-session state tracking.

func (*Store) SaveTokenMetadataWithScopesAndAudience added in v0.1.41

func (s *Store) SaveTokenMetadataWithScopesAndAudience(tokenID, userID, clientID, tokenType, audience string, scopes []string) error

SaveTokenMetadataWithScopesAndAudience saves metadata for a token including RFC 8707 audience and MCP 2025-11-25 scopes This should be called whenever a token is issued to a user for a client

func (*Store) SaveUserInfo

func (s *Store) SaveUserInfo(ctx context.Context, userID string, info *providers.UserInfo) error

SaveUserInfo saves user information

func (*Store) SetEncryptor

func (s *Store) SetEncryptor(enc *security.Encryptor)

SetEncryptor sets the token encryptor for encryption at rest

func (*Store) SetInstrumentation added in v0.1.26

func (s *Store) SetInstrumentation(inst *instrumentation.Instrumentation)

SetInstrumentation sets OpenTelemetry instrumentation for the store

func (*Store) SetLogger

func (s *Store) SetLogger(logger *slog.Logger)

SetLogger sets a custom logger

func (*Store) SetRevokedFamilyRetentionDays added in v0.1.11

func (s *Store) SetRevokedFamilyRetentionDays(days int64)

SetRevokedFamilyRetentionDays sets the retention period for revoked token family metadata. This should be called after New() and before starting the server. The retention period is used for forensics and security auditing. Default: 90 days (if not set)

func (*Store) Stop

func (s *Store) Stop()

Stop gracefully stops the cleanup goroutine

func (*Store) TrackClientIP

func (s *Store) TrackClientIP(ip string)

TrackClientIP increments the client count for an IP address

func (*Store) ValidateClientSecret

func (s *Store) ValidateClientSecret(ctx context.Context, clientID, clientSecret string) error

ValidateClientSecret validates a client's secret using bcrypt Uses constant-time operations to prevent timing attacks

Jump to

Keyboard shortcuts

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