userdb

package
v0.0.7 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2024 License: GPL-3.0 Imports: 14 Imported by: 0

README

Userdb Configuration

Configuration of the user database in smol/idp is managed via YAML-encoded objects. Multiple backend types are supported, each with its own configuration.

Generally speaking a userdb configuration looks like this:

type: "<backend-type>"
params: {...}

Where params holds backend-specific configuration parameters.

Backends

Note that smol/idp does not offer an API to create or delete users, or otherwise modify parameters which aren't strictly authentication-related. This is considered the responsibility of your application layer.

static - Static user database

The static userdb backend is useful when your user database is provisioned and managed by an external system (e.g. via configuration management). It is read-only.

The user list should be specified as the users attribute of params. Each user object can have the following attributes:

  • name - Username (and user ID).
  • email - Email address.
  • password - Encrypted password.
  • totp_secret - TOTP secret.
  • groups - List of groups the user is a member of.
  • webauthn_registrations - List of WebAuthN registrations. Each registration must have key_handle, public_key and an optional comment attributes.
  • app_specific_passwords - List of application-specific passwords for non-interactive, non-OIDC services. Each object should have id, service, password and optional comment attributes.

As a convenience, it is possible to ensure that all users from this backend are members of a set of fixed groups, by specifying the static_groups attribute in params.

sql - Generic SQL user database

The sql userdb backend can talk to a supported SQL database, using configurable queries that can be adapted to (almost) arbitrary schemas. Use it to connect to an externally managed database, e.g. your main application's. This allows integration of the authentication layer with existing business logic.

The following params are understood:

  • driver - Database driver (according to Go's database/sql). Only sqlite3 is supported, and is also the default.
  • dburi - Database URI. For sqlite3 this is the database path.
  • queries - Map of SQL queries.
SQL schema

The SQL backend does not manage the database schema in any way, it is best thought of as a client to an existing database. But a simple SQL schema for testing purposes is provided for reference in backend/sql/defaults.go.

SQL query configuration

The set of default SQL queries used by the backend can be examined in backend/sql/defaults.go. These can be individually overridden, in the queries configuration parameter, with anything that returns the same columns in the same order and accept the same query parameters. Query parameters are named (recognizable by the syntax :param), so their order does not matter.

chain - Concatenate backends

The chain userdb backend lets you combine multiple backends, in sequence. The only accepted configuration parameter is backends, a list of further userdb backend configurations.

rpc - Remote access over GRPC

The rpc userdb backend can access the user database over a GRPC API, defined in account/proto/account.proto as the Account GRPC service. This solution can be useful for splitting out compute and storage elements of the service architecture.

The Account server is a reference implementation of a server for this API, exposing a userdb backend.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound is returned by GetUser when a user is not in the db.
	ErrNotFound = errors.New("not found")

	// ErrReadOnly implies that the backend can't be modified.
	ErrReadOnly = errors.New("read-only backend")
)
View Source
var PasswordHasher = passwap.NewSwapper(
	argon2.NewArgon2id(argon2.RecommendedIDParams),
)

Default password hasher.

Functions

func Register

func Register(name string, f func(*yaml.Node, string) (Backend, error))

Types

type AuthLogContextFunc

type AuthLogContextFunc func(context.Context) (*authpb.Log, error)

type Backend

type Backend interface {
	Close()

	GetUserByID(context.Context, string) (*User, error)
	GetUserByName(context.Context, string) (*User, error)
}

Backend provides access to the user database with a transactional API. The transaction is always scoped to a specific user, so it is "hidden" in the User object.

func New

func New(spec *Spec, configPath string) (Backend, error)

func NewChainBackend

func NewChainBackend(backends []Backend) Backend

func WithAudit

func WithAudit(b Backend, client apb.AuditClient, ctxFn AuthLogContextFunc) Backend

WithAudit wraps a Backend with audit logging of all changes to user data.

type ReadOnlyTx

type ReadOnlyTx struct{}

ReadOnlyTx is an implementation of Tx that always returns ErrReadOnly.

func (*ReadOnlyTx) AddEncryptedAppSpecificPassword

func (*ReadOnlyTx) AddEncryptedAppSpecificPassword(_ *pb.AppSpecificPassword) error

func (*ReadOnlyTx) AddEncryptedRecoveryToken

func (*ReadOnlyTx) AddEncryptedRecoveryToken(_ *pb.RecoveryToken) error

func (*ReadOnlyTx) AddVerificationToken

func (*ReadOnlyTx) AddVerificationToken(_ *pb.VerificationToken) error

func (*ReadOnlyTx) AddWebAuthnRegistration

func (*ReadOnlyTx) AddWebAuthnRegistration(_ *pb.WebAuthnRegistration) error

func (*ReadOnlyTx) Commit

func (*ReadOnlyTx) Commit() error

func (*ReadOnlyTx) DeleteAppSpecificPassword

