Authentication & sessions
Local auth and OAuth, TOTP MFA enforcement, password policy, lockout and rate limiting, and session lifecycle.
RedScribe controls who can sign in, how hard an attacker has to work to guess their way in, and how long a session stays valid. This page covers local accounts, OAuth sign-in, mandatory MFA, lockout behavior, and session handling, so you know exactly what’s enforced and what isn’t. See Encryption model for how the data itself is protected once someone’s signed in.
Local authentication
Section titled “Local authentication”Local accounts sign in with a username and password. There’s no open self-registration: every local account is created by an administrator, then the new user activates it through a single-use setup link, emailed to them, that expires after 24 hours. They set their own password at that point; nobody else ever sees or sets it for them.
Password policy
Section titled “Password policy”The password rules below are enforced on the server, regardless of what any client-side strength meter shows:
- 14 to 128 characters.
- Rejected if it’s too close to the account’s own username or email.
- Rejected if it’s a known common password, or entirely numeric.
- Checked against the Have I Been Pwned breach corpus. This uses k-anonymity, so only a 5-character hash prefix of the password ever leaves the instance, never the password itself. It’s on by default; turn it off for an air-gapped deployment with no outbound internet access.
A password-strength meter in the UI gives advisory feedback as you type, but it’s just a hint. The rules above are what actually gets enforced.
OAuth (Google / Microsoft)
Section titled “OAuth (Google / Microsoft)”You can enable Google or Microsoft sign-in alongside local accounts. It’s additive: turning OAuth on never disables local login.
RedScribe is single-tenant per instance, and that’s enforced in the sign-in flow itself, not just left to convention. You configure one allowed email domain, and every incoming Google or Microsoft sign-in is checked against it before anything else happens. An account outside that domain is turned away immediately, with no partial session created along the way.
Superadmin accounts are local-auth only, as a deliberate second layer of defense. Even if a pending invite somehow ended up assigned the Superadmin role before anyone claimed it, sign-in would still be refused, the same way an out-of-domain login is refused. The account-creation forms also refuse to pair the Superadmin role with an OAuth account in the first place. The only way to create a Superadmin is a one-time setup command run at install time, and it’s always a local account.
If OAuth ever gets disabled, or a pending invite needs a fallback before anyone claims it, a Superadmin can convert that account back to local auth from its detail page. That sends the same setup email a brand-new local account would get. OAuth accounts never have a local password on file and never go through the password rules above, until they’re converted.
Setup for each provider:
| Provider | Console | Redirect URI |
|---|---|---|
| console.cloud.google.com/apis/credentials, a “Web application” OAuth 2.0 Client ID | https://<your-domain>/accounts/social/google/login/callback/ |
|
| Microsoft | entra.microsoft.com → App registrations | https://<your-domain>/accounts/social/microsoft/login/callback/ |
For Microsoft, you can also pin sign-in to one specific Entra tenant, as a stricter check that applies alongside (not instead of) the allowed-domain check above.
Both providers always show the account picker on sign-in, rather than silently reusing whatever Google or Microsoft account is already logged into the browser. That matters because the allowed-domain check only runs after an account is picked, so this avoids a mismatch surprise for anyone signed into more than one account at once.
TOTP multi-factor authentication
Section titled “TOTP multi-factor authentication”Every local account must enroll in TOTP MFA (an authenticator app scanning a QR code, then confirming a code) the first time they sign in. There’s no way to skip enrollment. Whether MFA is also required to actually use the app, beyond just being enrolled, depends on two independent settings:
- The Superadmin role always requires it, no matter what else is set.
- Any other role can independently be marked as requiring it from Role Management.
- An instance-wide feature flag requires it for every local account at once. It’s on by default; only turn it off for a local or disposable dev/test instance.
OAuth accounts are exempt from all of this, since MFA there is the identity provider’s responsibility, not RedScribe’s.
If MFA is required for a given account, every page they visit redirects them to enrollment (if they’ve never confirmed a TOTP device) or to verification (if they have a device but haven’t entered a code yet this session), with only sign-in, sign-out, and a couple of internal endpoints exempted.
MFA verification throttling
Section titled “MFA verification throttling”Separately from the login lockout below, repeated wrong TOTP codes are rate-limited per account: by default, 5 wrong codes within a 30-second window trigger a short throttle. Both numbers are configurable if the defaults don’t suit your instance.
Login lockout & rate limiting
Section titled “Login lockout & rate limiting”Failed login attempts are tracked per username, and checked before the password is even verified, using a short-lived lock so two simultaneous login attempts against the same username can’t race past the threshold together.
Two different thresholds apply, depending on whether the account being targeted is a Superadmin:
| Non-Superadmin | Superadmin | |
|---|---|---|
| Threshold | 5 failed attempts, by default | 10 failed attempts, by default |
| Window | 24 hours | 60 seconds |
| Effect | Account locked for the full window | Rate-limited for the (much shorter) window |
Superadmin gets a lighter touch on purpose: locking out the one account that can fix things is itself an operational risk. The failure count only looks at attempts since the last successful login for that username, so a successful login resets the counter.
Per-IP lockout
Section titled “Per-IP lockout”The per-username lockout above catches someone hammering a single account. A separate lockout keyed to the source IP address catches the other shape of attack: one address working through many different usernames. It’s checked first, before the per-username rules, so a blocked address never reaches the username stage at all.
By default an IP is locked once it reaches 20 failed attempts — deliberately
higher than the per-username threshold, so a shared office connection or
NAT’d network isn’t locked out by a handful of people mistyping passwords.
The window starts at one hour and escalates: each further block’s worth
of failures from that address doubles the window, up to a 24-hour cap, so a
persistent attacker is held progressively longer while a one-off burst
clears quickly. Unlike the per-username counter, a successful sign-in does
not reset an IP’s history — otherwise an attacker rotating usernames could
slip in one valid login to wipe the slate. The block lifts on its own as
the failures age out of the window. The threshold, base window, and cap are
all configurable (see
IP_LOCKOUT_THRESHOLD and its
companions). A locked-out address is told too many attempts have come from
its network, rather than anything tied to a specific account.
The moment a lockout or rate-limit actually triggers, every active Superadmin gets an email naming the affected username, how many attempts failed, and the source IP. That’s an active alert, not something you’d only notice later by checking the audit log.
Session lifecycle
Section titled “Session lifecycle”- Fixed cap: a session is valid for at most 4 hours, no matter what, and this isn’t separately configurable.
- Idle timeout: 30 minutes of inactivity signs you out early, before the 4-hour cap, with a message explaining why. Thirty minutes is a common baseline for HIPAA’s automatic-logoff expectation, which requires the behavior but doesn’t mandate a specific interval; it’s configurable if your policy needs a different number.
- One active session per user: signing in successfully on a new device or browser ends every other session for that account. This only happens after MFA is satisfied where it’s required, so a login that’s still mid-MFA-challenge on one device doesn’t kick an already-authenticated session on another device.
Password reset & account setup links
Section titled “Password reset & account setup links”Both password-reset links and new-account setup links are single-use in practice: using either one to set a password changes the password hash the link is tied to, so the same link can’t be replayed afterward.
- Password reset links expire after 1 hour by default.
- New-account setup links (for both staff and client-portal accounts) are valid for a fixed 24 hours, not separately configurable.