Documentation
¶
Overview ¶
Package statedb provides SQLite and PostgreSQL protocol state storage.
Index ¶
- Variables
- func CheckRuntime(ctx context.Context, db interface{ ... }) error
- func CheckSchema(ctx context.Context, db interface{ ... }) error
- func DecryptCredential(secret [32]byte, sid, clientID, connectorID string, nonce, ciphertext []byte) ([]byte, error)
- func DecryptTemporaryCredential(key []byte, flowID, clientID, connectorID string, nonce, ciphertext []byte) ([]byte, error)
- func EncryptCredential(secret [32]byte, sid, clientID, connectorID string, plaintext []byte) ([]byte, []byte, error)
- func EncryptTemporaryCredential(key []byte, flowID, clientID, connectorID string, plaintext []byte) ([]byte, []byte, error)
- func GenerateAuthCode() (string, error)
- func GenerateStateToken() (string, error)
- func MigratePostgreSQL(connectionString string) error
- type AuthCode
- type AuthCodeBinding
- type GrantAction
- type ManagedGrant
- type OAuthState
- type OTPFlow
- type OTPResendError
- type PushedRequest
- type RefreshClaim
- type RefreshGrant
- type RefreshMaterial
- type RevocationCredential
- type Store
- func (s *Store) AbortUpstreamRefresh(sid string, claim RefreshClaim) error
- func (s *Store) ClaimRefresh(current RefreshMaterial, clientID string, now time.Time, ttl time.Duration) (RefreshGrant, RefreshClaim, time.Time, error)
- func (s *Store) Close() error
- func (s *Store) CompleteClaimedRefresh(current, replacement RefreshMaterial, grant RefreshGrant, claim RefreshClaim, ...) (time.Time, error)
- func (s *Store) ConsumeAuthCode(expected AuthCode, binding AuthCodeBinding, grant *RefreshGrant, ...) error
- func (s *Store) ConsumeGrantActionAndRevoke(token, email, sid, action string, now time.Time) error
- func (s *Store) ConsumeIdentitySelection(token string, now time.Time) (string, string, string, []upstream.Email, error)
- func (s *Store) ConsumeOTP(challengeID, code string, secret []byte, now time.Time) (OTPFlow, error)
- func (s *Store) ConsumePushedRequest(requestURI, clientID string, now time.Time) (*PushedRequest, error)
- func (s *Store) CreateGrantAction(token, email, sid, action string, now, expiry time.Time) error
- func (s *Store) CreateGrantActions(actions []GrantAction, email, action string, now, expiry time.Time) error
- func (s *Store) CreateIdentitySelection(token, state, connector, subject string, emails []upstream.Email, ...) error
- func (s *Store) CreateOTP(challengeID, email, code string, flow OTPFlow, secret []byte, now time.Time, ...) (time.Time, error)
- func (s *Store) CreateRefreshGrant(grant RefreshGrant, material RefreshMaterial, nonce, ciphertext []byte, ...) error
- func (s *Store) CredentialVerified(connectorID, subject, email string) (exists, local bool, err error)
- func (s *Store) GetAndDeleteAuthCode(codeStr string) (*AuthCode, error)
- func (s *Store) GetAndDeleteState(stateToken string) (*OAuthState, error)
- func (s *Store) ListActiveGrants(email string, now time.Time) ([]ManagedGrant, error)
- func (s *Store) LoadFlowCredential(flowID, clientID, connectorID string, now time.Time) ([]byte, []byte, error)
- func (s *Store) MarkUpstreamRefreshStarted(sid string, claim RefreshClaim, now time.Time) error
- func (s *Store) OTPFlow(challengeID string, now time.Time) (OTPFlow, time.Time, error)
- func (s *Store) PeekAuthCode(codeStr string, now time.Time) (*AuthCode, error)
- func (s *Store) PeekState(stateToken string) (*OAuthState, error)
- func (s *Store) PrepareRefresh(current RefreshMaterial, clientID string, now time.Time) (RefreshGrant, time.Time, error)
- func (s *Store) Ready(ctx context.Context) error
- func (s *Store) ReleaseRefreshClaim(sid string, claim RefreshClaim) error
- func (s *Store) ResendOTP(challengeID, code string, secret []byte, now time.Time, ttl time.Duration) (OTPFlow, time.Time, error)
- func (s *Store) RevokeCredential(credential RevocationCredential, clientID, proofJKT, reason string, ...) error
- func (s *Store) RevokeGrant(sid, clientID, reason string, now time.Time) error
- func (s *Store) RevokeRefreshToken(material RefreshMaterial, clientID, reason string, now time.Time) error
- func (s *Store) RotateRefreshToken(current, replacement RefreshMaterial, clientID string, now time.Time) (RefreshGrant, time.Time, error)
- func (s *Store) SaveAuthCode(code *AuthCode) error
- func (s *Store) SaveCredential(connectorID, subject, email string, local bool, verifiedAt time.Time) error
- func (s *Store) SaveFlowCredential(from, to, clientID, connectorID string, nonce, ciphertext []byte, ...) error
- func (s *Store) SavePushedRequest(p *PushedRequest) error
- func (s *Store) SaveState(state *OAuthState) error
Constants ¶
This section is empty.
Variables ¶
var ( // ErrInvalidOTPChallenge identifies an unknown, expired, consumed, or attempt-limited challenge. ErrInvalidOTPChallenge = errors.New("invalid OTP challenge") // ErrInvalidOTPCode identifies a code mismatch for an otherwise active challenge. ErrInvalidOTPCode = errors.New("invalid OTP code") // ErrOTPSendLimit identifies an address that exceeded the hourly OTP send quota. ErrOTPSendLimit = errors.New("OTP send limit exceeded") )
var ( // ErrInvalidGrant identifies unknown, malformed, expired, revoked, or mismatched refresh material. ErrInvalidGrant = errors.New("invalid grant") // ErrRefreshReplay identifies reuse of a consumed token whose family has been compromised. ErrRefreshReplay = errors.New("refresh token replay") // ErrRefreshBusy identifies a refresh family currently processed by another request. ErrRefreshBusy = errors.New("refresh token is being processed") // ErrRefreshCollision identifies a generated handle that already exists. ErrRefreshCollision = errors.New("refresh token handle collision") // ErrCredentialIndeterminate identifies a claim that expired after upstream rotation began. ErrCredentialIndeterminate = errors.New("upstream credential is indeterminate") )
Functions ¶
func CheckRuntime ¶
func CheckRuntime(ctx context.Context, db interface { QueryRowContext(context.Context, string, ...any) *sql.Row }) error
CheckRuntime verifies schema compatibility and the runtime role's state-table privileges.
func CheckSchema ¶
func CheckSchema(ctx context.Context, db interface { QueryRowContext(context.Context, string, ...any) *sql.Row }) error
CheckSchema refuses absent, dirty, newer, or older PostgreSQL schemas.
func DecryptCredential ¶
func DecryptCredential(secret [32]byte, sid, clientID, connectorID string, nonce, ciphertext []byte) ([]byte, error)
DecryptCredential authenticates and decrypts an upstream credential.
func DecryptTemporaryCredential ¶
func DecryptTemporaryCredential(key []byte, flowID, clientID, connectorID string, nonce, ciphertext []byte) ([]byte, error)
DecryptTemporaryCredential decrypts and authenticates a flow credential.
func EncryptCredential ¶
func EncryptCredential(secret [32]byte, sid, clientID, connectorID string, plaintext []byte) ([]byte, []byte, error)
EncryptCredential encrypts an upstream credential using AES-256-GCM and fresh randomness.
func EncryptTemporaryCredential ¶
func EncryptTemporaryCredential(key []byte, flowID, clientID, connectorID string, plaintext []byte) ([]byte, []byte, error)
EncryptTemporaryCredential encrypts a flow credential with the configured master key.
func GenerateAuthCode ¶
GenerateAuthCode creates a new cryptographically secure random authorization code.
func GenerateStateToken ¶
GenerateStateToken creates a new cryptographically secure random state token.
func MigratePostgreSQL ¶
MigratePostgreSQL explicitly applies all embedded PostgreSQL state migrations.
Types ¶
type AuthCode ¶
type AuthCode struct {
Code string
ClientID string
RedirectURI string
CodeChallenge string
Email string
EmailVerified bool
Nonce string
CreatedAt time.Time
ExpiresAt time.Time
Scopes string
RefreshMode string
AuthTime time.Time
ConnectorID string
UpstreamSubject string
OfflineConsent bool
DPoPJKT string
PushedAuthorization bool
}
AuthCode represents a stored authorization code.
type AuthCodeBinding ¶
type AuthCodeBinding struct {
ClientID, RedirectURI, CodeChallenge string
}
AuthCodeBinding contains the request values revalidated during code consumption.
type GrantAction ¶
GrantAction binds a plaintext action token to one grant.
type ManagedGrant ¶
ManagedGrant is non-secret grant metadata shown to its owner.
type OAuthState ¶
type OAuthState struct {
StateToken string
ClientID string
RedirectURI string
CodeChallenge string
Nonce string
OIDCState string
CreatedAt time.Time
ExpiresAt time.Time
ConnectorID string
Scopes string
RefreshMode string
AuthTime time.Time
OfflineConsent bool
Purpose string
DPoPJKT string
PushedAuthorization bool
}
OAuthState represents stored OAuth state parameters.
type OTPFlow ¶
type OTPFlow struct {
FlowID string
ConnectorID string
Subject string
Email string
ClientID string
RedirectURI string
CodeChallenge string
Nonce string
OIDCState string
Scopes string
RefreshMode string
AuthTime time.Time
OfflineConsent bool
Purpose string
DPoPJKT string
PushedAuthorization bool
}
OTPFlow preserves the authorization and identity context of an OTP challenge.
type OTPResendError ¶ added in v2.1.0
OTPResendError describes a rejected resend and how long a caller should wait before retrying.
func (*OTPResendError) Error ¶ added in v2.1.0
func (*OTPResendError) Error() string
Error returns a client-safe resend rejection message.
type PushedRequest ¶
type PushedRequest struct {
RequestURI, ClientID, RedirectURI, ResponseType, Scopes, State, Nonce string
CodeChallenge, CodeChallengeMethod, Prompt, DPoPJKT string
CreatedAt, ExpiresAt time.Time
}
PushedRequest is a short-lived, one-time RFC 9126 authorization request.
type RefreshClaim ¶
RefreshClaim fences one connector-backed refresh operation.
type RefreshGrant ¶
type RefreshGrant struct {
SID string
ClientID string
Email string
EmailVerified bool
Scopes string
ConnectorID string
UpstreamSubject string
Mode string
AuthTime time.Time
IdleTTL time.Duration
AbsoluteExpiry time.Time
CredentialNonce []byte
CredentialCiphertext []byte
UpstreamAccessExpiry time.Time
UpstreamRefreshExpiry time.Time
UpstreamAccessNonExpiring bool
DPoPJKT string
}
RefreshGrant is the durable downstream refresh family metadata.
type RefreshMaterial ¶
type RefreshMaterial struct {
Token string
Handle [16]byte
Secret [32]byte
HandleHash [32]byte
TokenHash [32]byte
}
RefreshMaterial is the parsed canonical split-secret refresh token.
func GenerateRefreshMaterial ¶
func GenerateRefreshMaterial() (RefreshMaterial, error)
GenerateRefreshMaterial creates a canonical random ert1 token.
func ParseRefreshToken ¶
func ParseRefreshToken(token string) (RefreshMaterial, error)
ParseRefreshToken parses and canonicality-checks an ert1 split-secret token.
type RevocationCredential ¶
type RevocationCredential struct {
Refresh *RefreshMaterial
SID string
TokenJKT string
RequireTokenBinding bool
}
RevocationCredential identifies a submitted credential without granting endpoint code direct state access.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store provides persistent storage for OAuth flows and single-use credentials.
func NewPostgreSQL ¶
func NewPostgreSQL(ctx context.Context, connectionString string, maxConnections int, queryTimeout time.Duration, logger *slog.Logger) (*Store, error)
NewPostgreSQL opens a migrated PostgreSQL state database and verifies its compatibility.
func (*Store) AbortUpstreamRefresh ¶
func (s *Store) AbortUpstreamRefresh(sid string, claim RefreshClaim) error
AbortUpstreamRefresh releases a claim after a definitive provider response proves no rotation occurred.
func (*Store) ClaimRefresh ¶
func (s *Store) ClaimRefresh(current RefreshMaterial, clientID string, now time.Time, ttl time.Duration) (RefreshGrant, RefreshClaim, time.Time, error)
ClaimRefresh verifies a complete token and durably claims its active grant.
func (*Store) CompleteClaimedRefresh ¶
func (s *Store) CompleteClaimedRefresh(current, replacement RefreshMaterial, grant RefreshGrant, claim RefreshClaim, nonce, ciphertext []byte, absoluteExpiry, now time.Time) (time.Time, error)
CompleteClaimedRefresh conditionally rotates a claimed token and replaces its encrypted credential.
func (*Store) ConsumeAuthCode ¶
func (s *Store) ConsumeAuthCode(expected AuthCode, binding AuthCodeBinding, grant *RefreshGrant, material RefreshMaterial, now time.Time) error
ConsumeAuthCode atomically verifies and consumes an unchanged code and optionally creates its initial refresh grant.
func (*Store) ConsumeGrantActionAndRevoke ¶
ConsumeGrantActionAndRevoke atomically consumes a matching action and revokes its exact active grant.
func (*Store) ConsumeIdentitySelection ¶
func (s *Store) ConsumeIdentitySelection(token string, now time.Time) (string, string, string, []upstream.Email, error)
ConsumeIdentitySelection atomically consumes an unexpired opaque selection reference.
func (*Store) ConsumeOTP ¶
ConsumeOTP atomically limits attempts and makes successful codes single-use.
func (*Store) ConsumePushedRequest ¶
func (s *Store) ConsumePushedRequest(requestURI, clientID string, now time.Time) (*PushedRequest, error)
ConsumePushedRequest deletes and returns one client-bound, unexpired request.
func (*Store) CreateGrantAction ¶
CreateGrantAction stores only a hash of a short-lived action token.
func (*Store) CreateGrantActions ¶
func (s *Store) CreateGrantActions(actions []GrantAction, email, action string, now, expiry time.Time) error
CreateGrantActions stores hashes of short-lived action tokens in one operation.
func (*Store) CreateIdentitySelection ¶
func (s *Store) CreateIdentitySelection(token, state, connector, subject string, emails []upstream.Email, stateTTL, selectionTTL time.Duration) error
CreateIdentitySelection stores identity assertions and keeps their active OAuth state valid for the same lifetime.
func (*Store) CreateOTP ¶
func (s *Store) CreateOTP(challengeID, email, code string, flow OTPFlow, secret []byte, now time.Time, ttl time.Duration) (time.Time, error)
CreateOTP atomically enforces the address-only hourly quota, creates a challenge, and returns its expiry.
func (*Store) CreateRefreshGrant ¶
func (s *Store) CreateRefreshGrant(grant RefreshGrant, material RefreshMaterial, nonce, ciphertext []byte, now time.Time) error
CreateRefreshGrant atomically creates a grant and its first token.
func (*Store) CredentialVerified ¶
func (s *Store) CredentialVerified(connectorID, subject, email string) (exists, local bool, err error)
CredentialVerified reports whether this exact connector identity and email was accepted before.
func (*Store) GetAndDeleteAuthCode ¶
GetAndDeleteAuthCode retrieves and atomically deletes an authorization code (single-use enforcement).
func (*Store) GetAndDeleteState ¶
func (s *Store) GetAndDeleteState(stateToken string) (*OAuthState, error)
GetAndDeleteState retrieves and atomically deletes a state token (single-use enforcement).
func (*Store) ListActiveGrants ¶
ListActiveGrants returns only active and unexpired grants for an exact normalized email.
func (*Store) LoadFlowCredential ¶
func (s *Store) LoadFlowCredential(flowID, clientID, connectorID string, now time.Time) ([]byte, []byte, error)
LoadFlowCredential loads an encrypted, unexpired temporary credential.
func (*Store) MarkUpstreamRefreshStarted ¶
MarkUpstreamRefreshStarted durably records that provider rotation may occur.
func (*Store) OTPFlow ¶
OTPFlow retrieves the authorization context and expiry for an active challenge.
func (*Store) PeekAuthCode ¶
PeekAuthCode retrieves a valid authorization code without consuming it.
func (*Store) PeekState ¶
func (s *Store) PeekState(stateToken string) (*OAuthState, error)
PeekState retrieves a valid state token without consuming it.
func (*Store) PrepareRefresh ¶
func (s *Store) PrepareRefresh(current RefreshMaterial, clientID string, now time.Time) (RefreshGrant, time.Time, error)
PrepareRefresh verifies refresh material without consuming it and returns its current grant and token expiry.
func (*Store) Ready ¶
Ready reports whether the authoritative database can answer within its query timeout.
func (*Store) ReleaseRefreshClaim ¶
func (s *Store) ReleaseRefreshClaim(sid string, claim RefreshClaim) error
ReleaseRefreshClaim releases a claim only when upstream rotation has not started.
func (*Store) ResendOTP ¶
func (s *Store) ResendOTP(challengeID, code string, secret []byte, now time.Time, ttl time.Duration) (OTPFlow, time.Time, error)
ResendOTP replaces an active challenge's code and returns its flow and new expiry without reviving dead challenges.
func (*Store) RevokeCredential ¶
func (s *Store) RevokeCredential(credential RevocationCredential, clientID, proofJKT, reason string, now time.Time) error
RevokeCredential conditionally revokes an active credential without reserving a proof.
func (*Store) RevokeGrant ¶
RevokeGrant revokes an active refresh family identified by sid and client.
func (*Store) RevokeRefreshToken ¶
func (s *Store) RevokeRefreshToken(material RefreshMaterial, clientID, reason string, now time.Time) error
RevokeRefreshToken revokes a known refresh family only when it belongs to clientID.
func (*Store) RotateRefreshToken ¶
func (s *Store) RotateRefreshToken(current, replacement RefreshMaterial, clientID string, now time.Time) (RefreshGrant, time.Time, error)
RotateRefreshToken atomically consumes a token, installs its replacement, and revokes replayed families.
func (*Store) SaveAuthCode ¶
SaveAuthCode stores an authorization code.
func (*Store) SaveCredential ¶
func (s *Store) SaveCredential(connectorID, subject, email string, local bool, verifiedAt time.Time) error
SaveCredential records a credential only after its email has been accepted.
func (*Store) SaveFlowCredential ¶
func (s *Store) SaveFlowCredential(from, to, clientID, connectorID string, nonce, ciphertext []byte, expires time.Time) error
SaveFlowCredential stores or atomically relabels an encrypted temporary credential.
func (*Store) SavePushedRequest ¶
func (s *Store) SavePushedRequest(p *PushedRequest) error
SavePushedRequest persists a bounded-lifetime pushed authorization request.
func (*Store) SaveState ¶
func (s *Store) SaveState(state *OAuthState) error
SaveState stores an OAuth state token.