otp

package
v0.0.0-...-c4f7e29 Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2024 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ForgotPasswordTriggerEmailPerIP     ratelimit.BucketName = "ForgotPasswordTriggerEmailPerIP"
	ForgotPasswordTriggerSMSPerIP       ratelimit.BucketName = "ForgotPasswordTriggerSMSPerIP"
	ForgotPasswordTriggerWhatsappPerIP  ratelimit.BucketName = "ForgotPasswordTriggerWhatsappPerIP"
	ForgotPasswordCooldownEmail         ratelimit.BucketName = "ForgotPasswordCooldownEmail"
	ForgotPasswordCooldownSMS           ratelimit.BucketName = "ForgotPasswordCooldownSMS"
	ForgotPasswordCooldownWhatsapp      ratelimit.BucketName = "ForgotPasswordCooldownWhatsapp"
	ForgotPasswordValidateEmailPerIP    ratelimit.BucketName = "ForgotPasswordValidateEmailPerIP"
	ForgotPasswordValidateSMSPerIP      ratelimit.BucketName = "ForgotPasswordValidateSMSPerIP"
	ForgotPasswordValidateWhatsappPerIP ratelimit.BucketName = "ForgotPasswordValidateWhatsappPerIP"
)
View Source
const (
	OOBOTPTriggerEmailPerIP            ratelimit.BucketName = "OOBOTPTriggerEmailPerIP"
	OOBOTPTriggerSMSPerIP              ratelimit.BucketName = "OOBOTPTriggerSMSPerIP"
	OOBOTPTriggerWhatsappPerIP         ratelimit.BucketName = "OOBOTPTriggerWhatsappPerIP"
	OOBOTPTriggerEmailPerUser          ratelimit.BucketName = "OOBOTPTriggerEmailPerUser"
	OOBOTPTriggerSMSPerUser            ratelimit.BucketName = "OOBOTPTriggerSMSPerUser"
	OOBOTPTriggerWhatsappPerUser       ratelimit.BucketName = "OOBOTPTriggerWhatsappPerUser"
	OOBOTPCooldownEmail                ratelimit.BucketName = "OOBOTPCooldownEmail"
	OOBOTPCooldownSMS                  ratelimit.BucketName = "OOBOTPCooldownSMS"
	OOBOTPCooldownWhatsapp             ratelimit.BucketName = "OOBOTPCooldownWhatsapp"
	OOBOTPValidateEmailPerIP           ratelimit.BucketName = "OOBOTPValidateEmailPerIP"
	OOBOTPValidateSMSPerIP             ratelimit.BucketName = "OOBOTPValidateSMSPerIP"
	OOBOTPValidateWhatsappPerIP        ratelimit.BucketName = "OOBOTPValidateWhatsappPerIP"
	OOBOTPValidateEmailPerUserPerIP    ratelimit.BucketName = "OOBOTPValidateEmailPerUserPerIP"
	OOBOTPValidateSMSPerUserPerIP      ratelimit.BucketName = "OOBOTPValidateSMSPerUserPerIP"
	OOBOTPValidateWhatsappPerUserPerIP ratelimit.BucketName = "OOBOTPValidateWhatsappPerUserPerIP"
	AuthenticatePerIP                  ratelimit.BucketName = "AuthenticatePerIP"
	AuthenticatePerUserPerIP           ratelimit.BucketName = "AuthenticatePerUserPerIP"
)
View Source
const (
	VerificationTriggerEmailPerIP      ratelimit.BucketName = "VerificationTriggerEmailPerIP"
	VerificationTriggerSMSPerIP        ratelimit.BucketName = "VerificationTriggerSMSPerIP"
	VerificationTriggerWhatsappPerIP   ratelimit.BucketName = "VerificationTriggerWhatsappPerIP"
	VerificationTriggerEmailPerUser    ratelimit.BucketName = "VerificationTriggerEmailPerUser"
	VerificationTriggerSMSPerUser      ratelimit.BucketName = "VerificationTriggerSMSPerUser"
	VerificationTriggerWhatsappPerUser ratelimit.BucketName = "VerificationTriggerWhatsappPerUser"
	VerificationCooldownEmail          ratelimit.BucketName = "VerificationCooldownEmail"
	VerificationCooldownSMS            ratelimit.BucketName = "VerificationCooldownSMS"
	VerificationCooldownWhatsapp       ratelimit.BucketName = "VerificationCooldownWhatsapp"
	VerificationValidateEmailPerIP     ratelimit.BucketName = "VerificationValidateEmailPerIP"
	VerificationValidateSMSPerIP       ratelimit.BucketName = "VerificationValidateSMSPerIP"
	VerificationValidateWhatsappPerIP  ratelimit.BucketName = "VerificationValidateWhatsappPerIP"
)
View Source
const (
	WhatsappCodeDuration = duration.UserInteraction
)

