[SECURITY AUDIT] SSO login bypasses TOTP two-factor for accounts that have 2FA enabled #31
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: Medium
Confidence: Medium (may be an intentional trust-model decision — flagging for an explicit call)
Scope area: Admin login hardening / TOTP flow (audit area 1), auth transition overlap (area 2)
What
The local password login flow enforces TOTP:
logininserver/src/router/v1/auth/auth.controller.js:63-67checksneedsTotp(user)and refuses to issue a session until the second factor is verified. The SSO login flow does not perform this check.In
server/src/router/v1/auth/sso.controller.js,finishLogin(lines 141-157) resolves the linked identity and immediately mints a full session:There is no
if (user.totp_enabled)gate. An admin who has deliberately enabled TOTP, and who also has a Google/Discord/OIDC identity linked, can sign in through the SSO button and receive an identical fully-privileged session without presenting their authenticator code.Why it matters
Enabling 2FA is an explicit statement that a single factor is insufficient to access the account. SSO silently downgrades that: the effective strength of the account becomes the strength of the external IdP login (which may itself be single-factor). The user never consented to that downgrade and has no visibility into it. It also creates an asymmetry — the local path is hardened, an alternative path to the same session is not.
Where
server/src/router/v1/auth/sso.controller.js:141-157(finishLogin, no TOTP gate)server/src/router/v1/auth/auth.controller.js:63-67(local path gates onneedsTotp)Suggested fix (not implemented)
Decide the intended policy explicitly, then either:
finishLoginfor a user withtotp_enabled, issue the staged TOTP challenge (sessionService.createPartialSession) instead of a full session and route the browser through the existing/login/totpstep before setting the auth cookie.Given the app already invested in a staged TOTP challenge, wiring SSO through the same gate is the consistent choice.