Documentation
¶
Overview ¶
Package passwordreset provides typed model-first password recovery. The challenge and model write commit together; resetting never signs a user in.
Index ¶
- Constants
- type Issued
- type Model
- type Reset
- func (r *Reset[M, K]) Complete(ctx context.Context, token Token[M], plain password.Plaintext) (M, error)
- func (r *Reset[M, K]) Issue(ctx context.Context, reference model.Reference[M, K]) (Issued[M], error)
- func (r *Reset[M, K]) Prune(ctx context.Context, limit int) (uint64, error)
- func (r *Reset[M, K]) Revoke(ctx context.Context, reference model.Reference[M, K]) (bool, error)
- func (r *Reset[M, K]) Validate() error
- func (r *Reset[M, K]) WithObserver(observer auth.Observer) (*Reset[M, K], error)
- type Token
Constants ¶
const DefaultLifetime = time.Hour
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Model ¶
type Model[M model.Identifiable, K any] struct { Lock func(context.Context, *database.Tx, K) (value.Optional[M], error) Email func(M) string EmailRevision func(M) challenge.Revision[M] Hash func(M) password.Hash SetPassword func(context.Context, *database.Tx, M, password.Hash) (M, error) ValidatePassword func(context.Context, password.Plaintext) error Invalidate func(context.Context, *database.Tx, M) error Eligible func(context.Context, M) (bool, error) }
Model describes domain behavior using stored fields and generated mutations. Lock uses ForUpdate on tx. SetPassword must return the full updated model. ValidatePassword owns domain strength rules, not encoding/hashing policy. Invalidate MUST invalidate applicable credentials in the SAME transaction; failure rolls back the password change and link consumption. Do not call a store method that opens another transaction or defer revocation to after-commit. EmailRevision reads a nonzero persisted generation. Model lifecycle behavior must replace it whenever the stored email changes, even if an old email is restored later. Do not rotate it merely when issuing a link or resetting a password: verification links for an unchanged email remain independent. Additional outbox/audit writes may use tx. These callbacks must not send email. Eligible optionally replaces the provider's eligibility for this flow.
type Reset ¶
type Reset[M model.Identifiable, K any] struct { // contains filtered or unexported fields }
func WithLockout ¶
func WithLockout[M model.Identifiable, K, I any](reset *Reset[M, K], throttle lockout.Throttle[I], key func(M) I) (*Reset[M, K], error)
WithLockout returns a reset view that clears the login throttle for the reset account after the reset commits, using key to derive the same login key the PasswordLogin uses (for example the stored email). It clears the account ceiling and the resetting client's window. Clearing is best effort: the committed reset is never undone, and a lockout backend failure leaves the old windows to expire on their own.
func (*Reset[M, K]) Complete ¶
func (r *Reset[M, K]) Complete(ctx context.Context, token Token[M], plain password.Plaintext) (M, error)
Complete checks the link and current model before expensive hashing. The bounded KDF runs while the model is locked, avoiding a gap between validation and replacement. Apply request throttling before this operation. It returns no authentication proof; MFA requirements remain unchanged.