magiclink

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Jan 14, 2024 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// DefaultRedirectQueryKey is the default URL query parameter to contain the JWT in after a magic link has been
	// clicked.
	DefaultRedirectQueryKey = "jwt"
	// DefaultSecretQueryKey is the default URL query parameter to contain the secret for a magic link.
	DefaultSecretQueryKey = "secret"
)
View Source
const (
	// ReCAPTCHAV3QueryButtonBypassKey is the URL query parameter key for bypassing the reCAPTCHA v3 test.
	ReCAPTCHAV3QueryButtonBypassKey = "button-bypass"
	// ReCAPTCHAV3QueryButtonBypassValue is the URL query parameter value for bypassing the reCAPTCHA v3 test.
	ReCAPTCHAV3QueryButtonBypassValue = "true"
)
View Source
const DefaultJWKSCacheRefresh = 5 * time.Minute

DefaultJWKSCacheRefresh is the default time to wait before refreshing the JWKS cache.

Variables

View Source
var (
	// ErrJWKSEmpty is a possible error for an ErrorHandler implementation to handle.
	ErrJWKSEmpty = errors.New("JWK Set is empty")
	// ErrJWKSJSON is a possible error for an ErrorHandler implementation to handle.
	ErrJWKSJSON = errors.New("failed to get JWK Set as JSON")
	// ErrJWKSReadGivenKID is a possible error for an ErrorHandler implementation to handle.
	ErrJWKSReadGivenKID = errors.New("failed to read JWK with given key ID")
	// ErrJWKSSnapshot is a possible error for an ErrorHandler implementation to handle.
	ErrJWKSSnapshot = errors.New("failed to snapshot JWK Set")
	// ErrJWTSign is a possible error for an ErrorHandler implementation to handle.
	ErrJWTSign = errors.New("failed to sign JWT")
	// ErrLinkNotFound is a possible error for an ErrorHandler implementation to handle.
	ErrLinkNotFound = errors.New("link not found")
	// ErrMagicLinkMissingSecret is a possible error for an ErrorHandler implementation to handle.
	ErrMagicLinkMissingSecret = errors.New("visited magic link endpoint without a secret")
	// ErrMagicLinkRead is a possible error for an ErrorHandler implementation to handle.
	ErrMagicLinkRead = errors.New("failed to read the magic link from storage")
)

Errors that ErrorHandler needs to handle.

View Source
var (
	// ErrArgs indicates that the given parameters are invalid.
	ErrArgs = errors.New("invalid arguments")
)

Functions

func BestSigningMethod

func BestSigningMethod(key interface{}) jwt.SigningMethod

BestSigningMethod returns the best signing method for the given key.

Types

type Config

type Config[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any] struct {
	ErrorHandler     ErrorHandler
	JWKS             JWKSArgs[CustomKeyMeta]
	CustomRedirector Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]
	ServiceURL       *url.URL
	SecretQueryKey   string
	Store            Storage[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]
}

Config contains the required assets to create a MagicLink service.

