TL;DR: Adding MFA to homegrown authentication improves sign-in assurance, but the operational risk shifts to factor enrollment, challenge expiry, retry handling, and secret storage, according to WorkOS. The control question is no longer whether MFA exists, but whether the surrounding identity workflow prevents reuse, exposure, and weak fallback paths.
NHIMG editorial — based on content published by WorkOS: How to add MFA to your homegrown auth using WorkOS
By the numbers:
- Only 20% have formal processes for offboarding and revoking API keys, and even fewer have procedures for rotating them.
- 71% of NHIs are not rotated within recommended time frames, increasing the risk of compromise over time.
- 96% of organisations store secrets outside of secrets managers in vulnerable locations including code, config files, and CI/CD tools.
Questions worth separating out
Q: How should security teams implement MFA in a homegrown authentication flow?
A: Start by making factor enrollment, challenge issuance, verification, and recovery server-side identity states, not ad hoc application logic.
Q: Why do SMS-based MFA flows create more risk than TOTP in custom auth systems?
A: SMS depends on a transport channel that can be intercepted through SIM swap, phishing, or malware, so it is weaker as a primary factor.
Q: What breaks when MFA challenges can be reused or remain valid too long?
A: The control stops being a one-time verification step and becomes a reusable token that attackers can replay or brute-force.
Practitioner guidance
- Prefer TOTP as the primary factor Use authenticator-app based TOTP for standard sign-in, and reserve SMS for recovery or exceptional enrolment paths.
- Enforce single-use, short-lived challenges Set strict expiry on every challenge, invalidate it immediately after successful verification, and block additional use of the same challenge ID.
- Protect MFA artefacts as sensitive identity state Store factor IDs, challenge IDs, and TOTP secrets server-side in encrypted storage, and keep them out of logs, browser code, and shared configuration.
What's in the full article
WorkOS's full guide covers the operational detail this post intentionally leaves for the source:
- Copy-paste Node.js examples for enrolling factors, creating challenges, and verifying codes.
- Implementation details for storing factor IDs and challenge IDs safely in your own database.
- Error-handling patterns for already-verified and expired challenges.
- Practical MFA integration snippets for Python, Go, Ruby, and other SDKs.
👉 Read WorkOS's guide to adding MFA to a homegrown authentication system →
Homegrown MFA integration: are your controls ready for rollout?
Explore further
Homegrown MFA is only as strong as the identity state behind it. The security control is not the challenge prompt, it is the governance around factor enrollment, expiry, replay, and storage. Once those states live inside application logic, the organisation owns the full lifecycle failure surface, from initial enrolment to reset and re-enrollment. Practitioners should treat MFA as an identity workflow with failure modes, not as a checkbox.
A few things that frame the scale:
- 80% of identity breaches involved compromised non-human identities such as service accounts and API keys, according to Ultimate Guide to NHIs.
- Only 5.7% of organisations have full visibility into their service accounts, which means most identity teams cannot confidently inventory the non-human side of their access surface.
A question worth separating out:
Q: How do you know if MFA is actually being enforced correctly?
A: You should see every sign-in path issuing, expiring, and consuming challenges exactly as designed, with failed attempts, resets, and re-enrollment events recorded in logs. If users can bypass the challenge, reuse an old code, or complete sign-in without a second factor, enforcement is failing.
👉 Read our full editorial: MFA for homegrown auth: what teams need to govern now