On this page
How to Choose an Authentication Method for Your App: A Decision Guide
Sessions, JWTs, OAuth, passkeys, magic links, or SSO — the six questions that decide your auth method, a comparison table, and the cases where each option is the wrong pick.
Quick answer
- Default to server-side sessions with a password and a second factor. It’s the option with the fewest ways to be wrong, and it gives you logout and instant revocation for free.
- Six questions decide it: who your users are, whether you need instant revocation, how many services verify the caller, whether there’s a mobile client, what compliance requires, and whether your users can be phished.
- JWTs earn their complexity when several services must verify a caller without a shared session store. Otherwise sessions are simpler and safer.
- Add OAuth when you want users to skip creating a password; add passkeys when phishing resistance is the priority.
- Never authenticate machines with user credentials — give each service its own scoped identity.
- The comparison table below is the reference; the questions above it are how you pick a row.
The six questions that decide this
Authentication choices get argued as preferences. They’re actually decided by constraints, and these six narrow the field faster than any feature list:
- Who are your users — consumers or companies? Companies often require their own identity provider, which means SAML or OIDC federation rather than a local password.
- Do you need to revoke a session instantly? “Log out everywhere after a password change” and “kill the session of a compromised account” are trivial with server-side sessions and require extra machinery with stateless tokens.
- How many services verify the caller? One app can share a session store. Five services that can’t reach each other’s sessions are the case JWTs were built for.
- Is there a mobile or native client? Cookies work in browsers; native apps need a token they can store securely in the platform keystore.
- Does anything require a second factor or a specific factor type? Compliance regimes and enterprise customers often mandate MFA and sometimes phishing-resistant MFA specifically.
- Can your users be phished? Anyone can, which is the argument for passkeys — the credential is bound to your origin and won’t be replayed on a lookalike domain.
Answer those and the shortlist is usually obvious. The table below is the reference for choosing between what’s left.
The realistic options, compared
| Server-side sessions | JWT | OAuth / OIDC | Passkeys (WebAuthn) | Magic link / email OTP | Enterprise SSO (SAML / OIDC) | |
|---|---|---|---|---|---|---|
| How it works | Opaque session ID in a cookie; state lives on the server | Signed token the client presents; state lives in the token | A provider authenticates the user and returns a token about them | Public-key credential bound to your domain, unlocked by the device | A single-use link or code proves control of an inbox | The customer’s IdP authenticates, your app consumes an assertion |
| Best for | A normal web app with a browser front end | Multiple services verifying a caller without shared state | Consumer apps that want fewer passwords | Phishing resistance, app-based sign-in, passwordless | Frictionless onboarding, low-stakes accounts | Selling to companies with existing identity systems |
| Revocation | Immediate — delete the session | Hard — you need a denylist or short expiry | Provider-dependent, plus your own session | Remove the credential from the account | Expiry is the only control, so keep it short | Depends on the IdP’s session |
| Complexity | Lowest | Medium, and easy to get wrong | Medium — redirects, state, token validation | Low for the flow, higher for recovery | Low | High — metadata, certificates, mapping |
| Main risk | Session fixation, CSRF | Signature verification mistakes, no expiry | Open redirect, unverified token audience | Account recovery after a lost device | Link interception and email account compromise | Mis-mapped attributes granting wrong access |
| Wrong when | You have several services that can’t share a session store | You only have one app and no revocation story | You need offline or machine-to-machine access | You haven’t designed account recovery | The account controls anything valuable | Your users are individuals, not organizations |
Read the last row first — every method here is correct for a set of constraints and a poor fit outside them.
Sessions versus JWTs, specifically
This is the most common fork, and it’s usually decided on popularity rather than requirements. Server-side sessions keep the truth on the server: the cookie holds an opaque identifier, and deleting the row ends the session immediately. That gives you logout, admin-forced logout, and password-change invalidation with no extra code.
JWTs move the truth into the token. Any service holding the signing key can verify a caller without a database lookup, which is genuinely valuable when services don’t share storage. The cost is that a token remains valid until it expires unless you maintain a revocation list — which is the state you were trying to avoid.
The practical rule: one app with a browser front end → sessions. Several services that must verify callers independently → JWTs, with short expiries and a refresh mechanism you’ve actually implemented. Whichever you choose, the mistakes cluster in the same places.
- JWT Security: Common Mistakes That Get Tokens Stolen — Algorithm confusion, missing expiry, and tokens in the wrong storage.
- What Is CSRF (Cross-Site Request Forgery)? — The attack cookie-based sessions require you to handle.
- Why Does My App Ignore SIGTERM (and How Do I Fix It)? — Why in-memory sessions vanish on every deploy.
Adding a provider: OAuth, OIDC, and passkeys
OAuth is not an authentication protocol — it’s a delegation protocol for access, and OpenID Connect layers identity on top. In practice you adopt it for one of two reasons: users don’t want another password, or you don’t want to store credentials, resets, and MFA enrollment yourself.
Passkeys are the other adoption path, and the case is different: they remove the phishing vector rather than the password. The credential is a key pair bound to your domain, so a credential stolen from a convincing lookalike site is useless. The design work is in recovery, not the login flow.
- What Is OAuth 2.0? — Authorization code flow, scopes, and where the trust actually lives.
- What Are Passkeys (and Should You Switch)? — WebAuthn credentials and what changes for your users.
- What Is Phishing-Resistant MFA? — Why SMS codes are better than nothing and worse than a passkey.
- What Is Open Redirect (and Why Do Phishers Love It)? — The flaw that auth redirect flows keep introducing.
- What Is Zero Trust Architecture? — The access philosophy that fits short-lived, scoped credentials.
Selling to companies: SSO changes the shape of the problem
If a customer’s IT department asks how their employees sign in, the answer needs to be their identity provider, not your password form. SAML and OIDC federation move authentication to the customer and hand you an assertion you map to a local account.
This is a sales-driven requirement rather than a technical preference, and it brings its own failure modes: attribute mapping that grants the wrong role, certificate rotation that breaks logins silently, and provisioning that never happens automatically. Budget for it once, not per customer.
- What Is a Non-Human Identity (NHI)? — The service accounts that sit alongside human ones.
- How to Automate API Key Rotation — Rotation as a scheduled job rather than a quarterly scramble.
- Authentication and Authorization for AI Builders — The full cluster, including the ownership checks that come after login.
Where this bites vibecoders
Ask an assistant for “add authentication” and the answer is shaped by frequency in its training data, which is JWT plus a password hash in a
userstable — regardless of whether you have one service or six, a mobile client, or any need to verify callers without shared state. The result usually works, which is the problem: you inherit a revocation gap (logout that doesn’t invalidate, sessions that outlive a password change) that you only notice during an incident, when you need to force someone out of their account and discover you can’t. The fix isn’t a different token format; it’s deciding the revocation story before choosing the method, and stating your constraints — number of services, client types, whether logout must be immediate — in the prompt rather than asking for “auth.”
Checklist
- Write down your constraints — users, clients, services, revocation, compliance — before picking a method.
- Default to server-side sessions for a single web app.
- Use JWTs only when several services must verify callers independently.
- Give tokens short expiries and implement the refresh path, or don’t use them.
- Hash passwords with a slow, salted algorithm; never store them reversibly.
- Put a rate limit and lockout on login, reset, and MFA endpoints.
- Design account recovery before enabling passkeys.
- Authenticate machines with their own scoped credentials, never a user session.
- Test the revocation path: change a password and confirm existing sessions die.
FAQ
Which authentication method should a new app start with?
Server-side sessions with a password and a second factor. Sessions give you logout, expiry, and instant revocation for free, the browser handles the credential transport, and there is no token format to get wrong. Reach for JWTs when multiple services need to verify a caller independently, and add OAuth when you want users to skip creating a password at all.
Do I need OAuth if I am not offering social login?
No, but you may want OpenID Connect for a different reason: it moves password handling to someone else. If you don’t want to store credentials, reset flows, and MFA enrollment yourself, delegating sign-in to a provider removes an entire category of risk. What you take on instead is dependency on that provider’s availability and a mapping between their identity and your user records.
Are passkeys ready for production?
Yes, as an additional option rather than a replacement. Every major browser and platform supports WebAuthn, and the flow is phishing-resistant by construction because the credential is bound to your domain. The practical caveats are account recovery — losing the device must not mean losing the account — and users who expect a password field to exist.
How should I authenticate API clients and service accounts?
Not with a user session. Use scoped credentials issued per consumer: an API key with a defined scope for a trusted server-to-server integration, or OAuth client credentials for a third party. Store them hashed where possible, rotate them on a schedule, and treat each one as a non-human identity with the minimum access its job requires.
Related topics
- What Are the Different Types of Authentication?
- Authentication and Authorization for AI Builders
- JWT Security: Common Mistakes That Get Tokens Stolen
- What Is OAuth 2.0?
- What Are Passkeys (and Should You Switch)?
- How to Design Authorization for Your App
- Session Cookies vs JWT: Which Should You Use?