Two-Factor Authentication
A password alone is a weak lock on a tool that can email your whole list. Broadcast supports a second sign-in step with an authenticator app, lets an administrator require it for everyone, and can hand sign-in over to Cloudflare Access entirely if the dashboard already sits behind it.
Three pieces, each usable on its own:
- Authenticator app (TOTP): each user enrols from their profile and signs in with a password plus a six-digit code. Works offline with 1Password, Google Authenticator, Authy, Microsoft Authenticator, or any app that scans a QR code.
- Enforcement: an installation-wide switch that makes two-factor mandatory, with a grace period so existing users are reminded before they are locked out.
- Cloudflare Access sign-in: users who reach the dashboard through a Cloudflare Access application are signed in automatically, with no Broadcast password and no code.
Note
None of this touches the API. Tokens keep working exactly as before, and requiring two-factor for users does not affect integrations or the SDKs.
Enrolling as a user
Open My Profile. The Two-factor authentication section shows whether it is on for your account.

- Click Set up.
- Scan the QR code with your authenticator app. If you cannot scan, type the key shown next to it into the app by hand.
- Enter the six-digit code the app now shows and click Enable two-factor authentication.

- Save the ten recovery codes that appear. They are shown once. Each one signs you in a single time if you lose your device. Copy codes puts them on your clipboard.

From the next sign-in on, Broadcast asks for a code after your password. Codes are valid for thirty seconds, with a little tolerance for a phone whose clock drifts. A code that has already been used is refused even inside that window.
Recovery codes
If your authenticator is gone, enter a recovery code in place of the six-digit code. Broadcast tells you how many remain. Generate a fresh set from My Profile → Manage at any time; doing so invalidates every code from the old set.
Turning it off
From My Profile → Manage, confirm with your current password and a live code. Both are required so that a session left open on a shared machine cannot quietly weaken the account.

Wrong codes
Wrong codes count against the same limit as wrong passwords. After five failures in a row the account is locked and shows as inactive. An administrator reactivates it with Activate User on the user’s page under Users, which also clears the failure count. Broadcast additionally limits how many codes one address can try per minute, so a wrong code retyped from a phone is fine but a script is not.
If a user is locked out
A user who has lost their device and used up their recovery codes cannot get in on their own. An administrator with user-management permission opens the user’s page under Users and chooses Reset Two-Factor from the actions menu. The user can then sign in with their password alone and enrol again.

Your own two-factor cannot be reset from that page; it is managed from your profile, with the password and code checks above.
If the administrator is locked out
The reset above needs someone who can sign in. When there is nobody, because the only administrator lost their authenticator and every recovery code, or because two-factor was made mandatory before anyone able to switch it off had enrolled, the way back is the command line on the server. On an automatic installation:
cd /opt/broadcast # Clear one user's authenticator and recovery codes. They sign in with their # password alone and can enrol again from their profile. ./broadcast.sh two_factor reset admin@example.com # Stop requiring two-factor for everyone. Users who already enrolled keep it. ./broadcast.sh two_factor disable_enforcement # See whether two-factor is required and who has it enabled. ./broadcast.sh two_factor status
Broadcast must be running, since the command works inside the app container. On a manual Docker installation, run the same tasks directly:
docker exec -it app bin/rails "two_factor:reset[admin@example.com]" docker exec -it app bin/rails two_factor:disable_enforcement docker exec -it app bin/rails two_factor:status
Warning
Anyone with a shell on the server can run these, which is as it should be: a person who controls the machine controls the database too. Treat server access with the same care as the administrator password. See CLI Reference for the other commands.
Requiring two-factor for everyone
Under Application → Security, tick Require two-factor authentication for all users and pick a grace period: enforce immediately, or give existing users 7, 14 or 30 days.

- During the grace period every user who has not enrolled sees a banner on each page naming the deadline, with a link to enrolment.

- Once the deadline passes, a user without two-factor is sent to enrolment on every request and can do nothing else in the dashboard until they finish. They can still sign out.
- The requirement applies to every user, administrators included. There is no exempt account.
- A grace period that is already running is never extended by saving the page again, so you can adjust other settings without moving the deadline.
The page also shows how many users have enrolled so far, which is worth checking a day or two before the deadline.
Warning
Before you enforce immediately, make sure at least one user with user-management permission has
enrolled. Enforcement is unconditional, and the only way past it from the dashboard is to enrol.
If you do lock everyone out, ./broadcast.sh two_factor disable_enforcement on the server
turns the requirement off again.
Cloudflare Access sign-in
Many teams already put internal tools behind Cloudflare Access, which is free for up to fifty users and handles one-time PINs, Google or Microsoft sign-in, and hardware keys. Broadcast can trust it: when a request arrives through your Access application, Cloudflare attaches a signed assertion naming the user, and Broadcast signs in the Broadcast user with that email. No password, and no authenticator code, because Cloudflare has already done the second factor.
Setting it up
- In the Cloudflare Zero Trust dashboard, create a self-hosted Access application for the dashboard’s hostname, with whatever policy your team needs.
- Note two values: your team domain (Settings → Custom Pages, in the form
yourteam.cloudflareaccess.com) and the application’s Audience (AUD) tag (Access → Applications → your application → Overview). - In Broadcast, under Application → Security → Cloudflare Access sign-in, tick Sign users in from Cloudflare Access, enter both values, and save.

- Open the Security page again through the Access application and click Check this request. Broadcast reports the email Cloudflare verified, or explains what was wrong with the assertion.
Users must exist in Broadcast with the same email address Cloudflare knows them by. Someone who passes Access but has no Broadcast user sees the normal login page with a note saying so; Broadcast does not create accounts from Access.
Locking the origin down
Cloudflare can only vouch for requests that actually pass through it. If the server is reachable directly by IP, or on another hostname, a visitor can skip Access and reach the password form. Two ways to close that:
- Publish the dashboard through a Cloudflare Tunnel, so the origin has no public inbound port at all. This is the recommended setup.
- Or allow inbound traffic only from Cloudflare’s IP ranges at the firewall.
Once the origin is closed, you can tick Disable password sign-in (Cloudflare Access only). The password form disappears and password sign-ins are refused, so Access becomes the only door. Broadcast only lets you turn this on from a request that itself came through Access, which prevents a typo in the audience tag from locking you out of your own installation.
Note
Cloudflare Access sign-in and two-factor enforcement work together. A user who signs in through Access skips the code even if enforcement is on, because Cloudflare performed the second factor. Anyone still signing in with a password is held to the requirement.
Which one should you use?
| Situation | Use |
|---|---|
| Any installation, any size | Authenticator app, enrolled per user |
| A team that must all have a second factor | Authenticator app plus enforcement |
| Dashboard already behind Cloudflare Access | Cloudflare Access sign-in, with the origin locked down |
| Clients who insist on their own identity provider | Cloudflare Access can federate to Google, Microsoft, Okta and others, then sign the user into Broadcast |
See also Users & Permissions for who can change these settings, and CLI Reference for the recovery commands.