<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anish Roy</title>
    <description>The latest articles on DEV Community by Anish Roy (@anish_roy_1af520ea95fcb15).</description>
    <link>https://dev.to/anish_roy_1af520ea95fcb15</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3458703%2F68464415-4462-47e3-b2ae-dc9f4a43bca3.png</url>
      <title>DEV Community: Anish Roy</title>
      <link>https://dev.to/anish_roy_1af520ea95fcb15</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anish_roy_1af520ea95fcb15"/>
    <language>en</language>
    <item>
      <title>Understanding JWT Authentication with Access Tokens, Refresh Tokens, and Redis</title>
      <dc:creator>Anish Roy</dc:creator>
      <pubDate>Mon, 16 Feb 2026 11:53:37 +0000</pubDate>
      <link>https://dev.to/anish_roy_1af520ea95fcb15/understanding-jwt-authentication-with-access-tokens-refresh-tokens-and-redis-1ajj</link>
      <guid>https://dev.to/anish_roy_1af520ea95fcb15/understanding-jwt-authentication-with-access-tokens-refresh-tokens-and-redis-1ajj</guid>
      <description>&lt;p&gt;Modern web applications need authentication systems that are secure, scalable, and stateless. One widely used approach is JWT (JSON Web Token)–based authentication combined with Access Tokens, Refresh Tokens, and Redis for session control and enhanced security.&lt;/p&gt;

&lt;p&gt;This article explains how the system works, why it is designed this way, and how to implement it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is JWT?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A JWT (JSON Web Token) is a compact, URL-safe token used to transmit information securely between parties.&lt;/p&gt;

&lt;p&gt;A JWT has three parts:&lt;br&gt;
Header&lt;br&gt;
Payload&lt;br&gt;
Signature&lt;/p&gt;

&lt;p&gt;Example structure:&lt;br&gt;
xxxxx.yyyyy.zzzzz&lt;/p&gt;

&lt;p&gt;Header: Contains algorithm and token type&lt;br&gt;
Payload: Contains user data (claims)&lt;br&gt;
Signature: Ensures token integrity&lt;br&gt;
The server signs the token, and the client sends it in requests.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The Problem with Simple JWT Authentication&lt;br&gt;
A basic JWT system issues one token that lasts for hours or days.&lt;br&gt;
Problems:&lt;br&gt;
If the token is stolen, it can be used until expiration&lt;br&gt;
No easy way to revoke tokens&lt;br&gt;
Long expiry increases security risk&lt;br&gt;
To solve this, modern systems use Access Tokens + Refresh Tokens.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Access Token vs Refresh Token&lt;br&gt;
Feature Access Token    Refresh Token&lt;br&gt;
Lifetime    Short (5–15 min)  Long (days or weeks)&lt;br&gt;
Usage   Access APIs Generate new access tokens&lt;br&gt;
Stored In   Memory / HTTP-only cookie   Secure storage (DB or Redis)&lt;br&gt;
Risk    Lower   Higher (must be protected)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication Flow (Conceptual Diagram)&lt;br&gt;
User Login&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
Server verifies credentials&lt;br&gt;
│&lt;br&gt;
├── Access Token (short life)&lt;br&gt;
└── Refresh Token (long life, stored in Redis)&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
Client uses Access Token for API requests&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
Access Token expires&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
Client sends Refresh Token&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
Server verifies token in Redis&lt;br&gt;
│&lt;br&gt;
▼&lt;br&gt;
New Access Token issued&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Why Redis is Used&lt;br&gt;
Redis is an in-memory data store that is extremely fast.&lt;br&gt;
Redis helps in:&lt;br&gt;
Storing Refresh Tokens securely&lt;br&gt;
Blacklisting revoked tokens&lt;br&gt;
Managing session expiry&lt;br&gt;
Detecting token reuse attacks&lt;br&gt;
Without Redis, refresh tokens stored only on the client cannot be easily revoked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Token Storage Strategy&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Best practice:&lt;br&gt;
Access Token:&lt;br&gt;
Stored in memory or HTTP-only cookie&lt;br&gt;
Short expiration&lt;/p&gt;

&lt;p&gt;Refresh Token:&lt;br&gt;
Stored in HTTP-only cookie&lt;br&gt;
Stored in Redis on server side&lt;/p&gt;

&lt;p&gt;Redis example structure:&lt;br&gt;
Key: refreshToken:userId&lt;br&gt;
Value: token&lt;br&gt;
TTL: 7 days&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implementation Example (Node.js + Express)
Install dependencies
npm install jsonwebtoken redis cookie-parser
Generating Tokens
const jwt = require("jsonwebtoken");&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;function generateAccessToken(user) {&lt;br&gt;
  return jwt.sign(user, process.env.ACCESS_SECRET, { expiresIn: "15m" });&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;function generateRefreshToken(user) {&lt;br&gt;
  return jwt.sign(user, process.env.REFRESH_SECRET, { expiresIn: "7d" });&lt;br&gt;
}&lt;br&gt;
Storing Refresh Token in Redis&lt;br&gt;
await redisClient.set(&lt;br&gt;
  &lt;code&gt;refreshToken:${user.id}&lt;/code&gt;,&lt;br&gt;
  refreshToken,&lt;br&gt;
  { EX: 604800 } // 7 days&lt;br&gt;
);&lt;br&gt;
Refresh Token Endpoint&lt;br&gt;
app.post("/refresh", async (req, res) =&amp;gt; {&lt;br&gt;
  const token = req.cookies.refreshToken;&lt;/p&gt;

&lt;p&gt;if (!token) return res.sendStatus(401);&lt;/p&gt;

&lt;p&gt;const storedToken = await redisClient.get(&lt;code&gt;refreshToken:${userId}&lt;/code&gt;);&lt;/p&gt;

&lt;p&gt;if (storedToken !== token) return res.sendStatus(403);&lt;/p&gt;

&lt;p&gt;jwt.verify(token, process.env.REFRESH_SECRET, (err, user) =&amp;gt; {&lt;br&gt;
    if (err) return res.sendStatus(403);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const accessToken = generateAccessToken({ id: user.id });
res.json({ accessToken });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;});&lt;br&gt;
});&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security Best Practices&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Use HTTPS to prevent token interception&lt;br&gt;
Use HTTP-only cookies to prevent XSS attacks&lt;br&gt;
Rotate refresh tokens after each use&lt;br&gt;
Set short expiry for access tokens&lt;br&gt;
Store refresh tokens in Redis with expiration&lt;/p&gt;

&lt;p&gt;Optional advanced protection:&lt;br&gt;
Token fingerprinting&lt;br&gt;
IP/device binding&lt;br&gt;
Refresh token rotation with blacklist&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Advantages of This Approach&lt;br&gt;
Stateless API authentication&lt;br&gt;
Fast token verification&lt;br&gt;
Easy scaling in microservices&lt;br&gt;
Centralized session control using Redis&lt;br&gt;
Better protection against token theft&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Real-World Usage&lt;br&gt;
This pattern is used in:&lt;br&gt;
Banking dashboards&lt;br&gt;
SaaS products&lt;br&gt;
Mobile apps with APIs&lt;br&gt;
Large-scale distributed systems&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;JWT authentication becomes significantly more secure when combined with short-lived access tokens, refresh tokens, and Redis for session management. This approach balances performance, scalability, and security while keeping APIs stateless.&lt;/p&gt;

</description>
      <category>jwt</category>
      <category>backendbeginner</category>
    </item>
  </channel>
</rss>