Variables

View Source
var (
	TemplateMessageVerificationSMSTXT    = template.RegisterPlainText("messages/verification_sms.txt")
	TemplateMessageVerificationEmailTXT  = template.RegisterPlainText("messages/verification_email.txt")
	TemplateMessageVerificationEmailHTML = template.RegisterAppOverridableHTML("messages/verification_email.html")

	TemplateMessageSetupPrimaryOOBSMSTXT    = template.RegisterPlainText("messages/setup_primary_oob_sms.txt")
	TemplateMessageSetupPrimaryOOBEmailTXT  = template.RegisterPlainText("messages/setup_primary_oob_email.txt")
	TemplateMessageSetupPrimaryOOBEmailHTML = template.RegisterAppOverridableHTML("messages/setup_primary_oob_email.html")

	TemplateMessageSetupSecondaryOOBSMSTXT    = template.RegisterPlainText("messages/setup_secondary_oob_sms.txt")
	TemplateMessageSetupSecondaryOOBEmailTXT  = template.RegisterPlainText("messages/setup_secondary_oob_email.txt")
	TemplateMessageSetupSecondaryOOBEmailHTML = template.RegisterAppOverridableHTML("messages/setup_secondary_oob_email.html")

	TemplateMessageAuthenticatePrimaryOOBSMSTXT    = template.RegisterPlainText("messages/authenticate_primary_oob_sms.txt")
	TemplateMessageAuthenticatePrimaryOOBEmailTXT  = template.RegisterPlainText("messages/authenticate_primary_oob_email.txt")
	TemplateMessageAuthenticatePrimaryOOBEmailHTML = template.RegisterAppOverridableHTML("messages/authenticate_primary_oob_email.html")

	TemplateMessageAuthenticatePrimaryLoginLinkEmailTXT  = template.RegisterPlainText("messages/authenticate_primary_login_link.txt")
	TemplateMessageAuthenticatePrimaryLoginLinkEmailHTML = template.RegisterAppOverridableHTML("messages/authenticate_primary_login_link.html")

	TemplateMessageAuthenticateSecondaryOOBSMSTXT    = template.RegisterPlainText("messages/authenticate_secondary_oob_sms.txt")
	TemplateMessageAuthenticateSecondaryOOBEmailTXT  = template.RegisterPlainText("messages/authenticate_secondary_oob_email.txt")
	TemplateMessageAuthenticateSecondaryOOBEmailHTML = template.RegisterAppOverridableHTML("messages/authenticate_secondary_oob_email.html")

	TemplateMessageSetupPrimaryLoginLinkEmailTXT  = template.RegisterPlainText("messages/setup_primary_login_link.txt")
	TemplateMessageSetupPrimaryLoginLinkEmailHTML = template.RegisterAppOverridableHTML("messages/setup_primary_login_link.html")

	TemplateMessageSetupSecondaryLoginLinkEmailTXT  = template.RegisterPlainText("messages/setup_secondary_login_link.txt")
	TemplateMessageSetupSecondaryLoginLinkEmailHTML = template.RegisterAppOverridableHTML("messages/setup_secondary_login_link.html")

	TemplateMessageAuthenticateSecondaryLoginLinkEmailTXT  = template.RegisterPlainText("messages/authenticate_secondary_login_link.txt")
	TemplateMessageAuthenticateSecondaryLoginLinkEmailHTML = template.RegisterAppOverridableHTML("messages/authenticate_secondary_login_link.html")

	TemplateMessageForgotPasswordLinkSMSTXT    = template.RegisterPlainText("messages/forgot_password_sms.txt")
	TemplateMessageForgotPasswordLinkEmailTXT  = template.RegisterPlainText("messages/forgot_password_email.txt")
	TemplateMessageForgotPasswordLinkEmailHTML = template.RegisterAppOverridableHTML("messages/forgot_password_email.html")

	TemplateMessageForgotPasswordOOBSMSTXT    = template.RegisterPlainText("messages/forgot_password_oob_sms.txt")
	TemplateMessageForgotPasswordOOBEmailTXT  = template.RegisterPlainText("messages/forgot_password_oob_email.txt")
	TemplateMessageForgotPasswordOOBEmailHTML = template.RegisterAppOverridableHTML("messages/forgot_password_oob_email.html")

	TemplateWhatsappOTPCodeTXT = template.RegisterPlainText("messages/whatsapp_otp_code.txt")
)
View Source
var ErrCodeNotFound = InvalidOTPCode.NewWithCause("otp code is expired or invalid", apierrors.StringCause("CodeNotFound"))
View Source
var ErrConsumedCode = InvalidOTPCode.NewWithCause("used otp code", apierrors.StringCause("UsedCode"))
View Source
var ErrInvalidCode = InvalidOTPCode.NewWithCause("invalid otp code", apierrors.StringCause("InvalidCode"))
View Source
var ErrInvalidWhatsappUser = InvalidWhatsappUser.New("invalid whatsapp user")
View Source
var ErrTooManyAttempts = ratelimit.RateLimited.NewWithInfo("too many verify OTP attempts", apierrors.Details{
	"bucket_name": "TrackFailedOTPAttemptBucket",
})

