DEV Community

Cover image for Access token vs refresh token
kundan
kundan

Posted on

Access token vs refresh token

Refresh Token:-

A Refresh Token is a long-lived token used to generate new access tokens without login the user again.

Refresh tokens must be stored securely (server-side only)

Once the Refresh token is expire user must login again (re-authentication need).

Access tokens are short-lived token (15 minutes). When they expire, instead of making the user log in again, the app quietly uses the refresh token behind the scenes.

How refresh token works:-

The user login and gets both an access token and a refresh token
The app uses the access token to call APIs.
After 15 min the access token expires the API returns a 401 Unauthorized error.
The app sends the refresh token to the Authorization Server.
The Authorization Server returns a fresh access token.
The user never notices anything they stay logged in.

Analogy:-

Your office keycard expires every day at midnight. Instead of going back to reception every morning, you have a special master card that automatically issues you a new keycard. The master card much longer, but is stored securely in HR (your server),not to our shirt.

Access Token:-

An Access Token is a short-lived(15 min) token that allows a user to access protected resources.

Access Token are stored in the HttpOnly cookies.

Used to access APIs and protected routes and send in every request.

Access token use the refresh token to get new Access Token.

If someone steals an access token, the damage is limited because it expires quickly.

:- Why Do We Need Both?

Why not just use one token?

If we use only a long-lived access token:

The user stays logged in for a long time.
But if the token is stolen, the attacker can use it for a long period.

If we use only a short-lived access token:

Security improves.

But users would have to log in repeatedly.

Using both tokens gives us the best of both worlds:

Access Token → Better security.
Refresh Token → Better user experience.

This balance is why modern applications use both

flow:-

  1. User logs in ↓
  2. Backend verifies credentials ↓
  3. Backend generates:
    • Access Token
    • Refresh Token ↓
  4. Backend sends both as HttpOnly cookies ↓
  5. Backend stores the refresh token hash in the database

Later:-

  1. Access Token expires ↓
  2. Browser sends Refresh Token cookie ↓
  3. Backend verifies:
    • Is the refresh token valid?
    • Is it expired?
    • Does its hash match the one in the DB? ↓
  4. If valid:
    • Generate a new Access Token
    • (Often also generate a new Refresh Token) ↓
  5. Send new token back in HttpOnly cookies

Top comments (1)

Collapse
 
mehrdoost profile image
Mdm

Solid breakdown. From a pentesting angle, I've seen two recurring token handling mistakes that line up with this: first, storing refresh tokens in localStorage or mobile app shared preferences, where they're easily extracted. Second, using long-lived access tokens (hours or even days) "because it's easier" — then an exposed .env or CI/CD log hands an attacker a valid key for far too long. HttpOnly cookies help a lot, but in API-first or CI/CD setups, that's not always an option. Short-lived access tokens plus rotation on refresh is a good baseline, and I usually recommend pairing that with token binding (like DPoP or mTLS) for high-stakes environments. Are you planning to cover token rotation and theft detection next? That's where a lot of teams trip after getting the basics right.