How do I implement passwordless login in a web app?
Short answer
You implement passwordless login by replacing the password with something the person has: a passkey, a one-time link or code sent by email or SMS, or an existing Google or Apple account. Passkeys are the only common method that resists phishing, so offer them first and keep an email link or code as the fallback. With loginos you get passkeys with a password fallback, but no email or social login.
You want people to sign in without a password, so there is nothing to forget, reuse or leak. Passwordless login does that by checking something else: that the person holds a device, an inbox or a phone number. The methods differ in how well they resist phishing, how often messages fail to arrive, and how people get back in after losing access.
For most web apps today, the setup that works best is passkeys first, with an email link or code as the fallback.
What are the passwordless options?
Web apps use four common methods:
- A magic link is a sign-in link that works once, sent by email.
- A one-time code is a short code sent by email or SMS, which the person types in.
- A passkey is a key pair kept by the person’s device or password manager and checked with WebAuthn, the browser’s Web Authentication API.
- Social login signs people in with an account they already have, like Google, Apple, GitHub or Microsoft, through OpenID Connect or OAuth.
| Method | Resists phishing | Watch out for | Recovery |
|---|---|---|---|
| Magic link | No | Spam folders, delays, link scanners, links opened on another device | Built in: the inbox is the account |
| Email code | No | Spam folders, delays, codes relayed by a fake site | Built in |
| SMS code | No | SIM swaps, number porting, cost per message, SMS pumping fraud | Tied to the phone number |
| Passkey | Yes | Older devices, people who lose every device | Needs a second method |
| Social login | Depends on the provider | People without that account, lockouts by the provider | Through the provider |
Phishing. NIST’s digital identity guidelines, SP 800-63B-4 from July 2025, say that methods where people type a code are not phishing-resistant: a fake site can ask for the code and use it at once. They don’t accept email for authentication at all. Passkeys are phishing-resistant, because the browser only uses a passkey on the domain it belongs to.
Deliverability. Email can arrive late or land in spam. Some company mail filters open links to scan them, which can use up a link that works once. A magic link opened on a phone signs in the phone, not the laptop where the person started.
SIM swaps. In a SIM swap, an attacker talks a mobile carrier into moving someone’s number to a new SIM card, then receives their codes. NIST lists SMS as a restricted authenticator, asks services to watch for SIM changes and number porting, and requires an alternative method. Every text also costs money, and attackers abuse sign-in forms to send texts to numbers they earn from, which is called SMS pumping.
User experience. A passkey takes one touch or glance on a device that has one. Codes work across devices but mean switching apps and typing. Magic links skip the typing but send people to their inbox. Social login is one click for people who have that account.
Recovery. Email methods recover themselves, because the inbox is the account. Passkeys need a second way in for someone who loses every device, and that second way decides how secure the account really is.
Which setup should you use?
Passkeys first, with email as the fallback, suits most web apps:
- On the sign-in page, offer passkey autofill in the email field, plus a “Sign in with a passkey” button.
- For someone with no passkey on this device, send an email code or a magic link. One email can carry both.
- After that sign-in, offer to create a passkey right away. Automatic passkey creation in Chrome and Safari only follows a sign-in with a saved password, so ask with a normal prompt.
- Use the same email path for recovery, and let people keep more than one passkey.
- Leave SMS out unless your users lack email or smartphones. Add social login when most of your users already share one provider, like Google Workspace in a business app.
How do you build magic links and email codes?
Magic links and email codes both send a short-lived secret and then check it. The steps:
- Take the email address and always answer the same way, like “Check your inbox”, so the form doesn’t reveal who has an account.
- Make the secret: 32 random bytes for a link, or six random digits for a code. Store only a hash of it, with the account, an expiry a few minutes away and a used flag.
- Send it. A link should open a page with a “Sign in” button that posts the token, so mail scanners that open links don’t use it up.
- When the secret comes back, check the hash, the expiry and that it is unused. Mark it used, then start a fresh session.
- Limit requests per address and per IP, and limit wrong code attempts.
NIST’s rules for codes sent to a phone make a good baseline for email codes too: at least six random digits, valid for at most 10 minutes, accepted once, with a cap on failed tries.
You can also tie a link to the browser that asked for it, with a cookie. A leaked or forwarded link is then useless, but opening the email on a phone no longer works. A code avoids that trade-off.
How do you build passkey sign-in?
Passkey sign-in has more parts, but a library does the cryptography:
- Pick a maintained WebAuthn library, like SimpleWebAuthn for Node.js, py_webauthn for Python or go-webauthn for Go.
- After the first email sign-in, or at sign-up, create a passkey with
navigator.credentials.create(). Store its credential id, public key, signature counter, transports and backup flags. - On the sign-in page, call
navigator.credentials.get()withmediation: "conditional", so passkeys show up in autofill. - On your server, check the signature with the stored public key, plus the challenge, the origin and the RP ID (relying party ID), the domain the passkey belongs to.
- Send people without a passkey to the email path.
The full walk-through with code is in how to add passkeys to a website. The production details, like counters, backup flags and testing across password managers, are in how hard WebAuthn is to run yourself.
How loginos does it
loginos covers the passkey half of this setup, through standard OpenID Connect. People sign in on loginos.io with a passkey, using Face ID, a fingerprint or a security key, and Apple, Google, Microsoft or a password manager syncs it. The sign-in page offers passkey autofill, and people who prefer a password can use one. The passkeys belong to loginos.io, so they work on every domain of your platform.
The other half is missing, and you should know it up front. loginos sends no email yet, so it has no magic links, no email codes and no reset emails. It has no SMS codes and no social login either. If you need those, pick a service that has them, or build email sign-in yourself next to “Sign in with loginos” and let people link the two accounts.
To add loginos:
- Create a platform in the developer console and add your domains.
- Add the redirect and the callback from the quickstart. The flow uses
stateand PKCE, and your server exchanges the code. - Read
amrin the ID token:["hwk"]after a passkey and["pwd"]after a password. Your app can, for example, allow some actions only after a passkey sign-in.
Frequently asked questions
What is the difference between passwordless login and passkeys?
Passwordless login is any sign-in without a password. Passkeys are one way to do it, and the only common one that resists phishing. Magic links, one-time codes and social login are passwordless too.
Are magic links secure?
A magic link that works once, expires within minutes and needs a button press is a reasonable choice for many apps. It is only as safe as the person’s inbox, though: anyone who can read their email can sign in. NIST doesn’t accept email for authentication, because a mailbox is often protected by a password alone and mail can be intercepted.
Is SMS login safe enough?
For low-risk apps it can be. NIST SP 800-63B-4 lists SMS as a restricted authenticator because of SIM swaps and number porting, and asks services that use it to offer an alternative. If you send texts, protect the form against SMS pumping with rate limits.
Do passkeys count as two-factor authentication?
A passkey with user verification combines something you have, the device, with a fingerprint, face or PIN. Many providers treat it as multi-factor: Amazon Cognito can count it as MFA, and WorkOS skips the separate code after a passkey sign-in. Check your own compliance rules before you drop a second factor.
One account for every domain you run
loginos is an OpenID Connect provider with passkeys, a user pool shared by all of your domains, roles in every token, and account linking for the users you already have. Add your platform and its domains in a few minutes.
Keep reading
- PasskeysHow do I add passkeys to my website?To add passkeys, you use the WebAuthn browser API with a server library. Your server sends a random challenge, the browser calls navigator.credentials.create() to make a key pair, and you store the public key. To sign in, the browser signs a new challenge with navigator.credentials.get() and your server checks the signature. With loginos, passkeys live on loginos.io and need no WebAuthn code on your domains.7 min read
- PasskeysIs there a service that handles passkey login for me?Yes. Passkey add-ons such as Corbado Connect, the Hanko Passkey API and Bitwarden Passwordless.dev add passkeys to the login you already have, while full auth providers such as Auth0, Clerk, Stytch, Descope and Amazon Cognito run all of sign-in, passkeys included. Compare fallbacks, recovery, domains and data export first. With loginos, your app handles one OpenID Connect callback, and the ID token says whether a passkey was used.6 min read
- PasskeysHow hard is it to implement WebAuthn myself?The core is not hard: with a maintained library such as SimpleWebAuthn, registering and checking a passkey takes a day or two. The hard part is everything around it: choosing the RP ID, storing challenges and credentials, several passkeys per person, autofill, account recovery, fallbacks and testing across browsers and password managers. Plan for weeks, not days, or use a provider that has passkeys built in, like loginos.7 min read