Documentation
¶
Overview ¶
Package authsetup builds the instance's sign-in providers and keeps the live set of them — the ONE place a provider is constructed, whether the environment/config file or the Admin → Identity providers page asked for it.
Why this package exists ¶
Until v0.43.0 the admin page wrote `auth.<name>.*` settings rows that nothing read: the server built its drivers from FILEX_AUTH_DRIVERS and the config file only, once, at boot (release-candidate sweep, 2026-09-21). The page looked like it changed who could sign in and changed nothing — the worst kind of screen. The owner's decision: the page really manages sign-in, applied without a restart, and it can never lock the instance out.
The rules, in one place ¶
- One construction path: Build. server.go calls it for every provider the environment lists; Live calls it for every provider the page enabled.
- The environment wins, visibly. A provider the environment lists is built from the environment only; rows the page may hold under the same name are kept but not used, and the page shows the provider read-only with where it comes from (Live.EnvDefines, FromWords).
- Page providers are ADDED after the environment's, never in front of them: `local` stays the first password judge wherever the operator put it, so a directory that hangs never sits in front of the administrator's password.
- Password sign-in (`local`) and the recovery sign-in (the bootstrap administrator's break-glass, FILEX_AUTH_RECOVERY_LOGIN) are the environment's to decide and nobody else's. The page cannot add or remove either — see docs/SSO.md, "Why nothing on this page can lock you out".
- A page provider that cannot start is left out and says why; it never takes anything else down with it (assemble).
Index ¶
- Constants
- Variables
- func Build(ctx context.Context, store db.Store, name string, cfg map[string]any) (auth.Driver, error)
- func Canonical(name string) string
- func DraftConfig(s *Stored, draft map[string]any, box *secretbox.Box, opts Options) (map[string]any, error)
- func DriverConfig(s *Stored, box *secretbox.Box, opts Options) (map[string]any, bool, error)
- func EnsureAnchors(ctx context.Context, store db.Store, env []Entry, log *slog.Logger) error
- func EnvTrustEmail(ctx context.Context, store trustStore, explicit *bool) (trust, byUpgrade bool)
- func ForgetTrustUpgradeInstance(ctx context.Context, store trustStore, slug string)
- func ForgetTrustUpgradeTenant(ctx context.Context, store trustStore, id int64)
- func FromWords(from, lang string) string
- func IsManaged(name string) bool
- func IsOS(name string) bool
- func LoadStored(ctx context.Context, store db.Store) (map[string]*Stored, error)
- func PrimarySlug(slug, driver string) bool
- func RowConfigJSON(s *Stored) string
- func Save(ctx context.Context, store db.Store, next *Stored) error
- func SyncKeyPrefix(name string) string
- func TenantGuard(insecureAllowed bool) func(map[string]any)
- func UpgradeLegacy(ctx context.Context, store db.Store, box *secretbox.Box, log *slog.Logger) error
- func UpgradeOIDCTrust(ctx context.Context, store db.Store, log *slog.Logger) error
- func WithRecoveryLogin(loginDrvs []auth.LoginDriver, enabled bool, store db.Store) ([]auth.LoginDriver, bool)
- func WithSessionAuthenticator(enabled []auth.Driver, store db.Store) []auth.Driver
- type Bindings
- type Change
- type Directory
- type Entry
- type Field
- type FieldKind
- type Live
- func (l *Live) AdminPaths(ctx context.Context, without string) []string
- func (l *Live) AdminPathsIn(ctx context.Context, tenantID int64, exclude func(Entry) bool) []string
- func (l *Live) CanSync(name string) bool
- func (l *Live) Current() *Set
- func (l *Live) Dir() Directory
- func (l *Live) DirectoryFor(email string, tenant int64) (slug, label string, ok bool)
- func (l *Live) EnvDefines(name string) (Entry, bool)
- func (l *Live) Environment() []Entry
- func (l *Live) LastSync(ctx context.Context, name string) (*auth.DirectorySyncReport, error)
- func (l *Live) Login() auth.LoginDriver
- func (l *Live) LoginName() string
- func (l *Live) OIDC() auth.OIDCDriver
- func (l *Live) OnSwap(f func(*Set))
- func (l *Live) Options() Options
- func (l *Live) Reload(ctx context.Context) error
- func (l *Live) RunDirectorySync(ctx context.Context)
- func (l *Live) SSOChoices(ctx context.Context, p *model.Provider, tenantID int64, host string) []SSOChoice
- func (l *Live) SetProviderAlarm(f func(name, reason string))
- func (l *Live) Start(ctx context.Context)
- func (l *Live) StartSync(ctx context.Context, name, trigger string) error
- func (l *Live) SyncInterval(name string) time.Duration
- func (l *Live) SyncNow(ctx context.Context, name, trigger string) (*auth.DirectorySyncReport, error)
- func (l *Live) Syncing(name string) bool
- type Options
- type SSOChoice
- type Set
- func (s *Set) Bindings() *Bindings
- func (s *Set) Entry(name string) (Entry, bool)
- func (s *Set) For(tenantID int64) *View
- func (s *Set) HasDirectory() bool
- func (s *Set) MultiTenant() bool
- func (s *Set) Names() []string
- func (s *Set) PasswordLogin() bool
- func (s *Set) Recovery() bool
- func (s *Set) Serves(e Entry, tenantID int64) bool
- type Stored
- type TrustUpgrade
- type View
Constants ¶
const ( OriginEnvironment = "environment" OriginPage = "page" // OriginTenant: a tenant's administrator made it for their own tenant // (docs/TENANT-ADMIN.md). OriginTenant = "tenant" )
Where a provider's configuration comes from.
const ( // InstancesSetting records that the one-time upgrade below has run. InstancesSetting = "auth.instances.upgraded" // ReviewSetting asks the operator to review the bindings the upgrade made // (every provider bound to every tenant), until they dismiss it. ReviewSetting = "auth.instances.review_pending" )
const (
// OwnSSOKey names a tenant's own OIDC (its provider row) among its choices.
OwnSSOKey = "tenant"
)
const (
// SchemaSetting records that the one-time upgrade below has run.
SchemaSetting = "auth.providers.schema"
)
Settings keys. `auth.<name>.<field>` is the shape the page always wrote; two control keys sit beside the fields.
Variables ¶
var ErrNoDirectorySync = errors.New("this provider is not running or has no directory to sync")
ErrNoDirectorySync is a provider that is not running or cannot sync.
var ErrNoSSOForTenant = errors.New("oidc: no such sign-in for this realm")
ErrNoSSOForTenant answers a start whose tenant has no such OIDC, or a realm nobody has. One error for both, as the sign-in form answers one way.
var ErrOIDCOff = errors.New("OIDC is not configured")
ErrOIDCOff answers an OIDC flow when no OIDC provider is running.
var ErrPasswordSignInOff = errors.New("password sign-in is off")
ErrPasswordSignInOff answers a password sign-in when no driver takes one.
var ErrSecretKeyRequired = errors.New("a client secret or bind password is stored sealed, and that needs FILEX_SECRET_KEY")
ErrSecretKeyRequired: a secret was given and there is no FILEX_SECRET_KEY to seal it with. A secret is never stored in the clear.
var ErrSyncRunning = errors.New("a directory sync is already running")
ErrSyncRunning is a second run asked for while one is going.
var Managed = []string{"oidc", "ldap", "proxy-header", "windows", "pam"}
Managed lists the providers the admin page can configure, in the order they are added to the chain. `local` and `api-token` are not among them: password sign-in is the environment's to decide (see the package comment) and API tokens are always on.
var OSProviders = []string{"windows", "pam"}
OSProviders are the managed providers that sign people in with an account of the operating system filex runs on. They differ from the rest in two ways the page and the tests rely on: a first sign-in opens an account only when the operator says so (auto_create defaults to OFF, where every other provider defaults to ON), and switching one on needs a test that PASSED - never a confirmation over a failed one.
var Schema = map[string][]Field{ "oidc": { {Key: "issuer", Kind: FieldText, Required: true}, {Key: "client_id", Kind: FieldText, Required: true}, {Key: "client_secret", Kind: FieldSecret}, {Key: "redirect_url", Kind: FieldText}, {Key: "scopes", Kind: FieldText}, {Key: "role_claim", Kind: FieldText}, {Key: "admin_group", Kind: FieldText}, {Key: "auto_create", Kind: FieldBool, Default: "true"}, {Key: "allowed_groups", Kind: FieldText}, {Key: "trust_email", Kind: FieldBool, Default: "false"}, }, "ldap": { {Key: "url", Kind: FieldText, Required: true}, {Key: "base_dn", Kind: FieldText, Required: true}, {Key: "bind_dn", Kind: FieldText}, {Key: "bind_password", Kind: FieldSecret}, {Key: "user_filter", Kind: FieldText}, {Key: "email_attr", Kind: FieldText}, {Key: "email_domains", Kind: FieldText}, {Key: "start_tls", Kind: FieldBool}, {Key: "ca_file", Kind: FieldText}, {Key: "ca_pem", Kind: FieldMultiline}, {Key: "protocol_login", Kind: FieldBool, Default: "true"}, {Key: "auto_create", Kind: FieldBool, Default: "true"}, {Key: "allowed_groups", Kind: FieldText}, {Key: "group_attr", Kind: FieldText, Default: "memberOf"}, {Key: "group_filter", Kind: FieldText}, {Key: "group_base_dn", Kind: FieldText}, {Key: "sync_interval", Kind: FieldText}, {Key: "sync_filter", Kind: FieldText}, {Key: "sync_disable_missing", Kind: FieldBool}, {Key: "sync_groups", Kind: FieldBool, Default: "true"}, {Key: "sync_group_filter", Kind: FieldText}, {Key: "show_refusal_reason", Kind: FieldBool, Default: "false"}, }, "pam": { {Key: "pamtester_path", Kind: FieldText, Default: "/usr/bin/pamtester"}, {Key: "service", Kind: FieldText, Default: "filex"}, {Key: "use_sudo", Kind: FieldBool, Default: "true"}, {Key: "sudo_path", Kind: FieldText, Default: "/usr/bin/sudo"}, {Key: "timeout_seconds", Kind: FieldText, Default: "10"}, {Key: "max_concurrent", Kind: FieldText, Default: "4"}, {Key: "protocol_login", Kind: FieldBool, Default: "true"}, {Key: "email_domain", Kind: FieldText}, {Key: "auto_create", Kind: FieldBool, Default: "false"}, {Key: "allowed_groups", Kind: FieldText}, {Key: "show_refusal_reason", Kind: FieldBool, Default: "false"}, }, "proxy-header": { {Key: "trusted_proxies", Kind: FieldText, Required: true}, {Key: "header_user", Kind: FieldText}, {Key: "header_email", Kind: FieldText}, {Key: "header_name", Kind: FieldText}, {Key: "header_roles", Kind: FieldText}, {Key: "admin_role", Kind: FieldText}, {Key: "auto_provision", Kind: FieldBool}, {Key: "auto_create", Kind: FieldBool, Default: "true"}, {Key: "allowed_groups", Kind: FieldText}, }, "windows": { {Key: "auto_create", Kind: FieldBool, Default: "false"}, {Key: "allowed_groups", Kind: FieldText}, {Key: "domain", Kind: FieldText}, {Key: "protocol_login", Kind: FieldBool, Default: "true"}, {Key: "show_refusal_reason", Kind: FieldBool, Default: "false"}, }, }
Schema is every field the page may store per provider. A key outside it is dropped on save: the settings table is not a scratchpad, and an unknown key is either a typo or a client that means something this server does not do.
var TenantDrivers = []string{"oidc", "ldap"}
TenantDrivers are the kinds a tenant's administrator may add for their own tenant: an OIDC and an LDAP. The operating-system providers and the header proxy are the platform operator's alone.
Functions ¶
func Build ¶
func Build(ctx context.Context, store db.Store, name string, cfg map[string]any) (auth.Driver, error)
Build constructs and initialises ONE sign-in provider from a configuration map (the keys the driver's Init reads).
⚠⚠ The single construction path. The environment/config file (server.go) and the admin page (Live.Reload) both come here, so a provider configured on the page is exactly the driver the same values in the environment would have produced — no second, subtly different path. A caller that needs a retry (the environment's OIDC, whose IdP often boots alongside filex) wraps this call; it does not grow its own construction.
func Canonical ¶
Canonical returns the name a provider is known by. The environment has always accepted a few spellings of the header driver; the page and the wire use one.
func DraftConfig ¶
func DraftConfig(s *Stored, draft map[string]any, box *secretbox.Box, opts Options) (map[string]any, error)
DraftConfig is the configuration "Test now" checks: what is stored with the form's unsaved values laid over it. A secret the form left blank, or sent back as "***", is the stored one — opened for the test, never returned.
func DriverConfig ¶
DriverConfig turns stored rows into the map the driver's Init reads — secrets opened, booleans as booleans, defaults filled — plus whether a directory provider (LDAP, Windows) also judges passwords on the file protocols.
⚠ The opened map lives in memory only, for the length of a build or a test. It is never logged and never sent anywhere but the driver.
func EnsureAnchors ¶ added in v0.50.0
EnsureAnchors makes sure every existing provider has its row, and binds a row it had to create:
- before the one-time upgrade (InstancesSetting unset): to the platform's own tenant AND to every tenant that exists now (source `upgrade`) - what happened before 0.50, where one LDAP served every tenant - and it asks the operator to review the bindings (ReviewSetting) when there are tenants to review;
- after it: to the platform's own tenant only (a provider added later serves nobody else until somebody binds it).
A pin (FILEX_LDAP_PROVIDER, FILEX_HEADER_PROVIDER) is an implicit binding to the pinned tenant (source `pin`), whenever it is read. Idempotent: run at every Start and Reload.
func EnvTrustEmail ¶ added in v0.50.0
EnvTrustEmail is the environment OIDC's trust: what FILEX_OIDC_TRUST_EMAIL (or the config file's trust_email) says when it says anything; otherwise the answer the upgrade to 0.50 took once - on when the database had accounts that came through SSO then - and off on a fresh install. byUpgrade reports that the upgrade's answer is the one in force, for the page.
func ForgetTrustUpgradeInstance ¶ added in v0.50.0
ForgetTrustUpgradeInstance: an instance's trust was saved by someone, so it is theirs now and the page stops saying the upgrade set it.
func ForgetTrustUpgradeTenant ¶ added in v0.50.0
ForgetTrustUpgradeTenant is ForgetTrustUpgradeInstance for a tenant's own OIDC on its row.
func FromWords ¶
FromWords says where an environment provider is defined, in the reader's language: config.Auth.DriversFrom is "FILEX_AUTH_DRIVERS", "file:<path>" or "default"; anything else is shown as it is.
The words are the server catalogue's (`server.auth_provider.from_*`), so a language pack's language reads them too — not the English half of a hard-coded en/tr pair.
func LoadStored ¶
LoadStored reads every managed provider's rows.
func PrimarySlug ¶ added in v0.50.0
PrimarySlug reports whether a slug names the first instance of a driver, whose configuration lives in the `auth.<driver>.*` settings rows.
func RowConfigJSON ¶ added in v0.50.0
RowConfigJSON is the inverse of StoredOfRow: what a row instance stores.
func Save ¶
Save writes a provider's next state. A save is a review: it clears the "saved before v0.43.0, never applied" mark.
func SyncKeyPrefix ¶ added in v0.52.0
SyncKeyPrefix is the prefix of every settings row an instance's directory sync keeps — what removing the instance removes.
func TenantGuard ¶ added in v0.50.0
TenantGuard is what a tenant's own instance is handed on top of its configuration (docs/TENANT-ADMIN.md, the owner's decision of 2026-10-01): `guarded` (the connection goes through internal/netguard, and an LDAP must be encrypted) unless the platform operator allowed the tenant insecure and internal-network providers, and never a file on the server (`ca_file`: a tenant pastes its CA as `ca_pem`).
func UpgradeLegacy ¶
UpgradeLegacy runs once per database: rows the page saved before v0.43.0 were never applied by any server, so turning them on now would switch on, on upgrade, a sign-in configuration an operator may have typed long ago and forgotten. Each such provider is imported SWITCHED OFF and marked "saved before this version, never applied" for the page to show; the operator reviews and enables it.
A secret among those rows is sealed with FILEX_SECRET_KEY. With no key it cannot be sealed, and it is not kept in the clear either: it is cleared (it was never used), the page shows it as not set, and the log says which provider and which field — never the value.
func UpgradeOIDCTrust ¶ added in v0.50.0
UpgradeOIDCTrust runs once, at the first start of 0.50 on a database that already had accounts (the mark migration 00079 wrote): trust ON for every OIDC that exists - the page's first one, every row instance (a tenant's own among them), every tenant's own OIDC on its row - recorded so the page can say the upgrade set it; and the environment OIDC's answer (EnvTrustEmail). Called before the environment's providers are built.
func WithRecoveryLogin ¶
func WithRecoveryLogin(loginDrvs []auth.LoginDriver, enabled bool, store db.Store) ([]auth.LoginDriver, bool)
WithRecoveryLogin appends the recovery sign-in driver when no enabled login driver is `local` and recovery is on, and reports whether it did.
The owner's ruling, 2026-09-14: on an installation that signs in through an identity provider alone, the administrator created at installation must still be able to sign in with a password — for recovery only. Without it an unreachable IdP, an expired client secret or a broken realm locks out the one person who can repair filex's side of it. local.RecoveryLogin accepts that account and no other, so password sign-in stays off for everyone else.
⚠ It is switched off by the environment only (FILEX_AUTH_RECOVERY_LOGIN): the admin page, which can break the identity provider it would recover from, can never switch off the way back.
It goes LAST: a directory driver in the list judges its own accounts first.
func WithSessionAuthenticator ¶
WithSessionAuthenticator makes sure something in the chain can turn a filex session back into a user, whichever login drivers are enabled.
⚠⚠ Issue #24. Every sign-in — a password, an LDAP bind, an OIDC callback — ends in the same sessions row and the same `filex_session` cookie, but only the `local` driver's Authenticate reads that row: OIDC's and LDAP's answer "unauthorized" by design. With `FILEX_AUTH_DRIVERS=oidc` the callback minted a session the very next request refused, so nobody could sign in and every open session died on the restart that applied the setting.
The validator is not a LoginDriver, so it enables no password sign-in; and when `local` is already in the list it adds nothing, because that driver does the same lookup.
Types ¶
type Bindings ¶ added in v0.50.0
type Bindings struct {
// Main is the platform's own tenant (the supertenant), 0 when the install
// has none.
Main int64
// contains filtered or unexported fields
}
Bindings is which tenant signs in through which instance, as one reload read it.
func ReadBindings ¶ added in v0.50.0
ReadBindings reads the bindings and the tenants.
func (*Bindings) Bound ¶ added in v0.50.0
Bound reports whether a tenant signs in through an instance. An entry with no row (instance 0: `local`, or a provider built before its row existed) serves everybody, as every provider did before 0.50.
func (*Bindings) Insecure ¶ added in v0.50.0
Insecure reports whether a tenant's own providers may reach internal addresses and plain ldap:// (providers.allow_insecure_auth).
type Change ¶
Change is what a save asks for. Values holds the fields sent; a secret sent as "" or "***" keeps the stored one (the page never has it to send back).
type Directory ¶
type Directory interface {
VerifyPassword(ctx context.Context, identifier, password string) (*model.User, error)
}
Directory is an external password authority (protocolauth.Directory).
type Entry ¶
type Entry struct {
// Name is the DRIVER (oidc, ldap, pam, windows, proxy-header, local).
Name string
// Slug names the instance (auth_instances.slug): the driver's name for
// its first instance, so "the ldap" is still addressed as `ldap`.
Slug string
// InstanceID is the instance's row (auth_instances.id); 0 for `local`,
// which is not an instance, and for a provider built before its row
// existed. An entry with no row serves every tenant (Bindings.Bound).
InstanceID int64
// Label is what the sign-in page calls it ("" = the driver's words).
Label string
// Owner is the tenant a tenant's own instance belongs to (0 = none).
Owner int64
Origin string
// From says where an environment provider is defined
// (FILEX_AUTH_DRIVERS, the config file, the built-in default).
From string
// Driver is nil when the provider could not start; Err says why.
Driver auth.Driver
Err string
// Directory: an LDAP provider that also judges passwords on the file
// protocols (WebDAV, SFTP, FTPS, S3, NFS).
Directory bool
// Display is the configuration shown on the page for an environment
// provider — secrets left out (Secrets says which are set).
Display map[string]any
// Secrets names the secret fields an environment provider has set.
Secrets []string
// SetByUpgrade names the fields whose value the upgrade to 0.50 chose
// for an environment provider (trust_email, UpgradeOIDCTrust), for the
// page to say so.
SetByUpgrade []string
// contains filtered or unexported fields
}
Entry is one provider the instance knows of.
func NewEnvEntry ¶
func NewEnvEntry(name, from string, cfg map[string]any, d auth.Driver, err error, directory bool) Entry
NewEnvEntry records a provider the environment/config file defines. cfg is what Build was given; the page is shown a copy with every secret removed.
type Field ¶
type Field struct {
Key string `json:"key"`
Kind FieldKind `json:"kind"`
Required bool `json:"required,omitempty"`
// Default is what an absent value means, said so the page can show it.
Default string `json:"default,omitempty"`
}
Field is one setting a managed provider takes on the page.
func TenantFields ¶ added in v0.50.0
TenantFields are the fields a tenant's administrator may set on their own OIDC or LDAP: the schema's, without the ones that name something on the server (`ca_file`).
type FieldKind ¶
type FieldKind string
FieldKind is how a page field is stored and handed to the driver.
type Live ¶
type Live struct {
// contains filtered or unexported fields
}
Live owns the running providers and swaps them when the page saves.
func New ¶
New prepares a Live over the environment's providers (already built by the caller through Build) and installs a first set holding only those, so the password sign-in the environment configured works before anything the page saved has been looked at.
func (*Live) AdminPaths ¶
AdminPaths lists the ways an administrator can still sign in with the running set, leaving out one provider (the one about to be switched off, named by its slug: the driver's name for its first instance).
- "password": password sign-in is on (`local`) and at least one enabled administrator has a password;
- "recovery": the bootstrap administrator's recovery sign-in is on, and that account exists, is enabled and has a password;
- the slug of every other running identity provider or directory.
⚠ An identity provider counts as a way in although filex cannot prove an administrator's account is on the other side of it: the rule this serves is "never switch off the LAST way in", and a provider that is running is a way in until shown otherwise. The two password paths are checked for real, because an instance whose administrators all came in through SSO has a password form nobody can use.
On a multi-tenant install this is the platform's own tenant's answer: the providers bound to it (AdminPathsIn).
func (*Live) AdminPathsIn ¶ added in v0.50.0
AdminPathsIn is AdminPaths for one tenant (docs/TENANT-ADMIN.md, "the last way in"): the providers bound to it that exclude does not leave out, and the password form for an enabled administrator OF THAT TENANT who has a password. Recovery is the platform's own tenant's only.
func (*Live) CanSync ¶ added in v0.52.0
CanSync reports whether a provider is running and can sync its directory.
func (*Live) DirectoryFor ¶ added in v0.52.0
DirectoryFor names the running LDAP instance that owns an address (its email_domains) — whose people arrive by sign-in and sync, so an account made by hand for that address would be a local one the directory could never sign in. ok is false when no directory claims it.
⚠ Only the directories that sign people in to tenant (0: the platform's own; Set.Serves): the account is made there, and another tenant's own directory is no business of the caller's - asked about every instance, a tenant's administrator was told another tenant's directory label.
func (*Live) EnvDefines ¶
EnvDefines reports whether the environment lists a provider — in which case it is the effective one, and the page may not change it.
func (*Live) Environment ¶
Environment is the environment's providers, in the order it listed them.
func (*Live) LastSync ¶ added in v0.52.0
LastSync returns a provider's last report, or nil when it never ran.
func (*Live) Login ¶
func (l *Live) Login() auth.LoginDriver
Login is the password sign-in the handlers hold. It always asks the running set, so a reload changes what it does without re-wiring anything.
func (*Live) Reload ¶
Reload reads the page's providers and swaps in the set they make.
⚠ A provider that did not change is not rebuilt (an OIDC discovery per save of an unrelated LDAP field would be a network round trip for nothing), and a provider that fails to start is left out with its reason — the environment's providers and every other page provider stay exactly as they were. There is no path through here that drops `local`.
It also brings the providers' rows up to date (EnsureAnchors: a provider saved since the last reload gets its row, bound to the platform's own tenant) and reads which tenant signs in through which (ReadBindings).
func (*Live) RunDirectorySync ¶ added in v0.52.0
RunDirectorySync runs every provider's directory sync on its interval until ctx ends: at each tick, a provider whose last run started an interval ago or more (or never ran) runs. Blocks — start it with go.
func (*Live) SSOChoices ¶ added in v0.50.0
func (l *Live) SSOChoices(ctx context.Context, p *model.Provider, tenantID int64, host string) []SSOChoice
SSOChoices lists the OIDC a tenant may sign in through, in order: its own (provider row) first, then the instances bound to it.
func (*Live) SetProviderAlarm ¶ added in v0.50.0
SetProviderAlarm registers what happens when an operating-system provider the admin page switched on cannot start: the provider is left out of the running set (every other way in keeps working) and the operator hears about it, once per distinct reason. A failure that happened before the alarm was registered (the boot, which builds providers before notifications exist) is raised now.
The reason is the driver's error text, which never holds a secret (Build's errors are about the configuration and the machine, not the values).
func (*Live) Start ¶
Start imports what an earlier version saved (switched off), builds the page's enabled providers and, when one could not start, keeps re-trying it in the background.
func (*Live) StartSync ¶ added in v0.52.0
StartSync claims a provider's sync and runs it in the background: the error is that it could not start (ErrNoDirectorySync, ErrSyncRunning); the run's own outcome is its report (LastSync).
func (*Live) SyncInterval ¶ added in v0.52.0
SyncInterval is a running provider's sync interval (0: none).
func (*Live) SyncNow ¶ added in v0.52.0
func (l *Live) SyncNow(ctx context.Context, name, trigger string) (*auth.DirectorySyncReport, error)
SyncNow runs a provider's directory sync and keeps its report. trigger is "manual" or "schedule". The run is detached from ctx's cancellation (a closed browser tab must not stop it half way) but bounded by syncTimeout.
type Options ¶
type Options struct {
Store db.Store
Box *secretbox.Box
MultiTenant bool
RecoveryLogin bool
PublicURL string
// LoginEmailToken is the installation's e-mail token (FILEX_OS_LOGIN_EMAIL_TOKEN):
// what follows the `@` of an account a provider knows only by login name.
// Environment only — never a page field: it is part of every such account's
// address, and changing it later makes a second account of the same person
// (identity.EmailToken).
LoginEmailToken string
// BuildTimeout bounds one page provider's construction (an OIDC
// discovery that hangs must not hold a save, or the boot, hostage).
BuildTimeout time.Duration
// RetryBackoff re-tries, after boot, a page provider that could not
// start — its IdP may be booting alongside filex.
RetryBackoff []time.Duration
Log *slog.Logger
}
Options is what Live needs from the server.
type SSOChoice ¶ added in v0.50.0
type SSOChoice struct {
// Key names it in /api/auth/oidc/start?instance=: the instance's slug, or
// OwnSSOKey for the tenant's own OIDC on its provider row.
Key string
Label string
// contains filtered or unexported fields
}
SSOChoice is one OIDC a tenant may sign in through.
type Set ¶
type Set struct {
Entries []Entry
// contains filtered or unexported fields
}
Set is one immutable arrangement of the providers. Live swaps whole sets, so a request never sees half of a reload.
func (*Set) Bindings ¶ added in v0.50.0
Bindings is which tenant signs in through which instance, as the reload that made this set read it (nil on a set built before any reload).
func (*Set) Entry ¶
Entry returns a provider by its slug: the driver's name for the first instance of a driver, so `ldap` is still "the LDAP".
func (*Set) For ¶ added in v0.50.0
For is a tenant's view. On a single-tenant install every tenant's view is the whole set. 0 is the platform's own tenant.
func (*Set) HasDirectory ¶
HasDirectory reports whether a directory judges passwords on the file protocols.
func (*Set) MultiTenant ¶ added in v0.50.0
MultiTenant reports whether the set arranges providers per tenant.
func (*Set) Names ¶
Names are the sign-in methods the login page offers: every provider the environment lists (as before) and every page provider that is running.
func (*Set) PasswordLogin ¶
PasswordLogin reports whether the password form is answered at all.
func (*Set) Recovery ¶
Recovery reports whether the bootstrap administrator's recovery sign-in is on.
func (*Set) Serves ¶ added in v0.52.0
Serves reports whether an entry signs people in to a tenant (0: the platform's own): always on an install with one tenant; on a multi-tenant one when it is bound to that tenant and, a tenant's own instance, it is that tenant's - the rule buildView arranges a tenant's sign-in by.
type Stored ¶
type Stored struct {
Name string
Enabled bool
// Legacy: saved before v0.43.0 and never applied — review and enable.
Legacy bool
// Values are the stored field values; a secret stays SEALED here.
Values map[string]string
// Exists: at least one row is stored for this provider.
Exists bool
}
Stored is what the settings table holds for one managed provider.
func Merge ¶
Merge applies a change to what is stored, without writing anything, and returns the next stored state plus the names of the fields that changed (never their values — this list goes into the audit row).
func StoredOfRow ¶ added in v0.50.0
func StoredOfRow(a *model.AuthInstance) (*Stored, error)
StoredOfRow reads a row instance's configuration (config_json: field → value, secrets sealed) as the Stored the page's primary instance reads from the settings rows, so DriverConfig builds both the same way.
type TrustUpgrade ¶ added in v0.50.0
type TrustUpgrade struct {
// Instances are page and row instances, by slug (`oidc` is the page's
// first OIDC).
Instances []string `json:"instances,omitempty"`
// Tenants are tenants whose own OIDC on their row got trust.
Tenants []int64 `json:"tenants,omitempty"`
}
TrustUpgrade is what the upgrade switched on: which providers' trust is still the value it set (until someone saves it).
func ReadTrustUpgrade ¶ added in v0.50.0
func ReadTrustUpgrade(ctx context.Context, store trustStore) TrustUpgrade
ReadTrustUpgrade is what the upgrade switched on, as still recorded.
func (TrustUpgrade) Instance ¶ added in v0.50.0
func (t TrustUpgrade) Instance(slug string) bool
Instance reports whether an instance's trust is the upgrade's.
func (TrustUpgrade) Tenant ¶ added in v0.50.0
func (t TrustUpgrade) Tenant(id int64) bool
Tenant reports whether a tenant's own OIDC's trust is the upgrade's.
type View ¶ added in v0.50.0
type View struct {
Tenant int64
// SSO are the running OIDC instances bound to the tenant, in the set's
// order (the environment's first).
SSO []Entry
// contains filtered or unexported fields
}
View is one tenant's arrangement of the providers bound to it: what a sign-in for that tenant is judged by.
func (*View) PasswordLogin ¶ added in v0.50.0
PasswordLogin reports whether a password sign-in for the tenant is answered at all.