Skip to main content

Command Palette

Search for a command to run...

How Authenticator Apps Generate Codes Without Internet

The surprising part about Google Authenticator and Microsoft Authenticator

Updated
•9 min read•View as Markdown
How Authenticator Apps Generate Codes Without Internet
B
An engineer figuring out one thing at a time!

Have you ever put your phone on Airplane Mode and noticed that Google Authenticator or Microsoft Authenticator can still generate a new 6-digit code every 30 seconds?

That raises a pretty interesting question:

If there is no internet, where is the code coming from?

There is no API request.

There is no SMS.

There is no server sending a new code to your phone.

The answer is a clever combination of a shared secret, the current time, and a cryptographic algorithm.

This mechanism is commonly known as TOTP (Time-Based One-Time Password).

Let's understand how it actually works.


What happens when you enable 2FA?

When you enable authenticator-based 2FA on a website or application, the server generates a secret key associated with your account.

You usually see this as a QR code during setup.

When you scan that QR code using Google Authenticator, Microsoft Authenticator, or another compatible app, the secret is stored inside the authenticator app.

So now two parties know the same secret:

Authentication Server
        |
        | Shared Secret
        |
        v
Authenticator App

This is the important foundation of the whole system.

The server has the secret.

Your phone has the same secret.


Your phone doesn't need the internet to generate the code

Once the setup is complete, the authenticator app already has everything it needs to generate a TOTP code.

It mainly needs:

  • The shared secret

  • The current time

  • The TOTP algorithm

So the basic idea looks like this:

Shared Secret + Current Time
            |
            v
       TOTP Algorithm
            |
            v
        6 Digit Code

The calculation happens locally on your phone.

There is no need to contact Google, Microsoft, or your company's authentication server every time the code changes.


So why does the code change every 30 seconds?

This is where the word Time Based in TOTP becomes important.

TOTP divides time into fixed intervals called time steps.

A common configuration uses a 30-second interval.

For example:

10:30:00 ───────── 10:30:29
              Code A

10:30:30 ───────── 10:30:59
              Code B

10:31:00 ───────── 10:31:29
              Code C

The code isn't being downloaded every 30 seconds.

Instead, the input to the calculation changes when the time window changes.

That produces a completely different code.


What happens mathematically?

At a high level, TOTP can be thought of as:

OTP = HMAC(secret, time_counter)

The actual standard involves a few more steps, but this simplified version is enough to understand the architecture.

The process looks roughly like this:

Current Unix Time
       |
       v
Time Counter
       |
       +---- Shared Secret
       |
       v
     HMAC
       |
       v
Dynamic Truncation
       |
       v
  6 Digit OTP

The important thing is that the same secret and the same time window produce the same result.


How does the server know the correct code?

This is the clever part.

Suppose your authenticator app displays:

532416

You enter that code during login.

The server doesn't need to ask your phone whether the code is correct.

It already has the same secret.

It also knows the current time.

So it independently performs the same calculation:

Server Secret
      +
Current Time Window
      |
      v
TOTP Calculation
      |
      v
Expected Code

The server then compares its expected code with the code you entered.

Your Code      = 532416
Server's Code  = 532416

Result         = Match

Authentication succeeds.

The important detail is that both sides calculated the code independently.

The server never had to send the code to your phone.


This is why Airplane Mode works

Now the original question becomes much easier to answer.

Your authenticator app already has:

  • The shared secret

  • The current time

  • The algorithm required to generate the code

So generating the code does not require an internet connection.

The network connection becomes necessary when you actually communicate with the authentication server.

For example:

Generating OTP

Phone
  |
  +-- Secret
  +-- Current Time
  |
  v
OTP Generated

No Internet Required

But during login:

Phone
  |
  +-- Username / Password
  +-- OTP
  |
  v
Authentication Server

Internet Required

This distinction is easy to miss.

Generating the code and submitting the code are two different operations.


Why does the server accept a code from an offline phone?

Because the server doesn't care whether your phone was online when it generated the code.

It only cares whether the code is mathematically correct for the current time window.

Think about it this way:

                 Same Secret
                     |
          +----------+----------+
          |                     |
          v                     v
       Phone                 Server
          |                     |
    Current Time          Current Time
          |                     |
          v                     v
        TOTP                  TOTP
          |                     |
          v                     v
       Code A                Code A

Both sides arrive at the same result.

That's the core idea behind TOTP.


What if the phone and server clocks are slightly different?

There is an interesting problem here.

