1) User goes to BAD website and signs up.
2) BAD website says “We’ve sent you an email, please enter the 6-digit code! The email will come from GOOD, as they are our sign-in partner.”
3) BAD’s bots start a “Sign in with email one-time code” flow on the GOOD website using the user’s email.
4) GOOD sends a one-time login code email to the user’s email address.
5) The user is very likely to trust this email, because it’s from GOOD, and why would GOOD send it if it’s not a proper login?
6) User enters code into BAD’s website.
7) BAD uses code to login to GOOD’s website as the user. BAD now has full access to the user’s GOOD account.
This is why “email me a one-time code” is one of the worst authentication flows for phishing. It’s just so hard to stop users from making this mistake.
“Click a link in the email” is a tiny bit better because it takes the user straight to the GOOD website, and passing that link to BAD is more tedious and therefore more suspicious. However, if some popular email service suddenly decides your login emails or the login link within should be blocked, then suddenly many of your users cannot login.
Passkeys is the way to go. Password manager support for passkeys is getting really good. And I assure you, all passkeys being lost when a user loses their phone is far, far better than what’s been happening with passwords. I’d rather granny needs to visit the bank to get access to her account again, than someone phishes her and steals all her money.
"Click a link in the email" isn't much secure either for most part. You might end up following a link blindly which can lure you into revealing even more information
Passkeys aren't that great either cause almost everyone has to provide a account recovery flow which uses these same phishable methods.
The language in communication is probably the most important deterrent here, second to using signals in the flow to present more friction to the abuser. A simple check like presenting captcha like challenge to the user in case they are not authenticating from the same machine can go a long way to prevent these kind of attacks at scale
Migrations randomly fail, schema changes are a nightmare, and your team forgets how SQL works.
ORMs promise to abstract the database but end up being just another layer you have to fight when things go wrong.
Bit of context, I have background building authentication systems and almost all the time its built as just another feature even though its THE FEATURE which gates all other features.
Why not just use OpenSearch or ElasticSearch? The tool is already in the inventory; why use a screwdriver when a chisel is needed and available?
This is another one of those “when you have a hammer, everything looks like your thumb” stories.