Documentation
¶
Overview ¶
Package mfa defines the multi-factor authentication method drivers, the enrollment Store and the registry that resolves configured methods per request.
Index ¶
- Constants
- Variables
- func EnrolledMethods(ctx context.Context, s Store, userID string) ([]string, error)
- func MethodAMR(m Method) []string
- func MethodBackup(m Method) bool
- func MethodExclusive(m Method) bool
- func MethodInteraction(m Method) string
- func Register(name string, d Driver)
- type AMRProvider
- type AsyncMethod
- type BackupMethod
- type CallbackHandler
- type Driver
- type Enrollment
- type EnrollmentData
- type ExclusiveMethod
- type Method
- type Registry
- type Store
- type Verification
- type VerifyResult
Constants ¶
const ( InteractionCode = "code" // submit a code / assertion via POST /mfa/verify InteractionPoll = "poll" // wait for out-of-band approval via GET /mfa/status )
Interaction hints surfaced to the client for the selected method.
Variables ¶
var ( // ErrUnknownMethod is returned when no configured or registered method matches the name. ErrUnknownMethod = errors.New("unknown mfa method") // ErrNotEnrolled is returned when the user has no matching enrollment. ErrNotEnrolled = errors.New("mfa method not enrolled") // ErrInvalidResponse is returned by Method.FinishEnroll for a wrong code or malformed // response, counting as a failed attempt. ErrInvalidResponse = errors.New("invalid mfa response") )
Functions ¶
func EnrolledMethods ¶
EnrolledMethods returns the names of the methods userID is enrolled in, in enrollment order.
func MethodBackup ¶
MethodBackup reports whether m only backs up another factor.
func MethodExclusive ¶
MethodExclusive reports whether m holds at most one enrollment per user.
func MethodInteraction ¶
MethodInteraction returns the client interaction hint for m.
Types ¶
type AMRProvider ¶
type AMRProvider interface {
AMR() []string
}
AMRProvider is an optional Method extension declaring the RFC 8176 amr values recorded when the factor passes. Without it "mfa" alone is recorded.
type AsyncMethod ¶
type AsyncMethod interface {
Async() bool
}
AsyncMethod is an optional Method extension for factors verified out-of-band (push approval): the login flow signals InteractionPoll instead of prompting for a code.
type BackupMethod ¶
type BackupMethod interface {
Backup() bool
}
BackupMethod is an optional Method extension for factors that only back up another one (ex. recovery codes).
type CallbackHandler ¶
CallbackHandler is an optional Method extension for vendors that deliver approval via an inbound webhook, dispatched from POST /mfa/callback/{method}. That route is unauthenticated and not rate limited.
type Driver ¶
type Driver interface {
// Open creates a Method over the shared store from the configuration entry.
Open(store Store, cfg *contract.MFAMethodConfig) (Method, error)
}
Driver is implemented by each MFA method package and registered via Register.
type Enrollment ¶
type Enrollment struct {
ID string
UserID string
Method string
// Label is the user-facing name of the device or app.
Label string
// Secret is the driver-specific enrollment data; never surfaced to clients.
Secret []byte
CreatedAt time.Time
LastUsedAt *time.Time
}
Enrollment is one enrolled instance of a method for a user: an authenticator app, a device or a code set. A user may hold several per method.
type EnrollmentData ¶
type EnrollmentData struct {
// Data is surfaced to the client, e.g. {"secret":"...","uri":"otpauth://..."} for TOTP.
Data map[string]any
// State is opaque driver state the library hands back to FinishEnroll; never surfaced.
State []byte
}
EnrollmentData is returned by BeginEnroll.
type ExclusiveMethod ¶
type ExclusiveMethod interface {
Exclusive() bool
}
ExclusiveMethod is an optional Method extension for factors holding at most one enrollment per user.
type Method ¶
type Method interface {
// BeginEnroll returns enrollment data for the user.
BeginEnroll(ctx context.Context, userID string, info contract.UserInfo) (EnrollmentData, error)
// FinishEnroll verifies the enrollment response against state and returns the secret the
// library stores; a wrong response returns ErrInvalidResponse.
FinishEnroll(ctx context.Context, userID string, state []byte, response map[string]any) ([]byte, error)
// BeginVerify starts a challenge across the user's enrollments. challengeID is the opaque
// server-side handle; data is surfaced to the client. Both are empty for self-contained
// methods (TOTP).
BeginVerify(ctx context.Context, userID string) (challengeID string, data map[string]any, err error)
// Verify evaluates response against challengeID and the user's enrollments. response is nil
// when polling an async method.
Verify(ctx context.Context, userID, challengeID string, response map[string]any) (Verification, error)
}
Method encapsulates one authentication factor.
type Registry ¶
type Registry interface {
// Get returns the method available under name, or ErrUnknownMethod.
Get(ctx context.Context, name string) (Method, error)
// Names returns every available method name, configured entries first.
Names(ctx context.Context) ([]string, error)
}
Registry resolves MFA methods by name.
func NewConfigRegistry ¶
func NewConfigRegistry(config *contract.Configuration, store Store) Registry
NewConfigRegistry creates the default Registry.
type Store ¶
type Store interface {
// List returns userID's enrollments, oldest first.
List(ctx context.Context, userID string) ([]*Enrollment, error)
// Enroll persists e under its ID, replacing an enrollment with the same ID.
Enroll(ctx context.Context, e *Enrollment) error
// CompareAndSwap replaces the secret of userID's enrollment id only when its current value
// equals expected. It returns false when the enrollment is missing or has changed, allowing
// one-time factors to be consumed exactly once across concurrent requests.
CompareAndSwap(ctx context.Context, userID, id string, expected, replacement []byte) (bool, error)
// Touch records that userID's enrollment id passed verification at at, or ErrNotEnrolled.
Touch(ctx context.Context, userID, id string, at time.Time) error
// Revoke removes userID's enrollment id, or ErrNotEnrolled.
Revoke(ctx context.Context, userID, id string) error
}
Store persists MFA enrollments.
func NewMemoryStore ¶
func NewMemoryStore() Store
NewMemoryStore creates an empty in-memory Store.
Warning: Use it only for development and/or testing.
type Verification ¶
type Verification struct {
Result VerifyResult
// EnrollmentID names the enrollment that satisfied the factor, when the method knows it.
EnrollmentID string
}
Verification is the outcome of Method.Verify.
type VerifyResult ¶
type VerifyResult string
VerifyResult is the tri-state outcome of Method.Verify.
const ( VerifyApproved VerifyResult = "approved" // factor satisfied - advance the session VerifyDenied VerifyResult = "denied" // wrong code / rejected push - a failed attempt VerifyPending VerifyResult = "pending" // async method awaiting out-of-band approval )
VerifyResult values.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package recovery is the backup/recovery-code MFA driver: single-use codes that unlock an account when the primary factor is lost.
|
Package recovery is the backup/recovery-code MFA driver: single-use codes that unlock an account when the primary factor is lost. |
|
Package totp is the built-in RFC 6238 time-based one-time password MFA driver.
|
Package totp is the built-in RFC 6238 time-based one-time password MFA driver. |