Loading
Admin two-step verification (passkeys / authenticator app), and shows with several series
Summary
Two changes:
- Two-step verification for Admin. Admin now asks for a passkey or an authenticator app's code. An admin who has neither is walked through setting one up the first time they open Admin.
- Shows with several series. Season folders like
UK - Season 01orAll Stars - Season 02used to be merged into the show's own seasons. Each is now its own series. Also fixes episode thumbnails covering the episode title.
Two-step verification for Admin
- Methods: passkeys (Face ID / Touch ID, Windows Hello, Android, security keys) through .NET 10 Identity's built-in WebAuthn support, and 6-digit authenticator codes (TOTP, e.g. Apple Passwords, Google/Microsoft Authenticator, 1Password). A user can have both, and several passkeys.
- Scope: only Admin asks. A check lasts
AdminMfa:Hours(default 12) and applies however the admin signed in, including Google. Signing in itself is unchanged. - First-time setup: confirm the password, create a passkey or scan the QR code (the
otpauth://link opens Apple's Passwords app on iPhone/Mac), then save 10 one-time recovery codes. - Profile → Two-step verification: add/remove passkeys, turn the authenticator on/off, make new recovery codes. Removing a method or making new codes needs a recent check, so a stolen session can't swap in its own.
- Recovery: Admin → Users has Reset two-step for another user.
AdminMfa:Required = falselets a lone admin back in. - Brute force: wrong codes count toward the existing lockout (5 → 15 minutes), on top of the existing
authrate limit.
Implementation notes
- Where the check is kept: the time of the last check (and of a just-confirmed password) is stored as a claim in the sign-in cookie.
SecurityStampValidatorOptions.OnRefreshingPrincipalcopies it over when the cookie is rebuilt every minute, and the cookie is re-issued after anything that changes the security stamp. - Own authenticator flag: the authenticator uses its own
AppUser.AuthenticatorEnabled, not Identity'sTwoFactorEnabled. Setting the latter makesPasswordSignInAsyncrequire a code at every sign-in, which broke sign-in during testing. - Admin endpoints: guarded by an endpoint filter that returns 403 with
{ mfa: "setup" | "verify" }, which the page uses to show the setup or the check. - New dependency: QRCoder (MIT), which draws the authenticator QR code as an SVG
data:image, allowed by the existing CSP.
Shows with several series
- Season folders:
<series> - Season NN,<series> - SNNand<series> Season NNare now that series' seasons (Season.Series). - Loose files: files in the show's own folder whose name isn't the show's (
drag.race.espana.s01e01.mkvinRu Pauls Drag Race) get their own series too. - Show page: picks the series first, then its seasons. Play all and next/previous episode go series by series, starting with the show's own.
- Existing libraries: episodes are refiled from their path at the next scan, without re-reading the files.
- Thumbnails: episode frames now fill and crop to their column instead of drawing at full size over the title.
Migrations
TwoStepVerification: adds theAspNetUserPasskeystable (Identity schema version 3) and theAspNetUsers.AuthenticatorEnabledcolumn.ShowSeries: adds theSeasons.Seriescolumn (default"") and widens the unique index to(ShowId, Series, Number).
Neither rebuilds an existing table.
Deployment notes
- Settings: no settings changes are required.
AdminMfadefaults toRequired: true, Hours: 12. - Passkeys and the proxy: passkeys need the HTTPS address, and MediaRiffle must see requests as HTTPS behind the proxy. That means the proxy in
TrustedProxiesandX-Forwarded-Proto: httpsset on the HAProxy frontend. Authenticator codes work either way.
Testing
- Automated: 113 tests pass. New tests cover the check-time logic and its survival of the cookie refresh, the authenticator link/key/QR, and series parsing against real folder names.
- Manual, against a running server: authenticator setup end to end (codes generated per RFC 6238); the check surviving the one-minute security stamp refresh; recovery codes working once; removal needing a check; lockout after 5 wrong codes; sign-in unaffected by an enabled authenticator; passkey options returned correctly.
- Scan: a sample multi-series show split into the right series.
- Not tested yet: creating and using a passkey in a real browser, and the new show page and setup screens in a browser.