FIXME: backward compat; should not use RateLimited

View Source
var InvalidOTPCode = apierrors.Forbidden.WithReason("InvalidOTPCode")
View Source
var InvalidWhatsappUser = apierrors.BadRequest.WithReason("InvalidWhatsappUser")

Functions

This section is empty.

Types

type AttemptTracker

type AttemptTracker interface {
	ResetFailedAttempts(purpose Purpose, target string) error
	GetFailedAttempts(purpose Purpose, target string) (int, error)
	IncrementFailedAttempts(purpose Purpose, target string) (int, error)
}

type AttemptTrackerRedis

type AttemptTrackerRedis struct {
	Redis *appredis.Handle
	AppID config.AppID
	Clock clock.Clock
}

func (*AttemptTrackerRedis) GetFailedAttempts

func (s *AttemptTrackerRedis) GetFailedAttempts(purpose Purpose, target string) (int, error)

func (*AttemptTrackerRedis) IncrementFailedAttempts

func (s *AttemptTrackerRedis) IncrementFailedAttempts(purpose Purpose, target string) (int, error)

func (*AttemptTrackerRedis) ResetFailedAttempts

func (s *AttemptTrackerRedis) ResetFailedAttempts(purpose Purpose, target string) error

type Code

type Code struct {
	Target   string    `json:"target"`
	Purpose  Purpose   `json:"purpose"`
	Form     Form      `json:"form"`
	Code     string    `json:"code"`
	ExpireAt time.Time `json:"expire_at"`
	Consumed bool      `json:"consumed"`

	UserInputtedCode string `json:"user_inputted_code,omitempty"`
	UserID           string `json:"user_id,omitempty"`

	// For interaction
	WebSessionID string `json:"web_session_id,omitempty"`

	// For legacy workflow
	WorkflowID string `json:"workflow_id,omitempty"`

	// For authentication flow
	AuthenticationFlowWebsocketChannelName string        `json:"authentication_flow_websocket_channel_name,omitempty"`
	AuthenticationFlowType                 string        `json:"authentication_flow_type,omitempty"`
	AuthenticationFlowName                 string        `json:"authentication_flow_name,omitempty"`
	AuthenticationFlowJSONPointer          jsonpointer.T `json:"authentication_flow_json_pointer,omitempty"`
}

type CodeStore

type CodeStore interface {
	Create(purpose Purpose, code *Code) error
	Get(purpose Purpose, target string) (*Code, error)
	Update(purpose Purpose, code *Code) error
	Delete(purpose Purpose, target string) error
}

type CodeStoreRedis

type CodeStoreRedis struct {
	Redis *appredis.Handle
	AppID config.AppID
	Clock clock.Clock
}

func (*CodeStoreRedis) Create

