Elyra
Elyra The coding agent e The native code editor Elyra Grove Native local development environment Askr The real server for Laravel & PHP Elyra Framework Rust + Svelte 5 framework for desktop apps Elyra Conductor Local project conductor Elyra SQL Server MySQL-compatible SQL server in Rust Elyra Félagi Agents as teammates on one board Elyra SQL Client Native desktop SQL workbench Elyra SQL Anywhere Replication-ready SQL engine Elyra Sjá SEO & GEO workspace for macOS Elyra DataGrid Server-driven data grid for Laravel
Start here
Concepts
Elyra
Two-factor authentication

Two-factor authentication

Built on Laravel Fortify — its TOTP implementation, recovery codes and QR payload — with Félagi's own pages around it.

Fortify's HTTP routes are switched off. It registers a /login of its own, and using its endpoints as well as our Livewire pages would leave two ways in, one of them untested.


When it is required

# FELAGI_2FA_REQUIRED=true
FELAGI_2FA_GRACE_DAYS=5

Unset means: required in production, nowhere else. A second factor on a developer's machine protects nothing and gets in the way of every test run, which is how people end up disabling it in a way that follows them into production.

Setting the variable overrides that in either direction — on in staging, off in production if somebody truly must. The security page in /system says which of the two is in force and why.

The grace period

Five days, counted from when an account begins — accepting an invitation, or registering. Not from when the requirement was switched on.

That distinction matters twice:

  • A new colleague can read an issue before being marched through an authenticator app. Being made to do it in the first thirty seconds is how the secret ends up in a note on somebody's desk.
  • Somebody who has been here a year does not get five fresh days because an administrator changed a setting this morning.

The grace is spent the moment a second factor is confirmed, and /system/security lists who has not enrolled and how long each of them has left.

Single sign-on satisfies it

Somebody who signed in through an identity provider that does MFA has already proved a second factor, and will never enrol here — a provider account has no password for a TOTP secret to protect.

That is checked before enrolment rather than through the session flag alone: an unenrolled account is sent to the enrolment page whatever the session says, so marking the session verified was not enough by itself.

Per provider, in case one is configured without MFA. See Single sign-on.


The allowlist

Addresses that do not have to prove a second factor — an office range, typically. Single addresses and CIDR ranges, both families.

It is a platform setting, in /system, not a workspace one. This is deliberate and it is the one place this feature departs from where it was asked for. Anybody can create a workspace, so a workspace-scoped allowlist would let any user switch off a security control by making a workspace of their own and allowing 0.0.0.0/0 in it. A control that turns off authentication belongs with whoever is accountable for the platform.

If the allowlist should live in /admin, the prerequisite is restricting who can create a workspace.

Two smaller decisions:

  • Behind a proxy, set TRUSTED_PROXIES. Without it the address Félagi sees is the proxy's, and allowlisting that exempts the entire internet. The security page shows the address it currently sees, so this is visible before anybody adds it.
  • The address is trusted, not the account. The same person from a café still proves who they are; the exemption is per request.
  • Last-matched is recorded, at most once a minute, so a range nobody uses any more can be spotted and removed rather than left open forever.

Enrolling

There are two ways in, and they run the same code.

Settings carries a two-factor panel, between the password form and the danger zone — both of those are about how you sign in, and turning on a protection is not a destructive act. This is the one that matters during the grace period: without it the only route to the setup screen was being stopped by the middleware, which meant nobody could act on the warning they had been given.

The panel is also there where two-factor is not required at all, so a team that wants it need not wait for production to ask.

/two-factor/setup is the same steps with the framing of a door rather than a preference — the screen somebody is held on once their grace runs out.

Both call App\Support\TwoFactor, so the rule about spending the grace cannot end up in only one of them.

Either way it asks for the password in the same step. Somebody with a hijacked session must not be able to attach their own authenticator.

Enrolment is not complete until a code has been entered. Fortify calls this confirmation, and without it somebody can scan a QR code they never test and lock themselves out of their own account. Recovery codes are shown before it is switched on, because afterwards is too late to be told to write them down.

The challenge

/two-factor/challenge, once per session. Codes are verified through Fortify's provider: TOTP has a window, a drift tolerance and a replay problem, and none of that is worth re-deriving.

A recovery code is spent on use. Otherwise it is a second password with none of the protections, written on a piece of paper.

Where the gate sits

RequireTwoFactor runs on the whole authenticated application rather than only at login, because a session established before the requirement was switched on has to meet it too — and can only be asked on its next request.

Three routes stay reachable: the two pages that resolve the requirement, and logout. Otherwise somebody would be held on a screen they cannot use.

A JSON request gets a 403 rather than a redirect to HTML it cannot read.


Not there yet

  • No enforcement per workspace. The requirement is platform-wide; a workspace cannot demand more than the platform does.
  • No trusted devices. The challenge is once per session, not once per device per thirty days.
  • No WebAuthn as a second factor. Passkeys exist in the starter kit as a way to sign in, not as a factor on top of a password.
  • No administrative reset. Somebody who loses both their device and their recovery codes needs a platform admin with database access.