func (*ReadOnlyTx) DeleteAppSpecificPassword(_ *pb.AppSpecificPassword) error

func (*ReadOnlyTx) DeleteRecoveryToken

func (*ReadOnlyTx) DeleteRecoveryToken(_ *pb.RecoveryToken) error

func (*ReadOnlyTx) DeleteTOTPSecret

func (*ReadOnlyTx) DeleteTOTPSecret() error

func (*ReadOnlyTx) DeleteVerificationToken

func (*ReadOnlyTx) DeleteVerificationToken(_ *pb.VerificationToken) error

func (*ReadOnlyTx) DeleteWebAuthnRegistration

func (*ReadOnlyTx) DeleteWebAuthnRegistration(_ *pb.WebAuthnRegistration) error

func (*ReadOnlyTx) GetVerificationToken

func (*ReadOnlyTx) GetVerificationToken(_ string, _ string) (*pb.VerificationToken, error)

func (*ReadOnlyTx) Rollback

func (*ReadOnlyTx) Rollback() error

func (*ReadOnlyTx) SetEncryptedPrimaryPassword

func (*ReadOnlyTx) SetEncryptedPrimaryPassword(string) error

func (*ReadOnlyTx) SetTOTPSecret

func (*ReadOnlyTx) SetTOTPSecret(string) error

func (*ReadOnlyTx) SetUserInfo

func (*ReadOnlyTx) SetUserInfo(_ *pb.UserInfo) error

func (*ReadOnlyTx) UpdateAppSpecificPassword

func (*ReadOnlyTx) UpdateAppSpecificPassword(_ *pb.AppSpecificPassword) error

func (*ReadOnlyTx) UpdateWebAuthnRegistration

func (*ReadOnlyTx) UpdateWebAuthnRegistration(_ *pb.WebAuthnRegistration) error

type Spec

type Spec struct {
	Type   string    `yaml:"type" doc:"backend type"`
	Params yaml.Node `yaml:"params" doc:"backend-specific configuration"`
}

Spec configures a userdb backend. Parameters are type-specific, their parsing deferred to the backend constructors.

type Tx

type Tx interface {
	Commit() error
	Rollback() error

	SetEncryptedPrimaryPassword(string) error

	SetTOTPSecret(string) error
	DeleteTOTPSecret() error

	AddEncryptedRecoveryToken(*pb.RecoveryToken) error
	DeleteRecoveryToken(*pb.RecoveryToken) error

	AddEncryptedAppSpecificPassword(*pb.AppSpecificPassword) error
	UpdateAppSpecificPassword(*pb.AppSpecificPassword) error
	DeleteAppSpecificPassword(*pb.AppSpecificPassword) error

	AddWebAuthnRegistration(*pb.WebAuthnRegistration) error
	UpdateWebAuthnRegistration(*pb.WebAuthnRegistration) error
	DeleteWebAuthnRegistration(*pb.WebAuthnRegistration) error

	SetUserInfo(*pb.UserInfo) error

	GetVerificationToken(string, string) (*pb.VerificationToken, error)
	AddVerificationToken(*pb.VerificationToken) error
	DeleteVerificationToken(*pb.VerificationToken) error
}

Tx is the transactional write API to the user database. Note that after calling these methods, the outer User object will not be updated to reflect the changes. The Tx object embeds the user identity.

This interface only accepts encrypted credentials (the various AddEncrypted* methods). The User type wraps this with an API that accepts cleartext secrets and encrypts them, with matching methods lacking the 'Encrypted' part.

FIXME: this is a Context-wrapping API (mostly due to the semantics of the underlying database/sql.Tx) and this is bad.

type UnlockCredentials

type UnlockCredentials struct {
	AuthID   *pb.AuthenticatorID
	Password string
}

UnlockCredentials are used whenever we need to encrypt new credentials, in order for the API to eventually support password-derived encryption keys with transparent re-keying.

type User

type User struct {
	*pb.User

	Tx
}

User object. Fields are conceptually read-only: manipulation is delegated to the underlying Tx interface. There are specific methods for credential manipulation, to ensure that the user invariants are preserved: like the ability to decrypt the user encryption key when changing passwords, etc.

func (*User) AddAppSpecificPassword

func (u *User) AddAppSpecificPassword(unlock *UnlockCredentials, password, service, name string) error

AddAppSpecificPassword overrides the low-level method to manage encryption keys.

func (*User) AddRecoveryToken

func (u *User) AddRecoveryToken(unlock *UnlockCredentials, tokenType pb.RecoveryToken_Type, id, token string, expiry time.Time) error

AddRecoveryToken overrides the low-level method to manage encryption keys.

func (*User) DisableSecondFactorAuth

func (u *User) DisableSecondFactorAuth() error

func (*User) SetPrimaryPassword

func (u *User) SetPrimaryPassword(unlock *UnlockCredentials, password string) error

Directories

Path Synopsis
backend
all
rpc
sql

Jump to

Keyboard shortcuts

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