In this article
November 19, 2025
November 19, 2025

One-Time Passwords (OTPs) explained: What they are, how they work, and when to use them

Everything you need to know about OTPs, from HOTP and TOTP internals to real-world pros and cons, plus how WorkOS can help you implement them cleanly.

One-time passwords (OTPs) have been around for decades, but they’ve become one of the most common authentication patterns in modern apps. From SMS codes to authenticator apps to email-based passcodes, OTPs show up everywhere, and developers are often the ones gluing all the pieces together.

This post breaks down OTPs from a builder’s perspective: how they work, the different types, where they help, where they hurt, and how they compare to alternatives like magic links. We’ll also look under the hood at HOTP and TOTP, and wrap up with how WorkOS makes implementing OTP-based login dead simple. Let’s dive right in.

What are OTPs?

A one-time password is a code that’s valid for exactly one login attempt. Unlike a static password, which can be reused indefinitely, OTPs expire either after use or after a short time window.OTPs typically are short numeric codes, like “123456”, but that’s just a UX choice. Under the hood, they’re cryptographically generated and verified using shared secrets, standard algorithms, and sometimes counters or timestamps. More on this later on.Developers choose OTPs for a few reasons:

  • They’re easy for users to understand.
  • They don’t require storing passwords.
  • They reduce damage from password leaks or phishing.

Types of OTPs

There are three big categories developers run into:

1. SMS OTPs

These are sent via text message and are probably the most widely used type.

Pros:

  • Users are familiar with the flow
  • No app required

Cons:

  • SMS delivery can be unreliable
  • Vulnerable to SIM swapping
  • Carrier delays introduce friction

2. Email OTPs

Often used as a lightweight alternative to passwords or as a second factor.

Pros:

  • Easy to implement
  • No dependency on phone numbers
  • Works anywhere email works

Cons:

  • Email delivery latency
  • Users may have multiple inboxes, spam filters, etc.

3. App-generated OTPs (HOTP/TOTP)

Codes generated locally by an authenticator app like Google Authenticator, 1Password, or Authy.

Pros:

  • No network requirement
  • Strong security—phishing-resistant when paired with proper UX
  • Fast and predictable

Cons:

  • Requires setup and onboarding
  • Users can lose access if they lose their device and don’t have backup codes

How OTPs work

Under the hood, OTP systems rely on three ingredients:

  1. A shared secret between the server and the client (or the client’s authenticator app).
  2. An algorithm that uses that secret to generate numeric codes.
  3. A validation step on the server that checks the OTP and ensures it hasn’t been reused.

This gives the server a way to verify a user without storing any reusable secret (like a password).

There are two standardized algorithms you’ll hear about most often: HOTP and TOTP.

HOTP vs TOTP

HOTP (HMAC-based One-Time Password)

HOTP uses a counter that increments with each new OTP.

  • The server maintains a counter.
  • The client increments its own counter when generating a new code.
  • Both sides compute the OTP using:
  
HMAC-SHA1(secret, counter)
  
  • They stay in sync as long as the counters stay aligned.

HOTP shine on situations where you don’t trust the local device clock, but on the downside, counter desynchronization can be a real issue.

TOTP (Time-based One-Time Password)

TOTP builds on HOTP but replaces the counter with the current timestamp.

  • The “counter” becomes (currentUnixTime / 30)
  • Codes rotate every 30 seconds
  • No server-side counter needed

This is what most authenticator apps use today.Pros:

  • Simple to implement
  • Very predictable
  • No sync issues

Cons:

  • Depends on the device clock being reasonably accurate

Example OTP Flow (TOTP)

Let’s walk through a typical TOTP flow, like what happens with Google Authenticator, Authy, or 1Password generating a code.

1. Enrollment (secret setup)