func (s *CodeStoreRedis) Create(purpose Purpose, code *Code) error

func (*CodeStoreRedis) Delete

func (s *CodeStoreRedis) Delete(purpose Purpose, target string) error

func (*CodeStoreRedis) Get

func (s *CodeStoreRedis) Get(purpose Purpose, target string) (*Code, error)

func (*CodeStoreRedis) Update

func (s *CodeStoreRedis) Update(purpose Purpose, code *Code) error

type EndpointsProvider

type EndpointsProvider interface {
	Origin() *neturl.URL
	LoginLinkVerificationEndpointURL(uiImpl config.UIImplementation) *neturl.URL
	ResetPasswordEndpointURL(uiImpl config.UIImplementation) *neturl.URL
}

type Form

type Form string
const (
	FormCode Form = "code"
	FormLink Form = "link"
)

func (Form) AllowLookupByCode

func (f Form) AllowLookupByCode() bool

func (Form) CodeLength

func (f Form) CodeLength() int

func (Form) GenerateCode

func (f Form) GenerateCode(cfg *config.TestModeConfig, featureCfg *config.TestModeFeatureConfig, target string, userID string) string

func (Form) VerifyCode

func (f Form) VerifyCode(input string, expected string) bool

type GenerateOptions

type GenerateOptions struct {
	UserID                                 string
	WebSessionID                           string
	WorkflowID                             string
	AuthenticationFlowWebsocketChannelName string
	AuthenticationFlowType                 string
	AuthenticationFlowName                 string
	AuthenticationFlowJSONPointer          jsonpointer.T
	SkipRateLimits                         bool
}

type Kind

type Kind interface {
	Purpose() Purpose
	ValidPeriod() time.Duration

	RateLimitTriggerPerIP(ip string) ratelimit.BucketSpec
	RateLimitTriggerPerUser(userID string) ratelimit.BucketSpec
	RateLimitTriggerCooldown(target string) ratelimit.BucketSpec
	RateLimitValidatePerIP(ip string) ratelimit.BucketSpec
	RateLimitValidatePerUserPerIP(userID string, ip string) ratelimit.BucketSpec
	RevocationMaxFailedAttempts() int
}
func KindForgotPasswordLink(
	config *config.AppConfig,
	channel model.AuthenticatorOOBChannel) Kind

func KindForgotPasswordOTP

func KindForgotPasswordOTP(
	config *config.AppConfig,
	channel model.AuthenticatorOOBChannel) Kind

func KindOOBOTP

func KindOOBOTP(config *config.AppConfig, channel model.AuthenticatorOOBChannel) Kind

func KindVerification

func KindVerification(config *config.AppConfig, channel model.AuthenticatorOOBChannel) Kind

type KindFactory

type KindFactory func(config *config.AppConfig, channel model.AuthenticatorOOBChannel) Kind

type Logger

type Logger struct{ *log.Logger }

func NewLogger

func NewLogger(lf *log.Factory) Logger

type LookupStore

type LookupStore interface {
	Create(purpose Purpose, code string, target string, expireAt time.Time) error
	Get(purpose Purpose, code string) (string, error)
	Delete(purpose Purpose, code string) error
}

type LookupStoreRedis

type LookupStoreRedis struct {
	Redis *appredis.Handle
	AppID config.AppID
	Clock clock.Clock
}

func (*LookupStoreRedis) Create

func (s *LookupStoreRedis) Create(purpose Purpose, code string, target string, expireAt time.Time) error

func (*LookupStoreRedis) Delete

func (s *LookupStoreRedis) Delete(purpose Purpose, code string) error

func (*LookupStoreRedis) Get

func (s *LookupStoreRedis) Get(purpose Purpose, code string) (target string, err error)

type MessageSender

type MessageSender struct {
	Translation     TranslationService
	Endpoints       EndpointsProvider
	Sender          Sender
	WhatsappService WhatsappService
	UIConfig        *config.UIConfig
}

func (*MessageSender) Prepare

func (s *MessageSender) Prepare(channel model.AuthenticatorOOBChannel, target string, form Form, typ MessageType) (*PreparedMessage, error)

func (*MessageSender) Send

func (s *MessageSender) Send(msg *PreparedMessage, opts SendOptions) error

type MessageType

