API Reference macaw_auth v#0.4.1

Copy Markdown View Source

Modules

Authentication for Phoenix hosts: one contract, with a backend behind it.

What an app implements to decide what a user may do: one callback, authorize/3. It is the app's, not the backend's: a backend says who someone is, the app says what they may do. The app names its module

What a backend implements: who someone is, and their sessions. Nothing else. The plugs, hooks, steps, paths and the revocation push are Macaw.Auth's, the same for every backend, so a backend never reimplements them. And one check: check_config!/0, which the application calls at start, so a misconfigured backend refuses boot.

The conformance kit: what every Macaw.Auth.Backend must do, as tests a backend's author runs.

What a backend gives the conformance kit.

The LiveView side of Macaw.Auth

The native backend: users and sessions in the host's database, passwords checked by a chain of sources (local password hashes, LDAP directories), sign-in failures throttled.

The native backend's configuration, read once and parsed into structs, every fault named (exio's AuthConfig approach)

A fault in the native backend's configuration, named.

How Macaw.Auth.Native hashes passwords: a behavior with two implementations, Macaw.Auth.Native.Hasher.Bcrypt and Macaw.Auth.Native.Hasher.Argon2. Each library is an optional dependency, and each implementation is compiled only when its library is, so a host carries only the NIF it chose.

Argon2 (:argon2_elixir), compiled only when that library is loaded. The parameters are argon2_elixir's own settings (config :argon2_elixir, t_cost: 3, m_cost: 16, parallelism: 4, argon2_type: 2); a hash made with others is rehashed at sign-in.

Bcrypt (:bcrypt_elixir), compiled only when that library is loaded. The cost is bcrypt_elixir's own setting, config :bcrypt_elixir, log_rounds: 12; a hash made at another cost is rehashed at sign-in.

Just-in-time provisioning of directory users (ported from exio's External.resolve/2): a directory user signing in for the first time gets a macaw_auth_users row, with source the directory's name and no password, and at every later sign-in the directory's word replaces the row's roles and display name. The directory is the authority on who is in which group, so a user removed from an admin group loses the role at their next sign-in, not whenever someone remembers to edit the row.

A row of macaw_auth_recovery_codes: one unspent recovery code of a user's second factor (Macaw.Auth.Native.Totp).

The native backend's user commands as release entry points, for an app's <app>-ctl (macaw_host's generated script), on macaw_host's release protocol (Macaw.Host.Release)

Sealing at rest: what the native backend stores that must not be read back from the table (a TOTP secret) is sealed with AES-256-GCM, OTP's :crypto, under a key from the configuration (sealing_key:, Macaw.Auth.Native.Config).

The sealing key is missing, too short, or not the one a stored value was sealed with. The message names the fault, never the key.

A row of macaw_auth_sessions, the native backend's sessions, in the host's repo (mix macaw_auth.gen.migration writes the table's migration, separate from the users').

The native backend's sessions (ported from exio's Accounts.Sessions), in macaw_auth_sessions (Macaw.Auth.Native.SessionRecord).

Where Macaw.Auth.Native checks a password: a behavior, and the chain that tries the configured sources in order.

A directory as a sign-in source, over OTP's :eldap (no external LDAP library). Ported from exio's, the copy with the security fixes, plus macaw's allow_plaintext: false. The configuration is Macaw.Auth.Native.Source.Ldap.Config's

An LDAP source's configuration, validated with its defaults filled (ported from exio's and macaw's LdapSource), so a bad one is refused naming the source and the key: sources[nas].host: is required.

Escaping for values placed in LDAP distinguished names and search filters, so a username can never change a DN or widen a search. Ported from exio's, with two fixes.

RFC 4515 search filters as :eldap terms, built with the username as data. Ported from exio's parser, with one change in how the username gets in.

Local users: a macaw_auth_users row with a password hash.

Sign-in throttling for Macaw.Auth.Native.authenticate/2 (ported from exio's and macaw's Accounts.Throttle, which are the same mechanism).

The native backend's second factor: TOTP and recovery codes (ported from exio's and macaw's Accounts.Totp, which are the same rules), on the macaw_auth_users row and in macaw_auth_recovery_codes.

The user commands of mix macaw_auth.user and of the release entry points (Macaw.Auth.Native.Release), one implementation for both

A row of macaw_auth_users, the native backend's users, in the host's repo (mix macaw_auth.gen.migration writes the table's migration).

The request side of Macaw.Auth, for a Phoenix router.

One signed-in session, as every backend reports it.

Macaw.Auth.Native.Throttle as a model (spec/10 §7): the table of failures, shared by every sign-in in flight, and what each call does to it.

The signed-in user, as every backend reports it.

Mix Tasks

Writes the migrations that create the native backend's tables into the host's migrations, one file each

Runs an LDAP source's sign-in flow for a user without signing them in, and prints how each step went (connect, TLS, finding the DN, bind, attributes, groups, required group, roles), stopping at the first that failed

Administers the native backend's users, against the configured repo