By Diego Liascovich
Full-Stack Developer | Microservices | Angular | Node.js
Modern web applications rely heavily on JSON Web Tokens (JWT) for stateless authentication and secure communication between the frontend and backend.
In this article, we’ll explore the step-by-step security flow using JWT, from the moment a user logs in to the backend verifying their access, including refresh token strategies and best practices.
🔑 1. User Login Request
The user enters their credentials on the frontend (e.g., Angular, React).
The frontend sends a POST /login
request to the backend:
POST /login
{
"email": "user@example.com",
"password": "123456"
}
🧠 2. Backend Authenticates and Issues JWT
- Backend validates credentials.
- If valid, it generates a signed JWT (e.g. using HMAC SHA-256).
- Optional: also returns a refresh token.
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refreshToken": "..." (optional)
}
JWT contains non-sensitive info like
userId
,role
,exp
.
📦 3. Frontend Stores the Token
Options:
-
localStorage
orsessionStorage
(easier, but vulnerable to XSS) - HttpOnly Secure Cookie (safer against XSS)
✅ Recommended: Use cookies with
HttpOnly
,Secure
, andSameSite=Strict
when possible.
🔐 4. Accessing Protected Resources
The frontend includes the accessToken
in the Authorization
header:
GET /orders
Authorization: Bearer <access_token>
🔎 5. Backend Verifies JWT
Steps the backend performs:
- Extracts token from
Authorization
header. - Verifies the signature using the secret.
- Checks
exp
and optional claims likerole
.
If valid → user is authorized.
If invalid/expired → responds with 401 Unauthorized
.
🔁 6. Refreshing the Token (Optional)
If the accessToken
is expired, the frontend can request a new one using the refreshToken
:
POST /refresh-token
Authorization: Bearer <refresh_token>
The backend verifies the refresh token and responds with a new accessToken
.
🚪 7. Logout Flow
Frontend clears the token from storage.
If using cookies: optionally hit a /logout
endpoint to invalidate the refresh token on the server.
📦 Example JWT Payload
{
"sub": "user_123",
"email": "user@example.com",
"role": "admin",
"iat": 1721234567,
"exp": 1721242167
}
✅ Best Practices
- ✅ Use HTTPS always.
- ✅ Use short
accessToken
lifespan (5–15 mins). - ✅ Sign tokens securely (HS256, RS256).
- ✅ Store tokens safely (prefer
HttpOnly
cookies). - ✅ Validate tokens on every request.
🧭 Summary
JWT enables secure, stateless authentication — but only if implemented correctly.
From login to logout, your frontend and backend should follow a strict protocol for storing, sending, and validating tokens. When done right, JWTs make modern apps both user-friendly and secure. 🔐
Let me know if you'd like to see full implementation examples in Angular and Node.js!