otp

package
v0.0.0-...-45fc8d6 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2024 License: Apache-2.0 Imports: 25 Imported by: 1

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 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 ErrNoAvailableWhatsappClient = NoAvailableWhatsappClient.New("no available whatsapp client")
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 FromAdminAPIQueryKey = "x_from_admin_api"
View Source
var InvalidOTPCode = apierrors.Forbidden.WithReason("InvalidOTPCode")
View Source
var InvalidWhatsappUser = apierrors.BadRequest.WithReason("InvalidWhatsappUser")
View Source
var NoAvailableWhatsappClient = apierrors.BadRequest.WithReason("NoAvailableWhatsappClient")

Functions

This section is empty.

Types

type AdditionalContext

type AdditionalContext struct {
	HasPassword bool
}

type AttemptTracker

type AttemptTracker interface {
	ResetFailedAttempts(ctx context.Context, kind Kind, target string) error
	GetFailedAttempts(ctx context.Context, kind Kind, target string) (int, error)
	IncrementFailedAttempts(ctx context.Context, kind Kind, 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(ctx context.Context, kind Kind, target string) (int, error)

func (*AttemptTrackerRedis) IncrementFailedAttempts

func (s *AttemptTrackerRedis) IncrementFailedAttempts(ctx context.Context, kind Kind, target string) (int, error)

func (*AttemptTrackerRedis) ResetFailedAttempts

func (s *AttemptTrackerRedis) ResetFailedAttempts(ctx context.Context, kind Kind, 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(ctx context.Context, purpose Purpose, code *Code) error
	Get(ctx context.Context, purpose Purpose, target string) (*Code, error)
	Update(ctx context.Context, purpose Purpose, code *Code) error
	Delete(ctx context.Context, 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(ctx context.Context, purpose Purpose, code *Code) error

func (*CodeStoreRedis) Delete

func (s *CodeStoreRedis) Delete(ctx context.Context, purpose Purpose, target string) error

func (*CodeStoreRedis) Get

func (s *CodeStoreRedis) Get(ctx context.Context, purpose Purpose, target string) (*Code, error)

func (*CodeStoreRedis) Update

func (s *CodeStoreRedis) Update(ctx context.Context, purpose Purpose, code *Code) error

type DeprecatedKindFactory

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

type EndpointsProvider

type EndpointsProvider interface {
	Origin() *neturl.URL
	LoginLinkVerificationEndpointURL() *neturl.URL
	ResetPasswordEndpointURL() *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 KindOOBOTPCode

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

func KindOOBOTPWithForm

func KindOOBOTPWithForm(config *config.AppConfig, channel model.AuthenticatorOOBChannel, form Form) Kind

func KindVerification

func KindVerification(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(ctx context.Context, purpose Purpose, code string, target string, expireAt time.Time) error
	Get(ctx context.Context, purpose Purpose, code string) (string, error)
	Delete(ctx context.Context, 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(ctx context.Context, purpose Purpose, code string, target string, expireAt time.Time) error

func (*LookupStoreRedis) Delete

func (s *LookupStoreRedis) Delete(ctx context.Context, purpose Purpose, code string) error

func (*LookupStoreRedis) Get

func (s *LookupStoreRedis) Get(ctx context.Context, purpose Purpose, code string) (target string, err error)

type MessageSender

type MessageSender struct {
	AppID       config.AppID
	Translation TranslationService
	Endpoints   EndpointsProvider
	Sender      Sender
}

func (*MessageSender) Send

func (s *MessageSender) Send(ctx context.Context, opts SendOptions) error

type Purpose

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

type SendOptions

type SendOptions struct {
	Channel                 model.AuthenticatorOOBChannel
	Target                  string
	Form                    Form
	Type                    translation.MessageType
	OTP                     string
	AdditionalContext       *AdditionalContext
	IsAdminAPIResetPassword bool
}

type Sender

type Sender interface {
	SendEmailInNewGoroutine(ctx context.Context, msgType translation.MessageType, opts *mail.SendOptions) error
	SendSMSInNewGoroutine(ctx context.Context, msgType translation.MessageType, opts *sms.SendOptions) error
	SendWhatsappImmediately(ctx context.Context, msgType translation.MessageType, opts *whatsapp.SendAuthenticationOTPOptions) 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(ctx context.Context, purpose Purpose, target string) error

func (*Service) GenerateOTP

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

func (*Service) InspectCode

func (s *Service) InspectCode(ctx context.Context, purpose Purpose, target string) (*Code, error)

func (*Service) InspectState

func (s *Service) InspectState(ctx context.Context, kind Kind, target string) (*State, error)

func (*Service) LookupCode

func (s *Service) LookupCode(ctx context.Context, purpose Purpose, code string) (target string, err error)

func (*Service) SetSubmittedCode

func (s *Service) SetSubmittedCode(ctx context.Context, kind Kind, target string, code string) (*State, error)

func (*Service) VerifyOTP

func (s *Service) VerifyOTP(ctx context.Context, 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 VerifyOptions

type VerifyOptions struct {
	UserID           string
	UseSubmittedCode bool
	SkipConsume      bool
}

Jump to

Keyboard shortcuts

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