authentication
Toàn tập Authentication trong Backend & Microservices
Bài viết này sẽ chia sẻ chi tiết, chuyên sâu về các phương pháp xác thực (authentication) phổ biến trong backend và kiến trúc microservices, bao gồm:
- Session–Cookie
- JWT (JSON Web Token)
- OAuth & OAuth 2.0
- Basic Authentication
- Public/Private Key Authentication (Asymmetric Cryptography)
Mỗi phương pháp sẽ có lý thuyết, ưu & nhược điểm, ứng dụng thực tế, và ví dụ code song song với NestJS & FastAPI để bạn dễ áp dụng.
1. Session–Cookie Authentication
Lý thuyết
- Session: Dữ liệu phiên lưu trên server để ghi nhớ người dùng đã đăng nhập.
- Cookie: File nhỏ lưu trên trình duyệt chứa session ID.
- Server dùng session ID từ cookie để tìm thông tin session và xác thực người dùng.
Ưu điểm
- Dữ liệu nhạy cảm không rời server.
- Thu hồi quyền ngay lập tức.
- Đơn giản để triển khai.
Nhược điểm
- Stateful, cần lưu session.
- Khó scale nếu không có session store.
- Có nguy cơ CSRF.
NestJS Example
// main.ts import * as session from 'express-session'; import * as cookieParser from 'cookie-parser'; app.use(cookieParser()); app.use(session({ secret: 'my-secret', resave: false, saveUninitialized: false, cookie: { httpOnly: true, secure: false } }));
FastAPI Example
from fastapi import FastAPI, Request from starlette.middleware.sessions import SessionMiddleware app = FastAPI() app.add_middleware(SessionMiddleware, secret_key="my-secret") @app.post("/login") async def login(request: Request): request.session["user"] = {"username": "admin"} return {"message": "Logged in"}
2. JWT (JSON Web Token)
Lý thuyết
- Token chứa dữ liệu (payload) + chữ ký số.
- Server không lưu trạng thái, chỉ cần verify chữ ký.
Ưu điểm
- Stateless, dễ scale.
- Tích hợp tốt với microservices.
Nhược điểm
- Khó thu hồi trước khi hết hạn.
- Token dài hơn session ID.
NestJS Example
import { sign, verify } from 'jsonwebtoken'; const token = sign({ userId: 1 }, 'secret', { expiresIn: '1h' }); const decoded = verify(token, 'secret');
FastAPI Example
import jwt token = jwt.encode({"user_id": 1}, "secret", algorithm="HS256") decoded = jwt.decode(token, "secret", algorithms=["HS256"])
3. OAuth & OAuth 2.0
Lý thuyết
- OAuth: Cho phép ứng dụng bên thứ ba truy cập tài nguyên thay mặt người dùng.
- OAuth 2.0: Phiên bản hiện đại, hỗ trợ Access Token và Refresh Token.
Ưu điểm
- Chuẩn công nghiệp cho social login, API integration.
Nhược điểm
- Triển khai phức tạp.
- Cần quản lý refresh token an toàn.
NestJS Example
(Sử dụng Passport.js)
// google.strategy.ts @Injectable() export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { constructor() { super({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: 'http://localhost:3000/auth/google/callback', scope: ['email', 'profile'] }); } }
FastAPI Example
(Sử dụng Authlib)
from authlib.integrations.starlette_client import OAuth oauth = OAuth() oauth.register( name='google', client_id='GOOGLE_CLIENT_ID', client_secret='GOOGLE_CLIENT_SECRET', server_metadata_url='https://accounts.google.com/.well-known/openid-configuration', client_kwargs={'scope': 'openid email profile'} )
4. Basic Authentication
Lý thuyết
- Gửi username:password mã hóa Base64 trong header
Authorization
. - Ví dụ:
Authorization: Basic dXNlcjpwYXNz
.
Ưu điểm
- Đơn giản.
- Không cần cookie hoặc session.
Nhược điểm
- Không an toàn nếu không có HTTPS.
- Mỗi request phải gửi thông tin đăng nhập.
NestJS Example
// middleware.ts const auth = (req, res, next) => { const header = req.headers['authorization'] || ''; const [type, token] = header.split(' '); if (type === 'Basic') { const [user, pass] = Buffer.from(token, 'base64').toString().split(':'); if (user === 'admin' && pass === '123') return next(); } res.status(401).send('Unauthorized'); };
FastAPI Example
from fastapi import Depends, HTTPException from fastapi.security import HTTPBasic, HTTPBasicCredentials security = HTTPBasic() @app.get("/secure") async def secure_route(credentials: HTTPBasicCredentials = Depends(security)): if credentials.username != "admin" or credentials.password != "123": raise HTTPException(status_code=401) return {"message": "OK"}
5. Public/Private Key Authentication (Asymmetric Cryptography)
Tên gọi đúng: Asymmetric Key Authentication hoặc Public Key Infrastructure (PKI)
Lý thuyết
- Client và server dùng cặp khóa public–private.
- Private key giữ bí mật, public key chia sẻ để xác thực chữ ký.
Ưu điểm
- Bảo mật cao.
- Không cần chia sẻ secret.
Nhược điểm
- Quản lý khóa phức tạp.
- Tốn CPU hơn so với symmetric key.
NestJS Example
import { generateKeyPairSync, sign, verify } from 'crypto'; const { publicKey, privateKey } = generateKeyPairSync('rsa', { modulusLength: 2048 }); const data = Buffer.from('hello'); const signature = sign('sha256', data, privateKey); const isValid = verify('sha256', data, publicKey, signature);
FastAPI Example
from cryptography.hazmat.primitives.asymmetric import rsa, padding from cryptography.hazmat.primitives import hashes private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048) public_key = private_key.public_key() message = b"hello" signature = private_key.sign(message, padding.PKCS1v15(), hashes.SHA256()) public_key.verify(signature, message, padding.PKCS1v15(), hashes.SHA256())
Kết luận & Lựa chọn phương pháp
- Web app truyền thống: Session–Cookie.
- SPA/Mobile/microservices: JWT hoặc OAuth 2.0.
- Server-to-server nội bộ: Public/Private key hoặc mTLS.
- API đơn giản: Basic Auth (có HTTPS).
Trong thực tế, các công ty lớn thường kết hợp nhiều phương pháp: Ví dụ: Google dùng OAuth 2.0 + OpenID Connect cho đăng nhập, JWT cho giao tiếp API, và mTLS giữa microservices.