Help us shape the future of Go! Take the 2026 Go Developer Survey

twofactor

package
v0.14.0 Latest Latest
Warning

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

Go to latest
Published: Oct 23, 2026 License: AGPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package twofactor is the second factor of a local account (R-405): an authenticator app's time-based codes (TOTP, RFC 6238) and recovery codes.

Local accounts only. An account from an identity provider gets its second factor from the provider, and Pando never asks it for one (R-044: the provider authenticates).

Index

Constants

View Source
const RecoveryCodeCount = 10

RecoveryCodeCount is how many recovery codes a set holds.

Variables

This section is empty.

Functions

func IsAuthenticatorCode

func IsAuthenticatorCode(s string) bool

IsAuthenticatorCode says whether what someone typed is shaped like an authenticator code rather than a recovery code, spaces aside.

func IssuerFor

func IssuerFor(external *url.URL) string

IssuerFor names an installation in authenticator apps: "Pando", with the host it is reached at when one is configured, so two installations on one phone are told apart.

Types

type Enrollment

type Enrollment struct {
	Secret secret.Value `json:"-"`
	URI    secret.Value `json:"-"`
	QRSVG  string       `json:"-"`
}

Enrollment is a new authenticator, shown to its holder once: the secret to type in, and the same as a key URI and a QR code holding it.

type Method

type Method string

Method is how a sign-in's second factor was given.

const (
	MethodAuthenticator Method = "authenticator"
	MethodRecoveryCode  Method = "recovery_code"
)

type Service

type Service struct {
	Store Store

	// Policy is host policy as in force, startup overlay included.
	Policy interface {
		Load(ctx context.Context) (policy.Document, error)
	}
	Clock clock.Clock

	// Issuer names this installation in an authenticator app, beside the
	// account's username: "Pando (pando.example.com)".
	Issuer string
}

Service is a local account's second factor (R-405). It decides nothing about who may change whose: the caller has already, and audits what it did.

func (*Service) Begin

func (s *Service) Begin(ctx context.Context, userID, username string) (Enrollment, error)

Begin makes a new authenticator secret for an account and keeps it pending until Confirm sees a code from it. Replaces any pending one. The one in use, if any, stays in use until then, so starting over never locks anyone out.

func (*Service) Confirm

func (s *Service) Confirm(ctx context.Context, userID, presented string) ([]string, error)

Confirm checks a code from the pending authenticator and, if it is right, puts the authenticator in use with a fresh set of recovery codes, which are returned to be shown once and never again.

func (*Service) Decline

func (s *Service) Decline(ctx context.Context, userID string) error

Decline records that the holder chose not to set one up when asked, so they are not asked again. Refused where policy requires one.

func (*Service) NewRecoveryCodes

func (s *Service) NewRecoveryCodes(ctx context.Context, userID string) ([]string, error)

NewRecoveryCodes replaces an account's recovery codes with a fresh set.

func (*Service) Required

func (s *Service) Required(ctx context.Context) (bool, error)

Required says whether host policy requires a second factor on every local account.

func (*Service) Reset

func (s *Service) Reset(ctx context.Context, userID string) (bool, error)

Reset removes an account's second factor at an administrator's asking, or from the host: someone who lost their authenticator and their recovery codes. They are asked to set it up again at the next sign-in, and must if policy requires it.

func (*Service) SetupPending

func (s *Service) SetupPending(ctx context.Context, user state.User) (bool, error)

SetupPending says a session of this account may do nothing but set up its second factor: a local account without one, where policy requires it. Read on every request a session makes, so the account's own row decides first and policy is read only for the accounts it could hold back.

func (*Service) Summarize

func (s *Service) Summarize(ctx context.Context, userID string) (Summary, error)

Summarize is an account's second factor for GET /me.

func (*Service) TurnOff

func (s *Service) TurnOff(ctx context.Context, userID string) (bool, error)

TurnOff removes an account's second factor at its holder's asking, which host policy may forbid.

func (*Service) Verify

func (s *Service) Verify(ctx context.Context, userID, presented string) (Method, error)

Verify checks a code given at sign-in: an authenticator code, good once, or an unused recovery code, which is then spent. A wrong one is AUTH_INVALID; counting it is the caller's (R-404's counts, R-405).

type Store

type Store interface {
	Status(ctx context.Context, userID string) (state.TwoFactorStatus, error)
	PutPending(ctx context.Context, userID string, v secret.Value) error
	Secrets(ctx context.Context, userID string) (current, pending secret.Value, err error)
	Enable(ctx context.Context, userID string, v secret.Value, lastStep int64, digests []string) error
	AcceptStep(ctx context.Context, userID string, step int64) (bool, error)
	UseRecoveryCode(ctx context.Context, userID, digest string) (bool, error)
	ReplaceRecoveryCodes(ctx context.Context, userID string, digests []string) error
	Disable(ctx context.Context, userID string, reoffer bool) (bool, error)
	MarkOffered(ctx context.Context, userID string) error
}

Store is where second factors are kept (state.TwoFactor).

type Summary

type Summary struct {
	Enabled bool `json:"enabled"`

	// Required says host policy requires a second factor on local accounts.
	Required bool `json:"required"`

	// SetupRequired is Required without one: the account can do nothing but
	// set it up.
	SetupRequired bool `json:"setup_required"`

	// Offer says to ask the holder to set one up: not required, not on, and
	// not asked before. Asked once.
	Offer bool `json:"offer"`

	RecoveryCodesRemaining int `json:"recovery_codes_remaining"`
}

Summary is an account's second factor as the account's holder sees it.

Jump to

Keyboard shortcuts

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