Level 02 — Standard
HTTPS + JWT Authentication
HTTPS plus a login system with tokens. This is what 99% of real apps do — including yours, probably.
01What it actually is
- User logs in → server issues a JWT token
- Angular stores the token, sends it in every request via
Authorization: Bearer xxxheader - Server verifies the token on every request to know who is calling
→ Real-world example
Flipkart, Swiggy, your bank's online portal, any SaaS dashboard. Your project will use this as the baseline — JWT auth on every protected endpoint is non-negotiable.
02Node.js side
Three things to build: a login endpoint that issues tokens, a middleware that verifies them, and any number of protected routes that depend on that middleware.
1 — Login endpoint (issues a token)
server.js — auth endpoints
JavaScript
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const app = express();
app.use(express.json());
const SECRET = process.env.JWT_SECRET;
// 1. Login endpoint — gives back a token
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;
const user = await User.findOne({ email });
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
return res.status(401).json({ error: 'Invalid credentials' });
}
// Sign a JWT with user info
const token = jwt.sign(
{ userId: user.id, email: user.email },
SECRET,
{ expiresIn: '1h' }
);
res.json({ token });
});
2 — Middleware (verifies the token on every protected request)
middleware/auth.js
JavaScript
function authMiddleware(req, res, next) {
const authHeader = req.headers.authorization;
if (!authHeader) return res.status(401).json({ error: 'No token' });
const token = authHeader.replace('Bearer ', '');
try {
req.user = jwt.verify(token, SECRET); // attaches user to request
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
}
3 — Protected routes use the middleware
routes/orders.js
JavaScript
app.get('/api/my-orders', authMiddleware, async (req, res) => {
// req.user.userId came from the token
const orders = await Order.find({ userId: req.user.userId });
res.json(orders);
});
03Angular side
Two pieces: a service that handles login and stores the token, and an HTTP interceptor that automatically attaches the token to every outgoing request. Once the interceptor is wired up, the rest of your app doesn't need to think about auth at all.
1 — AuthService
auth.service.ts
TypeScript
@Injectable({ providedIn: 'root' })
export class AuthService {
constructor(private http: HttpClient) {}
login(email: string, password: string) {
return this.http.post<{token: string}>('/api/login', { email, password })
.pipe(tap(res => localStorage.setItem('token', res.token)));
}
getToken() { return localStorage.getItem('token'); }
logout() { localStorage.removeItem('token'); }
}
2 — HTTP Interceptor (adds the token to every request)
auth.interceptor.ts
TypeScript
// auth.interceptor.ts — adds token to EVERY request automatically
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const token = inject(AuthService).getToken();
if (token) {
req = req.clone({
setHeaders: { Authorization: `Bearer ${token}` }
});
}
return next(req);
};
3 — Components stay clean
orders.component.ts
TypeScript
// Component — no auth code needed, interceptor handles it
ngOnInit() {
this.http.get('/api/my-orders').subscribe(orders => this.orders = orders);
}
04What it protects (and what it doesn't)
| Threat | Protected? | Why / Why not |
|---|---|---|
| Random unauthenticated user calls a protected endpoint | Yes | Middleware rejects requests without a valid token. |
| A user trying to access another user's data | Yes | The token identifies which user, and queries filter by req.user.userId. |
| Stolen token (XSS, leaked from device) | No | Anyone with the token is the user — until it expires. |
Server-side log capture of req.body |
No | Logged requests show plaintext payloads. Level 3 fixes this. |
05Key takeaways
- Code complexity: Standard. Login endpoint, middleware, interceptor.
- Server sees data: Yes. The server needs to know who's calling and what they're asking for.
- Use case: 99% of real applications.
- Performance cost: ~0.07 ms per request (one JWT verify). Invisible.
- Don't skip: Set
JWT_SECRETas a strong env-var, set sensibleexpiresIn, useHttpOnlycookies if you can avoidlocalStoragefor higher-risk apps.