func (Config[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) Valid

func (c Config[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) Valid() error

Valid confirms the Config is valid.

type CreateArgs

type CreateArgs[CustomCreateArgs any] struct {
	// Custom is additional data or metadata for your use case.
	Custom CustomCreateArgs

	// JWTClaims is a data structure that can marshal to JSON as the JWT Claims. Make sure to embed AND populate
	// jwt.RegisteredClaims if your use case supports standard claims. If you shadow the .Valid() method of the
	// interface, be sure to call .RegisteredClaims.Valid() in your implementation. If you are using a non-memory
	// Storage implementation, be sure the data structure is the proper Go type after being read. Use of this field is
	// OPTIONAL and RECOMMENDED for most use cases.
	JWTClaims jwt.Claims

	// JWTKeyID is the key ID of the key used to sign the JWT. If this is empty, the first key in the JWK Set will be
	// used. If no key with the key ID is present when the magic link is visited, the service will produce a HTTP 500
	// error. Use of this field is OPTIONAL.
	JWTKeyID *string

	// JWTSigningMethod is a string that can be passed to jwt.GetSigningMethod to get the appropriate jwt.SigningMethod
	// to sign the JWT with. Do not populate this field unless you know what you are doing. By default, the most secure
	// method will be used. If a key type other than ECDSA, EdDSA, or RSA is used, then the most secure HMAC signing
	// method will be chosen by default. Use of this field is OPTIONAL and NOT RECOMMENDED for most use cases.
	JWTSigningMethod string

	// RedirectQueryKey is the URL query key used in the redirect. It will contain the JWT. If this is empty, "jwt" will
	// be used. Use of this field is OPTIONAL.
	RedirectQueryKey string

	// RedirectURL is the URL to redirect to after the JWT is verified. Use of this field is REQUIRED for all use cases.
	RedirectURL *url.URL
}

CreateArgs are the arguments for creating a magic link.

func (CreateArgs[CustomCreateArgs]) Valid

func (p CreateArgs[CustomCreateArgs]) Valid() error

Valid confirms the CreateArgs are valid.

type CreateResponse

type CreateResponse struct {
	MagicLink *url.URL
	Secret    string
}

CreateResponse is the response after a magic link has been created.

type ErrorHandler

type ErrorHandler interface {
	// Handle consumes an error and writes a response to the given writer. The set of possible errors to check by
	// unwrapping with errors.Is is documented above the interface's source code.
	Handle(args ErrorHandlerArgs)
}

ErrorHandler handles errors that occur in MagicLink's HTTP handlers.

type ErrorHandlerArgs

type ErrorHandlerArgs struct {
	Err                   error
	Request               *http.Request
	SuggestedResponseCode int
	Writer                http.ResponseWriter
}

ErrorHandlerArgs are the arguments passed to an ErrorHandler when an error occurs.

type ErrorHandlerFunc

type ErrorHandlerFunc func(args ErrorHandlerArgs)

ErrorHandlerFunc is a function that implements the ErrorHandler interface.

func (ErrorHandlerFunc) Handle

func (f ErrorHandlerFunc) Handle(args ErrorHandlerArgs)

Handle implements the ErrorHandler interface.

type JWKSArgs

type JWKSArgs[CustomKeyMeta any] struct {
	CacheRefresh time.Duration
	Store        jwkset.Storage[CustomKeyMeta]
}

JWKSArgs are the parameters for the MagicLink service's JWK Set.

type MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any] struct {
	Store Storage[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]
	// contains filtered or unexported fields
}

MagicLink holds the necessary assets for the magic link service.

func NewMagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any](setupCtx context.Context, config Config[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) (MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta], error)

NewMagicLink creates a new MagicLink. The given setupCtx is only used during the creation of the MagicLink.

func (m MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) HandleMagicLink(ctx context.Context, secret string) (jwtB64 string, response ReadResponse[CustomCreateArgs, CustomReadResponse], err error)

HandleMagicLink is a method that accepts a magic link secret, then returns the signed JWT.

func (MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) JWKSHandler

func (m MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) JWKSHandler() http.Handler

JWKSHandler is an HTTP handler that responds to requests with the JWK Set as JSON.

func (MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) JWKSet

func (m MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) JWKSet() jwkset.JWKSet[CustomKeyMeta]

JWKSet is a getter method to return the underlying JWK Set.

func (MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) MagicLinkHandler

func (m MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) MagicLinkHandler() http.Handler

MagicLinkHandler is an HTTP handler that accepts HTTP requests with magic link secrets, then redirects to the given URL with the JWT as a query parameter.

