Documentation
¶
Overview ¶
Package emailotp provides email-based One-Time Password (OTP) authentication for go-modular-auth, supporting passwordless sign-in, email verification, password reset, and email change flows.
Index ¶
- Constants
- Variables
- func DefaultNumericOTPGenerator(length int) (string, error)
- func SplitAtLastColon(input string) (string, string)
- func ToChangeEmailOTPIdentifier(currentEmail, newEmail string) string
- func ToOTPIdentifier(otpType OTPType, email string) string
- type AESGCMCipher
- type ChangeEmailConfig
- type ChangeEmailParams
- type ChangeEmailResult
- type CheckVerificationOTPParams
- type CheckVerificationOTPResult
- type Cipher
- type Config
- type CreateVerificationOTPParams
- type DefaultSHA256Hasher
- type EmailChangedPayload
- type GenerateOTPFunc
- type GetVerificationOTPParams
- type GetVerificationOTPResult
- type Hasher
- type OTPFailedPayload
- type OTPSentPayload
- type OTPType
- type OTPVerifiedPayload
- type Option
- func WithAllowedAttempts(attempts int) Option
- func WithAutoSignInAfterVerification(autoSignIn bool) Option
- func WithChangeEmail(enabled, verifyCurrent bool) Option
- func WithCustomCipher(cipher Cipher) Option
- func WithCustomHasher(h Hasher) Option
- func WithDisableSignUp(disable bool) Option
- func WithExpiresIn(d time.Duration) Option
- func WithGenerateOTP(fn GenerateOTPFunc) Option
- func WithOTPLength(length int) Option
- func WithOverrideDefaultEmailVerification(override bool) Option
- func WithPasswordLength(minLen, maxLen int) Option
- func WithRateLimit(window time.Duration, max int) Option
- func WithResendStrategy(strategy ResendStrategy) Option
- func WithRevokeSessionsOnPasswordReset(revoke bool) Option
- func WithSendVerificationOTP(fn SendVerificationOTPFunc) Option
- func WithSendVerificationOnSignUp(send bool) Option
- func WithStoreOTP(mode StoreOTPMode, secretKey ...string) Option
- type PasswordResetPayload
- type Plugin
- func (p *Plugin) ChangeEmailEmailOTP(ctx context.Context, params *ChangeEmailParams) (*ChangeEmailResult, error)
- func (p *Plugin) CheckVerificationOTP(ctx context.Context, params *CheckVerificationOTPParams) (*CheckVerificationOTPResult, error)
- func (p *Plugin) Config() Config
- func (p *Plugin) CreateVerificationOTP(ctx context.Context, params *CreateVerificationOTPParams) (string, error)
- func (p *Plugin) GetVerificationOTP(ctx context.Context, params *GetVerificationOTPParams) (*GetVerificationOTPResult, error)
- func (p *Plugin) ID() string
- func (p *Plugin) Init(ctx *plugin.Context) error
- func (p *Plugin) Repository() Repository
- func (p *Plugin) RequestEmailChangeEmailOTP(ctx context.Context, params *RequestEmailChangeParams) (*RequestEmailChangeResult, error)
- func (p *Plugin) RequestPasswordResetEmailOTP(ctx context.Context, params *RequestPasswordResetParams) (*RequestPasswordResetResult, error)
- func (p *Plugin) ResetPasswordEmailOTP(ctx context.Context, params *ResetPasswordParams) (*ResetPasswordResult, error)
- func (p *Plugin) SendVerificationOTP(ctx context.Context, params *SendVerificationOTPParams) (*SendVerificationOTPResult, error)
- func (p *Plugin) SignInEmailOTP(ctx context.Context, params *SignInEmailOTPParams) (*SignInEmailOTPResult, error)
- func (p *Plugin) VerifyEmailOTP(ctx context.Context, params *VerifyEmailOTPParams) (*VerifyEmailOTPResult, error)
- type RateLimitConfig
- type Repository
- type RequestEmailChangeParams
- type RequestEmailChangeResult
- type RequestPasswordResetParams
- type RequestPasswordResetResult
- type ResendStrategy
- type ResetPasswordParams
- type ResetPasswordResult
- type SendEmailData
- type SendOTPPendingPayload
- type SendVerificationOTPFunc
- type SendVerificationOTPParams
- type SendVerificationOTPResult
- type SignInEmailOTPParams
- type SignInEmailOTPResult
- type SignInSuccessPayload
- type StoreOTPMode
- type VerificationRecord
- type VerifyBeforePayload
- type VerifyEmailOTPParams
- type VerifyEmailOTPResult
Constants ¶
const ( // EventEmailOTPSendBefore is emitted right before dispatching an OTP to the recipient email. // Payload: *SendOTPPendingPayload EventEmailOTPSendBefore = "emailotp:send:before" // EventEmailOTPSent is emitted immediately after an OTP has been successfully dispatched. // Payload: *OTPSentPayload EventEmailOTPSent = "emailotp:send:after" // EventEmailOTPVerifyBefore is emitted right before verifying a submitted OTP code. // Payload: *VerifyBeforePayload EventEmailOTPVerifyBefore = "emailotp:verify:before" // EventEmailOTPVerified is emitted after an OTP code has been successfully verified. // Payload: *OTPVerifiedPayload EventEmailOTPVerified = "emailotp:verify:after" // EventEmailOTPSignInSuccess is emitted when a user successfully authenticates or registers via OTP. // Payload: *SignInSuccessPayload EventEmailOTPSignInSuccess = "emailotp:sign_in:success" // EventEmailOTPPasswordReset is emitted when a user resets their password using an OTP. // Payload: *PasswordResetPayload EventEmailOTPPasswordReset = "emailotp:password_reset:success" // EventEmailOTPChangeEmail is emitted when a user successfully updates their verified email address via OTP. // Payload: *EmailChangedPayload EventEmailOTPChangeEmail = "emailotp:change_email:success" // EventEmailOTPFailed is emitted when an incorrect OTP is submitted or verification fails. // Payload: *OTPFailedPayload EventEmailOTPFailed = "emailotp:verify:failed" // EventEmailOTPAttemptsExceeded is emitted when all allowed attempts on an OTP have been exhausted. // Payload: *OTPFailedPayload EventEmailOTPAttemptsExceeded = "emailotp:attempts:exceeded" // EventEmailOTPExpired is emitted when verification is attempted on an expired OTP. // Payload: *OTPFailedPayload EventEmailOTPExpired = "emailotp:expired" )
Event bus topic string constants emitted during Email OTP lifecycle operations.
const ( ExtraKeyOTPType = "email_otp_type" ExtraKeyOTPEmail = "email_otp_email" ExtraKeyOTPNewEmail = "email_otp_new_email" ExtraKeyDeviceID = "device_id" ExtraKeyIPAddress = "ip_address" ExtraKeyUserAgent = "user_agent" ExtraKeySessionToken = "session_token" ExtraKeyAutoSignIn = "auto_sign_in" )
Standard Extra metadata keys that can be set or consumed in Email OTP parameters and Event payloads.
const ( ContextKeyEmailOTPPendingPrefix = "email_otp_pending_" ContextKeyEmailOTPVerifiedPrefix = "email_otp_verified_" )
Context keys stored in plugin.Context for Email OTP state management.
const PluginID = "email-otp"
PluginID is the unique string identifier for the Email OTP plugin ("email-otp").
Variables ¶
var ( // ErrInvalidEmail is returned when an email format validation fails or is empty. ErrInvalidEmail = errors.New("emailotp: invalid email address") // ErrInvalidOTPType is returned when an unsupported OTP operation type is supplied. ErrInvalidOTPType = errors.New("emailotp: invalid OTP type") // ErrInvalidOTP is returned when the provided OTP code is incorrect or has already been consumed. ErrInvalidOTP = errors.New("emailotp: invalid OTP") // ErrOTPExpired is returned when attempting to verify an OTP that has passed its expiration time. ErrOTPExpired = errors.New("emailotp: OTP expired") // ErrTooManyAttempts is returned when the maximum number of failed attempts on an active OTP has been exceeded. ErrTooManyAttempts = errors.New("emailotp: maximum attempt limit reached") // ErrUserNotFound is returned when no user matches the queried identifier or email address. ErrUserNotFound = errors.New("emailotp: user not found") // ErrEmailAlreadyInUse is returned when attempting to assign an email that already belongs to another user. ErrEmailAlreadyInUse = errors.New("emailotp: email already in use") // ErrChangeEmailDisabled is returned when attempting an email change operation while the feature is disabled. ErrChangeEmailDisabled = errors.New("emailotp: change email with OTP is disabled") // ErrSameEmail is returned when attempting to change an email to the exact same current address. ErrSameEmail = errors.New("emailotp: new email must be different from current email") // ErrCurrentEmailNotVerified is returned when verifying the current email OTP is required before requesting change. ErrCurrentEmailNotVerified = errors.New("emailotp: OTP is required to verify current email") // ErrSendCallbackMissing is returned when attempting to dispatch an OTP without a registered SendVerificationOTP callback. ErrSendCallbackMissing = errors.New("emailotp: send verification OTP callback is not configured") // ErrCannotRetrieveHashed is returned when trying to read plain text OTP while hashed storage mode is active. ErrCannotRetrieveHashed = errors.New("emailotp: OTP is hashed, cannot return plain text OTP") // ErrPasswordTooShort is returned when a reset password does not satisfy the minimum length requirement. ErrPasswordTooShort = errors.New("emailotp: password is too short") // ErrPasswordTooLong is returned when a reset password exceeds the maximum allowed length. ErrPasswordTooLong = errors.New("emailotp: password is too long") // ErrAccountNotFound is returned when credentials for the requested provider are missing in storage. ErrAccountNotFound = errors.New("emailotp: credential account not found") // ErrInvalidParameter is returned when a required argument or parameter is missing or malformed. ErrInvalidParameter = errors.New("emailotp: required parameter is missing or invalid") )
Sentinel errors for the Email OTP plugin.
Functions ¶
func DefaultNumericOTPGenerator ¶
DefaultNumericOTPGenerator generates a cryptographically secure random numeric string of length N (default: 6).
func SplitAtLastColon ¶
SplitAtLastColon splits a stored value string into the stored OTP payload and the attempt counter ("<stored_otp>:<attempts>").
func ToChangeEmailOTPIdentifier ¶
ToChangeEmailOTPIdentifier formats the composite storage identifier for email change. Format: "change-email-otp-<normalized_current_email>-<normalized_new_email>"
func ToOTPIdentifier ¶
ToOTPIdentifier formats the standard storage identifier for an OTP given its type and email. Format: "<type>-otp-<normalized_email>" (e.g. "email-verification-otp-user@example.com")
Types ¶
type AESGCMCipher ¶
type AESGCMCipher struct {
// contains filtered or unexported fields
}
AESGCMCipher implements Cipher using AES-256-GCM with key derivation via SHA-256.
func NewAESGCMCipher ¶
func NewAESGCMCipher(secretKey string) (*AESGCMCipher, error)
NewAESGCMCipher instantiates a new AES-256-GCM cipher using the provided secret key.
type ChangeEmailConfig ¶
type ChangeEmailConfig struct {
// Enabled toggles whether users are permitted to change their email via OTP.
Enabled bool `json:"enabled"`
// VerifyCurrentEmail enforces sending and verifying an OTP to the current email address before sending one to the new address.
VerifyCurrentEmail bool `json:"verify_current_email"`
}
ChangeEmailConfig configures the email change verification flow.
type ChangeEmailParams ¶
type ChangeEmailParams struct {
// UserID is the ID of the authenticated user.
UserID string `json:"user_id"`
// NewEmail is the new verified email address.
NewEmail string `json:"new_email"`
// OTP is the confirmation code delivered to the new email.
OTP string `json:"otp"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
ChangeEmailParams defines parameters to confirm an email change using the OTP sent to the new email.
type ChangeEmailResult ¶
type ChangeEmailResult struct {
// Success indicates if the email was successfully changed.
Success bool `json:"success"`
// User is the updated user entity with the new email address.
User *entity.User `json:"user"`
}
ChangeEmailResult reports the outcome of the email change confirmation.
type CheckVerificationOTPParams ¶
type CheckVerificationOTPParams struct {
// Email is the target email address.
Email string `json:"email"`
// Type specifies the OTP workflow type.
Type OTPType `json:"type"`
// OTP is the code to check.
OTP string `json:"otp"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
CheckVerificationOTPParams defines parameters for validating an OTP without consuming it.
type CheckVerificationOTPResult ¶
type CheckVerificationOTPResult struct {
// Success indicates whether the OTP is currently valid.
Success bool `json:"success"`
}
CheckVerificationOTPResult reports whether the tested OTP code is valid.
type Cipher ¶
type Cipher interface {
// Encrypt encrypts a plain text OTP into a secure string representation.
Encrypt(otp string) (string, error)
// Decrypt decrypts an encrypted string back into the original plain text OTP.
Decrypt(encrypted string) (string, error)
}
Cipher defines the contract for symmetric reversible encryption of OTP codes.
type Config ¶
type Config struct {
// SendVerificationOTP is the required email delivery callback.
SendVerificationOTP SendVerificationOTPFunc
// OTPLength is the number of digits in generated numeric OTPs (default: 6).
OTPLength int
// ExpiresIn is the duration after which an unverified OTP expires (default: 5 minutes).
ExpiresIn time.Duration
// AllowedAttempts is the maximum number of failed verification tries permitted before invalidating the code (default: 3).
AllowedAttempts int
// StoreOTPMode defines how the OTP is persisted ("plain", "hashed", "encrypted", default: "plain").
StoreOTPMode StoreOTPMode
// SecretKey is the symmetric key used when StoreOTPMode is "encrypted".
SecretKey string
// CustomHasher is an optional custom Hasher implementation for "hashed" mode.
CustomHasher Hasher
// CustomCipher is an optional custom Cipher implementation for "encrypted" mode.
CustomCipher Cipher
// ResendStrategy specifies behavior on resend requests ("rotate" or "reuse", default: "rotate").
ResendStrategy ResendStrategy
// SendVerificationOnSignUp automatically sends an email verification OTP when a user registers.
SendVerificationOnSignUp bool
// DisableSignUp prevents creating a new user if an account does not exist during SignInEmailOTP.
DisableSignUp bool
// OverrideDefaultEmailVerification overrides default email verification behaviors.
OverrideDefaultEmailVerification bool
// AutoSignInAfterVerification automatically generates an authenticated session upon successful email verification (default: true).
AutoSignInAfterVerification bool
// RevokeSessionsOnPasswordReset invalidates all active user sessions after a successful password reset (default: true).
RevokeSessionsOnPasswordReset bool
// MinPasswordLength is the minimum password length enforced during password resets (default: 8).
MinPasswordLength int
// MaxPasswordLength is the maximum password length enforced during password resets (default: 128).
MaxPasswordLength int
// ChangeEmail holds email change flow configuration.
ChangeEmail ChangeEmailConfig
// RateLimit holds request throttling configuration.
RateLimit RateLimitConfig
// GenerateOTP is an optional custom OTP code generator.
GenerateOTP GenerateOTPFunc
}
Config structures all configuration options for the Email OTP plugin.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns the recommended default configuration for Email OTP authentication.
type CreateVerificationOTPParams ¶
type CreateVerificationOTPParams struct {
// Email is the target email address.
Email string `json:"email"`
// Type specifies the OTP workflow type.
Type OTPType `json:"type"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
CreateVerificationOTPParams defines parameters for server-side OTP generation without email dispatch.
type DefaultSHA256Hasher ¶
type DefaultSHA256Hasher struct{}
DefaultSHA256Hasher implements Hasher using SHA-256 encoded in Base64 Raw URL.
func (DefaultSHA256Hasher) Hash ¶
func (h DefaultSHA256Hasher) Hash(otp string) (string, error)
Hash computes the SHA-256 hash of the plain OTP code.
func (DefaultSHA256Hasher) Verify ¶
func (h DefaultSHA256Hasher) Verify(otp, hashed string) bool
Verify compares the plain text OTP against the stored hash using constant-time evaluation.
type EmailChangedPayload ¶
type EmailChangedPayload struct {
UserID string `json:"user_id"`
OldEmail string `json:"old_email"`
NewEmail string `json:"new_email"`
Timestamp time.Time `json:"timestamp"`
Extra map[string]any `json:"extra,omitempty"`
}
EmailChangedPayload reports details when an email address is changed and confirmed via OTP.
type GenerateOTPFunc ¶
GenerateOTPFunc allows overriding the default random numeric code generation routine.
type GetVerificationOTPParams ¶
type GetVerificationOTPParams struct {
// Email is the target email address.
Email string `json:"email"`
// Type specifies the OTP workflow type.
Type OTPType `json:"type"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
GetVerificationOTPParams defines parameters for server-side inspection of an active OTP code.
type GetVerificationOTPResult ¶
type GetVerificationOTPResult struct {
// OTP is the retrieved plain text code.
OTP string `json:"otp"`
}
GetVerificationOTPResult contains the plain text OTP code retrieved from storage.
type Hasher ¶
type Hasher interface {
// Hash computes the one-way cryptographic hash of an OTP code.
Hash(otp string) (string, error)
// Verify compares a plain text OTP against the stored hash in constant time.
Verify(otp, hashed string) bool
}
Hasher defines the contract for hashing and verifying OTP codes in constant time.
type OTPFailedPayload ¶
type OTPFailedPayload struct {
Email string `json:"email"`
Type OTPType `json:"type"`
AttemptsUsed int `json:"attempts_used"`
AttemptsRemaining int `json:"attempts_remaining"`
Reason string `json:"reason"`
Extra map[string]any `json:"extra,omitempty"`
}
OTPFailedPayload reports diagnostic information for failed or expired OTP verification attempts.
type OTPSentPayload ¶
type OTPSentPayload struct {
Email string `json:"email"`
Type OTPType `json:"type"`
ExpiresAt time.Time `json:"expires_at"`
Extra map[string]any `json:"extra,omitempty"`
}
OTPSentPayload contains confirmation details after an OTP has been dispatched.
type OTPType ¶
type OTPType string
OTPType defines the valid types of OTP operations supported by the plugin.
const ( // OTPTypeEmailVerification represents email address ownership verification. OTPTypeEmailVerification OTPType = "email-verification" // OTPTypeSignIn represents passwordless sign-in or auto-registration via OTP. OTPTypeSignIn OTPType = "sign-in" // OTPTypeForgetPassword represents password recovery and reset. OTPTypeForgetPassword OTPType = "forget-password" // OTPTypeChangeEmail represents changing a user's verified email address. OTPTypeChangeEmail OTPType = "change-email" )
type OTPVerifiedPayload ¶
type OTPVerifiedPayload struct {
UserID string `json:"user_id"`
Email string `json:"email"`
Type OTPType `json:"type"`
Timestamp time.Time `json:"timestamp"`
Extra map[string]any `json:"extra,omitempty"`
}
OTPVerifiedPayload reports details of a successful OTP code verification.
type Option ¶
type Option func(*Config)
Option represents a functional option to configure the Email OTP plugin.
func WithAllowedAttempts ¶
WithAllowedAttempts sets the maximum number of incorrect attempts before permanently consuming and invalidating the OTP.
func WithAutoSignInAfterVerification ¶
WithAutoSignInAfterVerification configures whether to issue a session immediately upon successful email verification.
func WithChangeEmail ¶
WithChangeEmail configures whether email changes via OTP are enabled and whether the current email must be verified first.
func WithCustomCipher ¶
WithCustomCipher configures a custom Cipher for symmetric encryption of OTPs.
func WithCustomHasher ¶
WithCustomHasher configures a custom Hasher for hashing OTPs.
func WithDisableSignUp ¶
WithDisableSignUp disables automatic user provisioning when verifying a sign-in OTP for an unknown email.
func WithExpiresIn ¶
WithExpiresIn sets the duration for which an OTP remains valid.
func WithGenerateOTP ¶
func WithGenerateOTP(fn GenerateOTPFunc) Option
WithGenerateOTP provides a custom code generation callback.
func WithOTPLength ¶
WithOTPLength sets the number of digits in generated numeric OTPs.
func WithOverrideDefaultEmailVerification ¶
WithOverrideDefaultEmailVerification overrides the framework default verification flow.
func WithPasswordLength ¶
WithPasswordLength configures the minimum and maximum password length permitted during password resets.
func WithRateLimit ¶
WithRateLimit configures rate limiting parameters for OTP dispatch requests.
func WithResendStrategy ¶
func WithResendStrategy(strategy ResendStrategy) Option
WithResendStrategy configures whether to rotate codes or reuse unexpired active codes on resend.
func WithRevokeSessionsOnPasswordReset ¶
WithRevokeSessionsOnPasswordReset configures whether all active sessions are revoked when resetting passwords via OTP.
func WithSendVerificationOTP ¶
func WithSendVerificationOTP(fn SendVerificationOTPFunc) Option
WithSendVerificationOTP configures the email delivery callback function.
func WithSendVerificationOnSignUp ¶
WithSendVerificationOnSignUp configures whether to automatically dispatch a verification OTP when a user signs up.
func WithStoreOTP ¶
func WithStoreOTP(mode StoreOTPMode, secretKey ...string) Option
WithStoreOTP configures the storage strategy for OTP codes ("plain", "hashed", or "encrypted").
type PasswordResetPayload ¶
type PasswordResetPayload struct {
UserID string `json:"user_id"`
Email string `json:"email"`
Timestamp time.Time `json:"timestamp"`
Extra map[string]any `json:"extra,omitempty"`
}
PasswordResetPayload reports details when a password is reset via OTP.
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin implements the Email OTP authentication plugin.
func New ¶
func New(repo Repository, opts ...Option) *Plugin
New instantiates a new Email OTP plugin configured with the given repository and options.
func (*Plugin) ChangeEmailEmailOTP ¶
func (p *Plugin) ChangeEmailEmailOTP(ctx context.Context, params *ChangeEmailParams) (*ChangeEmailResult, error)
ChangeEmailEmailOTP confirms changing the user's email address using the OTP delivered to the new email.
func (*Plugin) CheckVerificationOTP ¶
func (p *Plugin) CheckVerificationOTP(ctx context.Context, params *CheckVerificationOTPParams) (*CheckVerificationOTPResult, error)
CheckVerificationOTP verifies whether a submitted OTP is valid without consuming it or changing attempt counts.
func (*Plugin) CreateVerificationOTP ¶
func (p *Plugin) CreateVerificationOTP(ctx context.Context, params *CreateVerificationOTPParams) (string, error)
CreateVerificationOTP generates and stores an OTP code without triggering the email delivery callback (server API).
func (*Plugin) GetVerificationOTP ¶
func (p *Plugin) GetVerificationOTP(ctx context.Context, params *GetVerificationOTPParams) (*GetVerificationOTPResult, error)
GetVerificationOTP retrieves the plain text OTP code currently stored for an identifier (server API).
func (*Plugin) Repository ¶
func (p *Plugin) Repository() Repository
Repository returns the underlying storage repository instance.
func (*Plugin) RequestEmailChangeEmailOTP ¶
func (p *Plugin) RequestEmailChangeEmailOTP(ctx context.Context, params *RequestEmailChangeParams) (*RequestEmailChangeResult, error)
RequestEmailChangeEmailOTP initiates the email change procedure by dispatching an OTP to the new email address.
func (*Plugin) RequestPasswordResetEmailOTP ¶
func (p *Plugin) RequestPasswordResetEmailOTP(ctx context.Context, params *RequestPasswordResetParams) (*RequestPasswordResetResult, error)
RequestPasswordResetEmailOTP verifies account existence and dispatches a password recovery OTP.
func (*Plugin) ResetPasswordEmailOTP ¶
func (p *Plugin) ResetPasswordEmailOTP(ctx context.Context, params *ResetPasswordParams) (*ResetPasswordResult, error)
ResetPasswordEmailOTP validates a password reset OTP and updates the user's password hash.
func (*Plugin) SendVerificationOTP ¶
func (p *Plugin) SendVerificationOTP(ctx context.Context, params *SendVerificationOTPParams) (*SendVerificationOTPResult, error)
SendVerificationOTP generates and dispatches a one-time password code to the recipient's email.
func (*Plugin) SignInEmailOTP ¶
func (p *Plugin) SignInEmailOTP(ctx context.Context, params *SignInEmailOTPParams) (*SignInEmailOTPResult, error)
SignInEmailOTP authenticates an existing user or automatically provisions a new user via OTP.
func (*Plugin) VerifyEmailOTP ¶
func (p *Plugin) VerifyEmailOTP(ctx context.Context, params *VerifyEmailOTPParams) (*VerifyEmailOTPResult, error)
VerifyEmailOTP validates an OTP submitted for email verification and marks the user's email as verified.
type RateLimitConfig ¶
type RateLimitConfig struct {
// Window specifies the duration of the rate-limiting window.
Window time.Duration `json:"window"`
// Max specifies the maximum allowed requests within the configured window.
Max int `json:"max"`
}
RateLimitConfig configures sliding rate limits to protect OTP dispatching from spam abuse.
type Repository ¶
type Repository interface {
// FindVerificationValue retrieves an active verification record matching the given identifier.
//
// Arguments:
// - ctx: Request cancellation context.
// - identifier: The composite OTP key (e.g. "sign-in-otp-user@example.com").
//
// Returns:
// - *VerificationRecord: The matching record if found.
// - error: Nil on success, or database error.
//
// Example SQL:
// SELECT id, identifier, value, expires_at, created_at, updated_at FROM verification_tokens WHERE identifier = $1 LIMIT 1;
FindVerificationValue(ctx context.Context, identifier string) (*VerificationRecord, error)
// CreateVerificationValue creates or replaces a verification record in storage.
//
// Arguments:
// - ctx: Request cancellation context.
// - record: The VerificationRecord entity to persist.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// INSERT INTO verification_tokens (id, identifier, value, expires_at, created_at, updated_at)
// VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (identifier) DO UPDATE SET value = $3, expires_at = $4, updated_at = $6;
CreateVerificationValue(ctx context.Context, record *VerificationRecord) error
// UpdateVerificationValue updates the value and expiry of an existing verification record.
//
// Arguments:
// - ctx: Request cancellation context.
// - identifier: The composite OTP key.
// - value: The updated value payload (e.g. "<stored_otp>:<attempts>").
// - expiresAt: The updated expiration timestamp.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// UPDATE verification_tokens SET value = $1, expires_at = $2, updated_at = $3 WHERE identifier = $4;
UpdateVerificationValue(ctx context.Context, identifier, value string, expiresAt time.Time) error
// DeleteVerificationValue removes a verification record from storage by identifier.
//
// Arguments:
// - ctx: Request cancellation context.
// - identifier: The composite OTP key.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// DELETE FROM verification_tokens WHERE identifier = $1;
DeleteVerificationValue(ctx context.Context, identifier string) error
// ConsumeVerificationValue atomically retrieves and deletes a verification record in a single operation.
// This ensures strictly single-use anti-replay protection under high concurrency.
//
// Arguments:
// - ctx: Request cancellation context.
// - identifier: The composite OTP key.
//
// Returns:
// - *VerificationRecord: The consumed record if it existed and was not expired.
// - error: Nil on success, or database error if not found.
//
// Example SQL:
// DELETE FROM verification_tokens WHERE identifier = $1 AND expires_at > $2
// RETURNING id, identifier, value, expires_at, created_at, updated_at;
ConsumeVerificationValue(ctx context.Context, identifier string) (*VerificationRecord, error)
// GetUserByEmail retrieves a user entity matching the provided email address.
//
// Arguments:
// - ctx: Request cancellation context.
// - email: The normalized email address to query.
//
// Returns:
// - *entity.User: The matching user entity if found.
// - error: ErrUserNotFound if no record matches, or database error.
//
// Example SQL:
// SELECT id, name, email, email_verified, role, banned, created_at, updated_at FROM users WHERE LOWER(email) = LOWER($1) LIMIT 1;
GetUserByEmail(ctx context.Context, email string) (*entity.User, error)
// GetUserByID retrieves a user entity matching the provided unique identifier.
//
// Arguments:
// - ctx: Request cancellation context.
// - id: The user's primary key ID.
//
// Returns:
// - *entity.User: The matching user entity if found.
// - error: ErrUserNotFound if no record matches, or database error.
//
// Example SQL:
// SELECT id, name, email, email_verified, role, banned, created_at, updated_at FROM users WHERE id = $1 LIMIT 1;
GetUserByID(ctx context.Context, id string) (*entity.User, error)
// CreateUser persists a newly registered user in storage.
//
// Arguments:
// - ctx: Request cancellation context.
// - params: Parameters containing name, email, and metadata.
//
// Returns:
// - *entity.User: The created user entity.
// - error: Nil on success, or database error.
//
// Example SQL:
// INSERT INTO users (id, name, email, email_verified, role, created_at, updated_at)
// VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id, name, email, email_verified, created_at, updated_at;
CreateUser(ctx context.Context, params *dto.CreateUserParams) (*entity.User, error)
// UpdateUser updates modified fields of an existing user profile (e.g. Email, EmailVerified).
//
// Arguments:
// - ctx: Request cancellation context.
// - user: The modified user entity.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// UPDATE users SET email = $1, email_verified = $2, updated_at = $3 WHERE id = $4;
UpdateUser(ctx context.Context, user *entity.User) error
// GetAccountByUserIDAndProvider retrieves an account matching a given user and authentication provider.
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: The target user's ID.
// - providerID: The provider identifier (e.g. "credential").
//
// Returns:
// - *entity.Account: The matching account if found.
// - error: ErrAccountNotFound if missing, or database error.
//
// Example SQL:
// SELECT id, user_id, provider, created_at, updated_at FROM accounts WHERE user_id = $1 AND provider = $2 LIMIT 1;
GetAccountByUserIDAndProvider(ctx context.Context, userID, providerID string) (*entity.Account, error)
// CreateAccount associates a new provider authentication account with a user.
//
// Arguments:
// - ctx: Request cancellation context.
// - account: The Account entity to persist.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// INSERT INTO accounts (id, user_id, provider, created_at, updated_at) VALUES ($1, $2, $3, $4, $5);
CreateAccount(ctx context.Context, account *entity.Account) error
// UpdateAccountPassword updates the password hash on a user's credential account.
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: The target user's ID.
// - passwordHash: The newly calculated password hash string.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// UPDATE accounts SET password = $1, updated_at = $2 WHERE user_id = $3 AND provider = 'credential';
UpdateAccountPassword(ctx context.Context, userID, passwordHash string) error
// DeleteCredentialAccount removes the credential account for a user adopted via passwordless OTP.
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: The target user's ID.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// DELETE FROM accounts WHERE user_id = $1 AND provider = 'credential';
DeleteCredentialAccount(ctx context.Context, userID string) error
// CreateSession persists a new active user session in storage.
//
// Arguments:
// - ctx: Request cancellation context.
// - params: Parameters containing userID, token, expiration, and metadata.
//
// Returns:
// - *entity.Session: The created session entity.
// - error: Nil on success, or database error.
//
// Example SQL:
// INSERT INTO sessions (id, user_id, token, expires_at, ip_address, user_agent, created_at, updated_at)
// VALUES ($1, $2, $3, $4, $5, $6, $7, $8);
CreateSession(ctx context.Context, params *dto.CreateSessionParams) (*entity.Session, error)
// DeleteSessionsByUserID invalidates all active sessions for a user (used upon password reset).
//
// Arguments:
// - ctx: Request cancellation context.
// - userID: The target user's ID.
//
// Returns:
// - error: Nil on success, or database error.
//
// Example SQL:
// DELETE FROM sessions WHERE user_id = $1;
DeleteSessionsByUserID(ctx context.Context, userID string) error
}
Repository defines the persistent storage contract required by the Email OTP plugin. Implement this interface on your custom database adapter (e.g. PostgreSQL, MySQL, SQLite, MongoDB, GORM).
type RequestEmailChangeParams ¶
type RequestEmailChangeParams struct {
// UserID is the ID of the authenticated user requesting the change.
UserID string `json:"user_id"`
// NewEmail is the new email address to bind to the account.
NewEmail string `json:"new_email"`
// OTP is the verification code for the current email if VerifyCurrentEmail is enabled.
OTP string `json:"otp,omitempty"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
RequestEmailChangeParams defines parameters to initiate an email change flow.
type RequestEmailChangeResult ¶
type RequestEmailChangeResult struct {
// Success indicates if the OTP was successfully dispatched to the new email address.
Success bool `json:"success"`
}
RequestEmailChangeResult reports whether the email change OTP was dispatched to the new email.
type RequestPasswordResetParams ¶
type RequestPasswordResetParams struct {
// Email is the account email requesting a password reset.
Email string `json:"email"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
RequestPasswordResetParams defines parameters to request a password reset OTP.
type RequestPasswordResetResult ¶
type RequestPasswordResetResult struct {
// Success indicates if the reset OTP was successfully dispatched.
Success bool `json:"success"`
}
RequestPasswordResetResult reports the result of the password reset dispatch request.
type ResendStrategy ¶
type ResendStrategy string
ResendStrategy defines the behavior when requesting a new OTP while an active one exists.
const ( // ResendStrategyRotate always invalidates the previous OTP and generates a fresh code. ResendStrategyRotate ResendStrategy = "rotate" // ResendStrategyReuse resends the existing active OTP and extends its expiration (plain/encrypted only). ResendStrategyReuse ResendStrategy = "reuse" )
type ResetPasswordParams ¶
type ResetPasswordParams struct {
// Email is the account email address.
Email string `json:"email"`
// OTP is the reset code submitted by the user.
OTP string `json:"otp"`
// NewPassword is the new password string to set.
NewPassword string `json:"new_password"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
ResetPasswordParams defines parameters for setting a new password using a verified OTP.
func (*ResetPasswordParams) Set ¶
func (p *ResetPasswordParams) Set(key string, val any)
type ResetPasswordResult ¶
type ResetPasswordResult struct {
// Success indicates if the password was successfully reset.
Success bool `json:"success"`
}
ResetPasswordResult reports whether the password was successfully updated.
type SendEmailData ¶
type SendEmailData struct {
// Email is the destination recipient email address.
Email string `json:"email"`
// OTP is the raw numeric OTP verification code to deliver.
OTP string `json:"otp"`
// Type indicates the specific operation requiring verification.
Type OTPType `json:"type"`
}
SendEmailData contains the parameters delivered to the transactional email delivery callback.
type SendOTPPendingPayload ¶
type SendOTPPendingPayload struct {
Email string `json:"email"`
Type OTPType `json:"type"`
ExpiresAt time.Time `json:"expires_at"`
Extra map[string]any `json:"extra,omitempty"`
}
SendOTPPendingPayload contains recipient and expiration details before dispatching an OTP.
type SendVerificationOTPFunc ¶
type SendVerificationOTPFunc func(ctx context.Context, data SendEmailData) error
SendVerificationOTPFunc defines the callback function invoked when dispatching an OTP to a recipient email.
type SendVerificationOTPParams ¶
type SendVerificationOTPParams struct {
// Email is the destination recipient email address (required).
Email string `json:"email"`
// Type specifies the OTP workflow type ("email-verification", "sign-in", "forget-password", "change-email").
Type OTPType `json:"type"`
// Extra holds dynamic metadata passed through event interceptors (optional).
Extra map[string]any `json:"extra,omitempty"`
}
SendVerificationOTPParams defines parameters required to dispatch an OTP to a user's email.
func (*SendVerificationOTPParams) Get ¶
func (p *SendVerificationOTPParams) Get(key string) (any, bool)
func (*SendVerificationOTPParams) Set ¶
func (p *SendVerificationOTPParams) Set(key string, val any)
type SendVerificationOTPResult ¶
type SendVerificationOTPResult struct {
// Success indicates if the OTP was successfully generated and dispatched.
Success bool `json:"success"`
// ExpiresAt indicates when the dispatched OTP code will expire.
ExpiresAt time.Time `json:"expires_at"`
}
SendVerificationOTPResult contains the delivery status and expiry of the dispatched OTP.
type SignInEmailOTPParams ¶
type SignInEmailOTPParams struct {
// Email is the user's email address.
Email string `json:"email"`
// OTP is the one-time code submitted by the user.
OTP string `json:"otp"`
// Name is the optional display name assigned if a new user is created.
Name string `json:"name,omitempty"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
SignInEmailOTPParams defines parameters for passwordless sign-in and auto-registration via OTP.
func (*SignInEmailOTPParams) Set ¶
func (p *SignInEmailOTPParams) Set(key string, val any)
type SignInEmailOTPResult ¶
type SignInEmailOTPResult struct {
// User is the authenticated or newly provisioned user entity.
User *entity.User `json:"user"`
// SessionToken is the raw session token.
SessionToken string `json:"session_token"`
// Session is the persisted active session entity.
Session *entity.Session `json:"session"`
// IsNewUser indicates if this sign-in operation provisioned a new user account.
IsNewUser bool `json:"is_new_user"`
}
SignInEmailOTPResult contains the authenticated user profile, session, and registration indicator.
type SignInSuccessPayload ¶
type SignInSuccessPayload struct {
User *entity.User `json:"user"`
Session *entity.Session `json:"session"`
IsNewUser bool `json:"is_new_user"`
Extra map[string]any `json:"extra,omitempty"`
}
SignInSuccessPayload reports authentication or auto-registration details upon OTP sign-in.
type StoreOTPMode ¶
type StoreOTPMode string
StoreOTPMode defines how the OTP code is persisted in storage.
const ( // StoreOTPPlain stores the OTP code in plain text. StoreOTPPlain StoreOTPMode = "plain" // StoreOTPHashed stores the OTP code using constant-time SHA-256 hash. StoreOTPHashed StoreOTPMode = "hashed" // StoreOTPEncrypted stores the OTP code using AES-256-GCM symmetric encryption. StoreOTPEncrypted StoreOTPMode = "encrypted" )
type VerificationRecord ¶
type VerificationRecord struct {
// ID is the unique database record identifier.
ID string `json:"id"`
// Identifier is the composite lookup key (e.g. "email-verification-otp-user@example.com").
Identifier string `json:"identifier"`
// Value stores the code and attempt counter formatted as "<stored_otp>:<attempts>".
Value string `json:"value"`
// ExpiresAt specifies the exact timestamp after which this verification value is invalid.
ExpiresAt time.Time `json:"expires_at"`
// CreatedAt records when the verification record was initialized.
CreatedAt time.Time `json:"created_at"`
// UpdatedAt records when the verification record was last modified.
UpdatedAt time.Time `json:"updated_at"`
}
VerificationRecord represents the persistent storage entity for an OTP verification value.
type VerifyBeforePayload ¶
type VerifyBeforePayload struct {
Email string `json:"email"`
Type OTPType `json:"type"`
Extra map[string]any `json:"extra,omitempty"`
}
VerifyBeforePayload contains parameters before executing OTP verification.
type VerifyEmailOTPParams ¶
type VerifyEmailOTPParams struct {
// Email is the address being verified.
Email string `json:"email"`
// OTP is the verification code submitted by the user.
OTP string `json:"otp"`
// Extra holds optional dynamic metadata.
Extra map[string]any `json:"extra,omitempty"`
}
VerifyEmailOTPParams defines parameters to verify email ownership via OTP.
func (*VerifyEmailOTPParams) Set ¶
func (p *VerifyEmailOTPParams) Set(key string, val any)
type VerifyEmailOTPResult ¶
type VerifyEmailOTPResult struct {
// Success indicates successful email verification.
Success bool `json:"success"`
// User is the updated user entity with EmailVerified set to true.
User *entity.User `json:"user"`
// SessionToken is the raw token string if AutoSignInAfterVerification is enabled.
SessionToken string `json:"session_token,omitempty"`
// Session is the active session entity if AutoSignInAfterVerification is enabled.
Session *entity.Session `json:"session,omitempty"`
}
VerifyEmailOTPResult contains the updated user profile and optional auto-created session.