Your phone's clock and the server's clock might not be perfectly synchronized.

If TOTP required both clocks to be identical down to the exact second, the system would be very fragile.

Implementations can therefore allow a small amount of clock drift by checking nearby time windows.

For example, a server may consider the current time window and a nearby previous or next window.

This gives the system some tolerance for small differences in device and server clocks.

However, if the device clock is significantly incorrect, authentication can fail.

That is why keeping your device time accurate is important.


Why can't you reuse an old code?

The code is tied to a specific time window.

For example:

10:30:00 - 10:30:29
        |
        v
     Code A

10:30:30 - 10:30:59
        |
        v
     Code B

Once the time window changes, the previous code should no longer be valid.

This makes TOTP useful as a second authentication factor.

Even if someone sees a code, it is only useful for a limited period.


Is the QR code itself the secret?

Not exactly.

The QR code is simply a convenient way to transfer the configuration information to your authenticator app.

One of the important pieces of that configuration is the shared secret.

After you scan the QR code, the authenticator app stores the necessary information.

You don't need the QR code again every time a new code is generated.


TOTP vs SMS based authentication

There is an important architectural difference between TOTP and SMS verification.

With SMS based authentication, the flow looks something like:

User requests OTP
       |
       v
Authentication Server
       |
       v
SMS Provider
       |
       v
User's Phone

The code has to travel through a network.

With TOTP, the architecture is different:

          Shared Secret
               |
       +-------+-------+
       |               |
       v               v
     Phone           Server
       |               |
 Current Time      Current Time
       |               |
       v               v
      TOTP            TOTP
       |               |
       v               v
     Code           Expected Code

The code doesn't need to be transmitted to the phone.

Both sides calculate it independently.

That is why TOTP can work without internet connectivity.


A simplified architecture

Let's put the complete flow together.

Step 1: Initial setup

Authentication Server
        |
        | Generates Secret
        v
      QR Code
        |
        v
Authenticator App
        |
        | Stores Secret
        v
      Ready

Step 2: Generate the code

Stored Secret
     +
Current Time
     |
     v
TOTP Algorithm
     |
     v
6 Digit Code

Step 3: User logs in

User
 |
 +-- Username / Password
 |
 +-- 6 Digit OTP
 |
 v
Authentication Server

Step 4: Server verifies

Stored Secret
     +
Current Time
     |
     v
TOTP Algorithm
     |
     v
Expected OTP
     |
     v
Compare
     |
     +---- Match ----> Authentication Successful
     |
     +---- No Match -> Authentication Failed

The interesting system design lesson

This is the part I find most interesting about authenticator apps.

At first, you might assume that the app needs to constantly communicate with the backend to get new codes.

But it doesn't.

The system only needs both sides to have:

  1. The same secret

  2. A reasonably synchronized concept of time

  3. The same deterministic algorithm

That's enough.

The phone can calculate the code locally.

The server can independently calculate what the code should be.

No polling.

No API request every 30 seconds.

No SMS.

No code being pushed to the device.

The system removes the network dependency from the code generation itself.


One important distinction

There is a difference between generating a TOTP code and other authenticator features.

TOTP codes can be generated offline because everything required for the calculation is already stored on the device.

However, features such as push-based sign-in approvals require communication with a server and therefore need network connectivity.

So when we say:

Authenticator apps work offline

we specifically mean the locally generated TOTP codes.


The whole idea in one line

If you remember only one thing from this article, remember this:

Same Secret
     +
Same Time Window
     +
Same Algorithm
     =
Same Code

Your phone doesn't receive the code.

The server doesn't send the code.

Both simply calculate it independently.

And that's why the little 6-digit number on your phone can keep changing every 30 seconds even when your phone is sitting in Airplane Mode.


Final Thoughts

What looks like a simple six-digit number is actually a nice example of practical cryptography and system design.

The clever part isn't that the phone can generate a random number.

The clever part is that two systems can independently calculate the same short-lived value without communicating with each other first.

A shared secret gives them a common starting point.

Time gives the value a limited lifetime.

The cryptographic algorithm makes the result difficult to predict without the secret.

And the lack of a network dependency makes the whole thing work even when your phone is offline.

Sometimes good system design is not about adding another API or another service.

It's about designing the system so that you don't need that API in the first place.

More from this blog

B

Bhavy Ladani | Blogs

22 posts

Practical articles that simplify JavaScript, React, browser internals, web security, and AI engineering. Every article focuses on helping developers understand what actually happens behind the scenes.