This happens once when the user sets up OTP authentication.

  1. Your server generates a random shared secret: base32("q3k7fz9bwo2...")
  2. The server stores the secret securely in its database.
  3. You deliver the secret to the user’s authenticator app (usually via a QR code with the otpauth:// format).
  4. The authenticator app saves the secret locally.

At this point, both the server and the device share the same secret.

2. OTP generation (on the user’s device)

This repeats every time the user wants to authenticate.

  1. The authenticator app reads the current Unix timestamp. Example: 1732051200
  2. It computes the time-step counter:
  
timestep = floor(timestamp / 30)
  

       3. It computes the OTP using TOTP:

  
HMAC(secret, timestep)
→ dynamic truncation → 6-digit code
  

       4. The app displays something like: “482911”

This code is valid only for 30 seconds.

3. OTP submission (user → server)

  1. The user enters the 6-digit OTP.
  2. The server fetches the user’s stored secret.
  3. The server computes the TOTP for:
    • the current timestep
    • one step before and after (to allow slight clock drift)
  4. Server checks:
    • Does the submitted code match?
    • Has this code already been used? (replay protection)
  5. If valid, the user is authenticated.

The server never stores a reusable password, just a secret used for generating ephemeral codes.

Important notes

  • Replay protection is crucial: Even if an OTP is correct, the server must ensure it hasn’t already been used within its validity window.
  • Clock drift handling: Allowing ±1 timestep ensures minor device time skews don’t ruin UX.
  • Secrets should never leave secure storage: Treat them like passwords; rotate them if compromised.
  • HOTP flows look similar, except “timestep” is replaced with an incrementing counter, which both sides must keep in sync.

How HOTP differs

TOTP and HOTP both rely on the same core ingredients:

  • a shared secret
  • an HMAC-based computation
  • server-side verification

But HOTP swaps out the timestamp for a counter.

Aspect TOTP HOTP
Input value Time-step (e.g., every 30s) Incrementing counter
Code lifetime ~30 seconds Valid until used (or invalidated)
Sync requirement Clocks must be roughly accurate Client/server counters must stay aligned
UX Code rotates automatically Code stays fixed until used

During enrollment, the server and client both initialize a counter (usually 0).

During OTP generation:

  • TOTP computes: HMAC(secret, floor(timestamp / 30))
  • HOTP computes: HMAC(secret, counter)

During verification:

  • TOTP: server computes for time windows (t-1, t, t+1)
  • HOTP: server computes for a range of counters (e.g., current, +1, +2) to allow for desync

After successful verification:

  • Server increments its counter
  • Client increments its counter on the next generation

Pros and cons of OTPs

Pros

  • No passwords to store: OTP-based systems eliminate the need to store long-lived secrets, which removes an entire category of risk around password hashing, breaches, and resets. It also simplifies your backend because you no longer have to manage password complexity rules or recovery flows.
  • Familiar user flow: Most users have already seen OTPs in banking apps, ecommerce, and onboarding flows, so the pattern usually feels straightforward. There’s much less explanation required compared to newer or more abstract authentication methods.
  • Reduces risk from credential leaks: Because OTPs are short-lived and single-use, an attacker can’t reuse a captured code after it expires or has already been consumed. This dramatically reduces the blast radius of intercepted credentials compared to passwords or API keys.
  • Works as either primary auth or MFA: OTPs are flexible: you can use them as the main login mechanism or as a step-up factor when a user performs something sensitive. This makes them a good fit for apps that need different authentication “tiers” without introducing entirely separate flows.
  • Easy to implement with a service: Modern services (like WorkOS Magic Auth) handle the gritty details such as code generation, expiration, delivery, and anti-abuse controls. That means you can ship a secure OTP flow quickly without building a full authentication system from scratch.

Cons

  • Delivery delays frustrate users: Email and SMS aren’t always immediate, and users tend to abandon flows when the OTP doesn’t arrive quickly. This delay creates support overhead and can make your login experience feel inconsistent.
  • SMS can be insecure: Although common, SMS is vulnerable to SIM swapping, carrier-level interception, and number recycling. It’s still suitable for many apps, but it’s not ideal if you need strong guarantees about identity.
  • Clock drift or counter sync issues (HOTP/TOTP): App-based OTPs rely on time or counters. If a user’s device clock is off or counters get out of sync, the correct code can appear “wrong,” leading to confusion and retries.
  • Users often mistype codes: Six-digit numbers look simple, but humans still mistype them—especially on small mobile keyboards. This can slow down onboarding or increase abandonment, particularly for first-time users.

OTPs vs. standard passwords

OTPs are fundamentally different from passwords:

Aspect OTPs Standard Passwords
Reuse One-time only Persistent
Storage No reusable secret Stored hash required
Phishing risk Lower, but not zero High
User friction Small but recurring Larger upfront but reused

OTPs cut out the mess of password storage, resets, strength requirements, and breach exposure. But they introduce new forms of friction: delivery delays, code entry, timeouts, etc.

OTPs vs. magic links

OTPs and magic links try to solve the same problem—letting users in without passwords—but they rely on slightly different trust models. With a magic link, the link is the credential. Clicking it is effectively saying: “My email inbox is secure, so you can trust this request.” In practice, authentication becomes only as secure as the user’s email account and the way your system handles that one-time URL.

OTPs sent over email lean on the same channel, but the user has to copy a code back into your app. That extra step gives you more control. You can evaluate the request before finalizing login, add risk checks, or combine the OTP with other signals. TOTP/HOTP take it a step further by moving trust to a shared secret on the user’s device, removing email from the equation entirely.

Magic links shine when friction is the enemy: desktop onboarding, quick invites, or “pick up where you left off” flows. The downside is that links can leak into logs, get opened on the wrong device, or be forwarded. OTPs aren’t perfect, but they provide more opportunities to sanity-check the login before issuing a session.

In practice, many products use both: magic links for quick entry, and OTPs—email or TOTP—for step-up checks or higher-risk situations.

Implementing OTPs with WorkOS

If you want OTP-style authentication without building all the edge cases yourself, Magic Auth makes it painless.

Magic Auth works by sending a unique, six-digit, one-time-use code to the user’s email inbox. If you are using AuthKit , the only thing you need to do is enable the feature in the WorkOS dashboard. If you’d prefer to build and manage your own authentication UI, you can do so via the AuthKit Magic Auth API.

When you use AuthKit, you don’t have to write any OTP logic or API calls yourself. AuthKit automatically:

  • Generates each OTP
  • Sends the OTP email
  • Validates the user’s input
  • Exchanges the valid code for an authenticated session

Each code expires after 10 minutes, and AuthKit takes care of the rate limiting and one-time-use enforcement behind the scenes.

No managing SMTP providers, no dealing with wrong clocks, no custom retry logic—just clean auth.

Wrapping up

OTPs remain a reliable, flexible option for passwordless authentication. They’re not perfect, but they’re familiar to users and straightforward for developers, especially when you use a platform that handles the hard parts.

If you want to roll out OTP login without wrestling with SMS gateways, custom email infrastructure, stateful code storage, or anti-abuse logic, WorkOS Magic Auth is an easy way to ship it fast.

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.