func (m MagicLink[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) NewLink(ctx context.Context, args CreateArgs[CustomCreateArgs]) (CreateResponse, error)

NewLink creates a magic link with the given parameters.

type ReCAPTCHAV3Config

type ReCAPTCHAV3Config struct {
	APKPackageName []string                `json:"apkPackageName"`
	Action         []string                `json:"action"`
	Hostname       []string                `json:"hostname"`
	MinScore       float64                 `json:"minScore"`
	SecretKey      string                  `json:"secretKey"`
	TemplateData   ReCAPTCHAV3TemplateData `json:"templateData"`

	Verifier recaptcha.VerifierV3 `json:"-"`
}

ReCAPTCHAV3Config is the configuration for Google's reCAPTCHA v3.

func (ReCAPTCHAV3Config) DefaultsAndValidate

func (r ReCAPTCHAV3Config) DefaultsAndValidate() (ReCAPTCHAV3Config, error)

DefaultsAndValidate implements the jsontype.Config interface.

type ReCAPTCHAV3Redirector

type ReCAPTCHAV3Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any] struct {
	// contains filtered or unexported fields
}

ReCAPTCHAV3Redirector is a Redirector that uses Google's reCAPTCHA v3 to verify the user.

func (ReCAPTCHAV3Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) Redirect

func (r ReCAPTCHAV3Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]) Redirect(args RedirectorArgs[CustomCreateArgs, CustomReadResponse, CustomKeyMeta])

Redirect implements the Redirector interface.

type ReCAPTCHAV3TemplateData

type ReCAPTCHAV3TemplateData struct {
	ButtonBypass bool          `json:"buttonBypass"`
	ButtonText   string        `json:"buttonText"`
	CSS          template.CSS  `json:"css"`
	Code         string        `json:"code"`
	HTMLTitle    string        `json:"htmlTitle"`
	Instruction  string        `json:"instruction"`
	SiteKey      template.HTML `json:"siteKey"`
	Title        string        `json:"title"`

	FormAction string `json:"-"`
}

ReCAPTCHAV3TemplateData is the configuration for the HTML template for Google's reCAPTCHA v3.

func (ReCAPTCHAV3TemplateData) DefaultsAndValidate

func (r ReCAPTCHAV3TemplateData) DefaultsAndValidate() (ReCAPTCHAV3TemplateData, error)

DefaultsAndValidate implements the jsontype.Config interface.

type ReadResponse

type ReadResponse[CustomCreateArgs, CustomReadResponse any] struct {
	// Custom is additional data or metadata for your use case.
	Custom CustomReadResponse
	// CreateArgs are the parameters used to create the magic link.
	CreateArgs CreateArgs[CustomCreateArgs]
}

ReadResponse is the response after a magic link has been read.

type Redirector

type Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any] interface {
	Redirect(args RedirectorArgs[CustomCreateArgs, CustomReadResponse, CustomKeyMeta])
}

Redirector is a custom implementation of redirecting a user to a magic link target.

func NewReCAPTCHAV3Redirector

func NewReCAPTCHAV3Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any](config ReCAPTCHAV3Config) Redirector[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]

NewReCAPTCHAV3Redirector creates a new ReCAPTCHAV3Redirector with the given config.

type RedirectorArgs

type RedirectorArgs[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any] struct {
	ReadAndExpireLink func(ctx context.Context, secret string) (jwtB64 string, response ReadResponse[CustomCreateArgs, CustomReadResponse], err error)
	Request           *http.Request
	Secret            string
	Writer            http.ResponseWriter
}

RedirectorArgs are passed to a Redirector when performing a redirect.

type Storage

type Storage[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any] interface {
	// CreateLink creates a secret for the given parameters and stores the pair. The secret is returned to the caller.
	CreateLink(ctx context.Context, args CreateArgs[CustomCreateArgs]) (secret string, err error)
	// ReadLink finds the creation parameters for the given secret. ErrLinkNotFound is returned if the secret is not
	// found or was deleted/expired. This will automatically expire the link.
	ReadLink(ctx context.Context, secret string) (ReadResponse[CustomCreateArgs, CustomReadResponse], error)
}

Storage represents the underlying storage for the MagicLink service.

func NewMemoryStorage

func NewMemoryStorage[CustomCreateArgs, CustomReadResponse, CustomKeyMeta any]() Storage[CustomCreateArgs, CustomReadResponse, CustomKeyMeta]

NewMemoryStorage creates an in-memory implementation of the MagicLink Storage.

Jump to

Keyboard shortcuts

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