type MessageType string
const (
	MessageTypeVerification             MessageType = "verification"
	MessageTypeSetupPrimaryOOB          MessageType = "setup-primary-oob"
	MessageTypeSetupSecondaryOOB        MessageType = "setup-secondary-oob"
	MessageTypeAuthenticatePrimaryOOB   MessageType = "authenticate-primary-oob"
	MessageTypeAuthenticateSecondaryOOB MessageType = "authenticate-secondary-oob"
	MessageTypeForgotPassword           MessageType = "forgot-password"
	MessageTypeWhatsappCode             MessageType = "whatsapp-code"
)

type PreparedMessage

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

func (*PreparedMessage) Close

func (m *PreparedMessage) Close()

type Purpose

type Purpose string
const PurposeForgotPassword Purpose = "forgot-password"
const PurposeOOBOTP Purpose = "oob-otp"
const PurposeVerification Purpose = "verification"

type RateLimiter

type RateLimiter interface {
	Allow(spec ratelimit.BucketSpec) error
	Reserve(spec ratelimit.BucketSpec) *ratelimit.Reservation
	ReserveN(spec ratelimit.BucketSpec, n int) *ratelimit.Reservation
	Cancel(r *ratelimit.Reservation)
}

type SendOptions

type SendOptions struct {
	OTP               string
	AdditionalContext any
}

type Sender

type Sender interface {
	PrepareEmail(email string, msgType nonblocking.MessageType) (*messaging.EmailMessage, error)
	PrepareSMS(phoneNumber string, msgType nonblocking.MessageType) (*messaging.SMSMessage, error)
	PrepareWhatsapp(phoneNumber string, msgType nonblocking.MessageType) (*messaging.WhatsappMessage, error)
}

type Service

type Service struct {
	Clock clock.Clock

	AppID                 config.AppID
	TestModeConfig        *config.TestModeConfig
	TestModeFeatureConfig *config.TestModeFeatureConfig
	RemoteIP              httputil.RemoteIP
	CodeStore             CodeStore
	LookupStore           LookupStore
	AttemptTracker        AttemptTracker
	Logger                Logger
	RateLimiter           RateLimiter
}

func (*Service) ConsumeCode

func (s *Service) ConsumeCode(purpose Purpose, target string) error

func (*Service) GenerateOTP

func (s *Service) GenerateOTP(kind Kind, target string, form Form, opts *GenerateOptions) (string, error)

func (*Service) InspectCode

func (s *Service) InspectCode(purpose Purpose, target string) (*Code, error)

func (*Service) InspectState

func (s *Service) InspectState(kind Kind, target string) (*State, error)

func (*Service) LookupCode

func (s *Service) LookupCode(purpose Purpose, code string) (target string, err error)

func (*Service) SetSubmittedCode

func (s *Service) SetSubmittedCode(kind Kind, target string, code string) (*State, error)

func (*Service) VerifyOTP

func (s *Service) VerifyOTP(kind Kind, target string, otp string, opts *VerifyOptions) error

type State

type State struct {
	ExpireAt        time.Time
	CanResendAt     time.Time
	SubmittedCode   string
	UserID          string
	TooManyAttempts bool

	WebSessionID                           string
	WorkflowID                             string
	AuthenticationFlowWebsocketChannelName string
	AuthenticationFlowType                 string
	AuthenticationFlowName                 string
	AuthenticationFlowJSONPointer          jsonpointer.T
}

type TranslationService

type TranslationService interface {
	EmailMessageData(msg *translation.MessageSpec, args interface{}) (*translation.EmailMessageData, error)
	SMSMessageData(msg *translation.MessageSpec, args interface{}) (*translation.SMSMessageData, error)
	WhatsappMessageData(language string, msg *translation.MessageSpec, args interface{}) (*translation.WhatsappMessageData, error)
}

type VerifyOptions

type VerifyOptions struct {
	UserID           string
	UseSubmittedCode bool
	SkipConsume      bool
}

type WhatsappService

type WhatsappService interface {
	ResolveOTPTemplateLanguage() (string, error)
	PrepareOTPTemplate(language string, text string, code string) (*whatsapp.PreparedOTPTemplate, error)
	SendTemplate(opts *whatsapp.SendTemplateOptions) error
}

Jump to

Keyboard shortcuts

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