Documentation
¶
Index ¶
- Constants
- Variables
- func DefaultTokenGenerator(length int) (string, error)
- func ToMagicLinkIdentifier(email string) string
- func ToMagicLinkTokenLookupKey(token string) string
- type AESGCMCipher
- type Cipher
- type Config
- type DefaultSHA256Hasher
- type Hasher
- type MagicLinkFailedPayload
- type MagicLinkSentPayload
- type MagicLinkVerifiedPayload
- type Option
- func WithCustomCipher(ciph Cipher) Option
- func WithCustomHasher(h Hasher) Option
- func WithDefaultCallbackURL(url string) Option
- func WithDisableSignUp(disable bool) Option
- func WithExpiresIn(d time.Duration) Option
- func WithGenerateToken(fn TokenGeneratorFunc) Option
- func WithRateLimit(window time.Duration, max int) Option
- func WithSecretKey(key string) Option
- func WithSendMagicLink(fn SendMagicLinkFunc) Option
- func WithStoreTokenMode(mode StoreTokenMode) Option
- type Plugin
- func (p *Plugin) ID() string
- func (p *Plugin) Init(ctx *plugin.Context) error
- func (p *Plugin) ServeSignIn(w http.ResponseWriter, r *http.Request)
- func (p *Plugin) ServeVerify(w http.ResponseWriter, r *http.Request)
- func (p *Plugin) SignInMagicLink(ctx context.Context, params SignInMagicLinkParams) (*SignInMagicLinkResult, error)
- func (p *Plugin) VerifyMagicLink(ctx context.Context, params VerifyMagicLinkParams) (*VerifyMagicLinkResult, error)
- type RateLimitConfig
- type Repository
- type SendMagicLinkData
- type SendMagicLinkFunc
- type SendMagicLinkPendingPayload
- type SignInMagicLinkParams
- type SignInMagicLinkResult
- type SignInSuccessPayload
- type StoreTokenMode
- type TokenGeneratorFunc
- type TokenPayload
- type VerificationRecord
- type VerifyBeforePayload
- type VerifyMagicLinkParams
- type VerifyMagicLinkResult
Constants ¶
const ( // EventMagicLinkSendBefore is emitted right before dispatching a magic link email. // Payload: *SendMagicLinkPendingPayload EventMagicLinkSendBefore = "magiclink:send:before" // EventMagicLinkSent is emitted immediately after a magic link email has been dispatched. // Payload: *MagicLinkSentPayload EventMagicLinkSent = "magiclink:send:after" // EventMagicLinkVerifyBefore is emitted right before verifying a submitted magic link token. // Payload: *VerifyBeforePayload EventMagicLinkVerifyBefore = "magiclink:verify:before" // EventMagicLinkVerified is emitted after a magic link token has been successfully verified. // Payload: *MagicLinkVerifiedPayload EventMagicLinkVerified = "magiclink:verify:after" // EventMagicLinkSignInSuccess is emitted when a user successfully authenticates or registers via magic link. // Payload: *SignInSuccessPayload EventMagicLinkSignInSuccess = "magiclink:sign_in:success" // EventMagicLinkFailed is emitted when an invalid magic link token is submitted or verification fails. // Payload: *MagicLinkFailedPayload EventMagicLinkFailed = "magiclink:verify:failed" // EventMagicLinkExpired is emitted when verification is attempted on an expired magic link token. // Payload: *MagicLinkFailedPayload EventMagicLinkExpired = "magiclink:expired" )
Event bus topic string constants emitted during Magic Link lifecycle operations.
const ( ExtraKeyEmail = "magic_link_email" ExtraKeyToken = "magic_link_token" ExtraKeyName = "magic_link_name" ExtraKeyCallbackURL = "magic_link_callback_url" ExtraKeyNewUserCallbackURL = "magic_link_new_user_callback_url" ExtraKeyErrorCallbackURL = "magic_link_error_callback_url" ExtraKeyIPAddress = "ip_address" ExtraKeyUserAgent = "user_agent" )
Standard Extra metadata keys that can be set or consumed in Magic Link parameters and Event payloads.
const ( ContextKeyMagicLinkPendingPrefix = "magic_link_pending_" ContextKeyMagicLinkVerifiedPrefix = "magic_link_verified_" )
Context keys stored in plugin.Context for Magic Link state management.
const PluginID = "magic-link"
PluginID is the unique string identifier for the Magic Link plugin ("magic-link").
Variables ¶
var ( // ErrInvalidEmail is returned when an email format validation fails or is empty. ErrInvalidEmail = errors.New("magiclink: invalid email address") // ErrInvalidToken is returned when the provided magic link token is incorrect or invalid. ErrInvalidToken = errors.New("magiclink: invalid verification token") // ErrTokenExpired is returned when attempting to verify a token that has passed its expiration time. ErrTokenExpired = errors.New("magiclink: verification token has expired") // ErrUserNotFound is returned when no user matches the queried email address. ErrUserNotFound = errors.New("magiclink: user not found") // ErrSignUpDisabled is returned when attempting to sign up a new user via magic link when DisableSignUp is true. ErrSignUpDisabled = errors.New("magiclink: user sign-up is disabled") // ErrSendCallbackMissing is returned when attempting to dispatch a magic link without a registered SendMagicLink callback. ErrSendCallbackMissing = errors.New("magiclink: SendMagicLink callback is not configured") // ErrCannotRetrieveHashed is returned when attempting to inspect a hashed token in plain text. ErrCannotRetrieveHashed = errors.New("magiclink: token is hashed, cannot return plain text token") // ErrInvalidParameter is returned when a required request parameter is missing or invalid. ErrInvalidParameter = errors.New("magiclink: required parameter is missing or invalid") )
Sentinel errors for the Magic Link plugin.
Functions ¶
func DefaultTokenGenerator ¶
DefaultTokenGenerator generates a cryptographically secure random 32-byte hex token string (64 characters).
func ToMagicLinkIdentifier ¶
ToMagicLinkIdentifier formats the standard storage identifier for a magic link token. Format: "magic-link-token-<normalized_email>" (e.g. "magic-link-token-user@example.com")
func ToMagicLinkTokenLookupKey ¶
ToMagicLinkTokenLookupKey formats a direct token identifier for reverse token lookup if needed. Format: "magic-link-rawtoken-<token>"
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 Cipher ¶
type Cipher interface {
// Encrypt encrypts a plain text token into a secure string representation.
Encrypt(token string) (string, error)
// Decrypt decrypts an encrypted string back into the original plain text token.
Decrypt(encrypted string) (string, error)
}
Cipher defines the contract for symmetric reversible encryption of tokens.
type Config ¶
type Config struct {
// SendMagicLink is the required callback function for dispatching email links.
SendMagicLink SendMagicLinkFunc
// ExpiresIn specifies the lifetime of generated magic link tokens (default: 5 minutes).
ExpiresIn time.Duration
// DisableSignUp prevents creation of new accounts when an email is not yet registered (default: false).
DisableSignUp bool
// DefaultCallbackURL specifies the fallback redirect URL after successful verification.
DefaultCallbackURL string
// GenerateToken allows overriding the default random token generator.
GenerateToken TokenGeneratorFunc
// StoreTokenMode defines token persistence security ("plain", "hashed", "encrypted", default: "plain").
StoreTokenMode StoreTokenMode
// SecretKey is the symmetric key used when StoreTokenMode is "encrypted".
SecretKey string
// CustomHasher allows overriding the default SHA-256 token hasher.
CustomHasher Hasher
// CustomCipher allows overriding the default AES-256-GCM cipher.
CustomCipher Cipher
// RateLimit holds rate limiting rules for magic link requests.
RateLimit RateLimitConfig
}
Config structures all configuration options for the Magic Link plugin.
func DefaultConfig ¶
func DefaultConfig() Config
DefaultConfig returns recommended production defaults for the Magic Link plugin.
type DefaultSHA256Hasher ¶
type DefaultSHA256Hasher struct{}
DefaultSHA256Hasher implements Hasher using SHA-256 encoded in Base64 Raw URL.
func (DefaultSHA256Hasher) Hash ¶
func (h DefaultSHA256Hasher) Hash(token string) (string, error)
Hash computes the SHA-256 hash of the plain token.
func (DefaultSHA256Hasher) Verify ¶
func (h DefaultSHA256Hasher) Verify(token, hashed string) bool
Verify compares the plain text token against the stored hash using constant-time evaluation.
type Hasher ¶
type Hasher interface {
// Hash computes the one-way cryptographic hash of a token.
Hash(token string) (string, error)
// Verify compares a plain text token against the stored hash in constant time.
Verify(token, hashed string) bool
}
Hasher defines the contract for hashing and verifying magic link tokens in constant time.
type MagicLinkFailedPayload ¶
type MagicLinkFailedPayload struct {
Email string `json:"email,omitempty"`
Token string `json:"token,omitempty"`
Reason string `json:"reason"`
Extra map[string]any `json:"extra,omitempty"`
}
MagicLinkFailedPayload contains failure context when magic link verification fails.
type MagicLinkSentPayload ¶
type MagicLinkSentPayload struct {
Email string `json:"email"`
URL string `json:"url"`
ExpiresAt time.Time `json:"expires_at"`
Extra map[string]any `json:"extra,omitempty"`
}
MagicLinkSentPayload contains confirmation details after dispatching a magic link email.
type MagicLinkVerifiedPayload ¶
type MagicLinkVerifiedPayload struct {
Email string `json:"email"`
User *entity.User `json:"user"`
IsNewUser bool `json:"is_new_user"`
}
MagicLinkVerifiedPayload contains verified user and token details.
type Option ¶
type Option func(*Config)
Option modifies a Magic Link plugin Config instance.
func WithCustomCipher ¶
WithCustomCipher sets a custom Cipher for encrypted token mode.
func WithCustomHasher ¶
WithCustomHasher sets a custom Hasher for hashed token mode.
func WithDefaultCallbackURL ¶
WithDefaultCallbackURL sets the default post-login redirect URL.
func WithDisableSignUp ¶
WithDisableSignUp toggles whether unregistered users can sign up via magic links.
func WithExpiresIn ¶
WithExpiresIn configures the magic link token expiration duration.
func WithGenerateToken ¶
func WithGenerateToken(fn TokenGeneratorFunc) Option
WithGenerateToken sets a custom token generation function.
func WithRateLimit ¶
WithRateLimit configures rate limiting parameters.
func WithSecretKey ¶
WithSecretKey configures the secret key for encrypted token mode.
func WithSendMagicLink ¶
func WithSendMagicLink(fn SendMagicLinkFunc) Option
WithSendMagicLink registers the required email delivery callback.
func WithStoreTokenMode ¶
func WithStoreTokenMode(mode StoreTokenMode) Option
WithStoreTokenMode configures how tokens are stored in the database ("plain", "hashed", "encrypted").
type Plugin ¶
type Plugin struct {
// contains filtered or unexported fields
}
Plugin implements the magic link authentication plugin for go-modular-auth.
func New ¶
func New(repo Repository, opts ...Option) *Plugin
New instantiates a new Magic Link plugin configured with the given repository and options.
func (*Plugin) ServeSignIn ¶ added in v0.20.0
func (p *Plugin) ServeSignIn(w http.ResponseWriter, r *http.Request)
ServeSignIn handles HTTP POST /sign-in/magic-link requests.
func (*Plugin) ServeVerify ¶ added in v0.20.0
func (p *Plugin) ServeVerify(w http.ResponseWriter, r *http.Request)
ServeVerify handles HTTP GET/POST /magic-link/verify requests.
func (*Plugin) SignInMagicLink ¶
func (p *Plugin) SignInMagicLink(ctx context.Context, params SignInMagicLinkParams) (*SignInMagicLinkResult, error)
SignInMagicLink generates a secure token, saves the verification record, and dispatches the magic link email.
func (*Plugin) VerifyMagicLink ¶
func (p *Plugin) VerifyMagicLink(ctx context.Context, params VerifyMagicLinkParams) (*VerifyMagicLinkResult, error)
VerifyMagicLink verifies the token atómicamente, authenticates or registers the user, and creates a session.
type RateLimitConfig ¶
type RateLimitConfig struct {
// Window specifies the sliding rate limit time window.
Window time.Duration `json:"window"`
// Max specifies the maximum allowed requests within the configured window.
Max int `json:"max"`
}
RateLimitConfig defines request throttling limits for magic link dispatching.
type Repository ¶
type Repository interface {
// CreateVerificationValue creates a new verification record in persistent storage.
CreateVerificationValue(ctx context.Context, record *VerificationRecord) error
// FindVerificationValue retrieves an active verification record matching the given identifier.
FindVerificationValue(ctx context.Context, identifier string) (*VerificationRecord, error)
// ConsumeVerificationValue atomically retrieves and removes/invalidates a verification record by identifier.
// This operation MUST be single-use to protect against race conditions and token replay attacks.
ConsumeVerificationValue(ctx context.Context, identifier string) (*VerificationRecord, error)
// DeleteVerificationValue removes a verification record from persistent storage.
DeleteVerificationValue(ctx context.Context, identifier string) error
// FindUserByEmail retrieves a user by their email address.
FindUserByEmail(ctx context.Context, email string) (*entity.User, error)
// CreateUser persists a new user entity in storage.
CreateUser(ctx context.Context, user *entity.User) (*entity.User, error)
// UpdateEmailVerified updates the email verification status for a specific user.
UpdateEmailVerified(ctx context.Context, userID string, verified bool) error
// CreateSession initializes and persists an active user session.
CreateSession(ctx context.Context, session *entity.Session) (*entity.Session, error)
}
Repository defines the persistent storage contract required by the Magic Link plugin.
type SendMagicLinkData ¶
type SendMagicLinkData struct {
// Email is the target recipient email address.
Email string `json:"email"`
// Name is an optional recipient display name.
Name string `json:"name,omitempty"`
// URL is the generated full verification URL including token and query parameters.
URL string `json:"url"`
// Token is the raw verification token string.
Token string `json:"token"`
// CallbackURL is the destination URL to redirect upon successful verification.
CallbackURL string `json:"callback_url,omitempty"`
// NewUserCallbackURL is an optional destination URL for newly registered users.
NewUserCallbackURL string `json:"new_user_callback_url,omitempty"`
// ErrorCallbackURL is an optional destination URL on verification failures.
ErrorCallbackURL string `json:"error_callback_url,omitempty"`
// Extra holds dynamic metadata passed through request parameters or hooks.
Extra map[string]any `json:"extra,omitempty"`
}
SendMagicLinkData contains parameters passed to the transactional email delivery callback.
type SendMagicLinkFunc ¶
type SendMagicLinkFunc func(ctx context.Context, data SendMagicLinkData) error
SendMagicLinkFunc defines the required transactional email delivery callback.
type SendMagicLinkPendingPayload ¶
type SendMagicLinkPendingPayload struct {
Email string `json:"email"`
URL string `json:"url"`
ExpiresAt time.Time `json:"expires_at"`
Extra map[string]any `json:"extra,omitempty"`
}
SendMagicLinkPendingPayload contains recipient and expiration details before dispatching a magic link.
type SignInMagicLinkParams ¶
type SignInMagicLinkParams struct {
// Email is the target recipient email address (required).
Email string `json:"email"`
// Name is an optional recipient display name.
Name string `json:"name,omitempty"`
// CallbackURL is the target redirect URL after successful verification.
CallbackURL string `json:"callback_url,omitempty"`
// NewUserCallbackURL is an optional target redirect URL for newly created users.
NewUserCallbackURL string `json:"new_user_callback_url,omitempty"`
// ErrorCallbackURL is an optional target redirect URL on verification error.
ErrorCallbackURL string `json:"error_callback_url,omitempty"`
plugin.ExtraContainer
}
SignInMagicLinkParams defines input parameters to generate and send a magic link email.
type SignInMagicLinkResult ¶
type SignInMagicLinkResult struct {
// Success indicates if the magic link was generated and dispatched.
Success bool `json:"success"`
// ExpiresAt indicates when the dispatched magic link token will expire.
ExpiresAt time.Time `json:"expires_at"`
}
SignInMagicLinkResult contains delivery status and expiration of the generated magic link.
type SignInSuccessPayload ¶
type SignInSuccessPayload struct {
User *entity.User `json:"user"`
Session *entity.Session `json:"session"`
IsNewUser bool `json:"is_new_user"`
}
SignInSuccessPayload contains authentication output upon successful magic link login.
type StoreTokenMode ¶
type StoreTokenMode string
StoreTokenMode defines how magic link verification tokens are persisted in storage.
const ( // StoreTokenPlain persists the token in raw plain text format. StoreTokenPlain StoreTokenMode = "plain" // StoreTokenHashed persists the token as a one-way cryptographic hash (SHA-256 by default). StoreTokenHashed StoreTokenMode = "hashed" // StoreTokenEncrypted persists the token using AES-256-GCM symmetric encryption. StoreTokenEncrypted StoreTokenMode = "encrypted" )
type TokenGeneratorFunc ¶
TokenGeneratorFunc defines a custom random verification token generator callback.
type TokenPayload ¶
type TokenPayload struct {
Token string `json:"token"`
Email string `json:"email"`
Name string `json:"name,omitempty"`
CallbackURL string `json:"callback_url,omitempty"`
NewUserCallbackURL string `json:"new_user_callback_url,omitempty"`
ErrorCallbackURL string `json:"error_callback_url,omitempty"`
Extra map[string]any `json:"extra,omitempty"`
}
TokenPayload holds stored token data and metadata.
type VerificationRecord ¶
type VerificationRecord struct {
// ID is the unique database record identifier.
ID string `json:"id"`
// Identifier is the composite lookup key (e.g. "magic-link-token-user@example.com").
Identifier string `json:"identifier"`
// Value stores the token value (or hashed/encrypted token) along with metadata payload.
Value string `json:"value"`
// ExpiresAt specifies the exact timestamp after which this token is invalid.
ExpiresAt time.Time `json:"expires_at"`
// CreatedAt records when the token record was initialized.
CreatedAt time.Time `json:"created_at"`
// UpdatedAt records when the token record was last modified.
UpdatedAt time.Time `json:"updated_at"`
}
VerificationRecord represents the persistent storage entity for a magic link token.
type VerifyBeforePayload ¶
type VerifyBeforePayload struct {
Token string `json:"token"`
Extra map[string]any `json:"extra,omitempty"`
}
VerifyBeforePayload contains the raw token and extra parameters before verification execution.
type VerifyMagicLinkParams ¶
type VerifyMagicLinkParams struct {
// Token is the magic link verification token string (required).
Token string `json:"token"`
// Email is an optional email address parameter for token scoping.
Email string `json:"email,omitempty"`
// CallbackURL overrides post-verification redirect URL.
CallbackURL string `json:"callback_url,omitempty"`
// NewUserCallbackURL overrides new-user redirect URL.
NewUserCallbackURL string `json:"new_user_callback_url,omitempty"`
// ErrorCallbackURL overrides error redirect URL.
ErrorCallbackURL string `json:"error_callback_url,omitempty"`
plugin.ExtraContainer
}
VerifyMagicLinkParams defines input parameters to verify a magic link token.
type VerifyMagicLinkResult ¶
type VerifyMagicLinkResult struct {
// User is the authenticated or newly created user entity.
User *entity.User `json:"user"`
// Session is the newly created active user session.
Session *entity.Session `json:"session"`
// IsNewUser reports whether a new user account was registered during verification.
IsNewUser bool `json:"is_new_user"`
// RedirectURL is the calculated destination URL for browser navigation.
RedirectURL string `json:"redirect_url"`
}
VerifyMagicLinkResult contains the authenticated user, session, and redirect URL output.