xiaohongshu
xiaohongshu
auth-comprehensive
Production-grade authentication & authorization covering JWT, cookies, sessions, hashing, MFA, OAuth2, RBAC, and permissions across all frameworks (Next.js, Express.js, FastAPI, Django, Spring, etc.). Includes intelligent pattern selection, Better Auth integration, email verification, social logi...
Full skill instructions
Enterprise-grade authentication system supporting multiple frameworks with intelligent pattern selection, advanced security hardening, and production-ready implementations across all authentication methods (JWT, sessions, cookies, hybrid approaches).
Choose authentication method based on requirements:
Need stateless, API-first, microservices?
├─ YES → JWT Tokens (access + refresh)
└─ NO → Continue
Need session-based, traditional web app?
├─ YES → Sessions (server-side)
└─ NO → Continue
Need browser cookies, XSS protection?
├─ YES → HTTP-Only Cookies
└─ NO → Continue
Need best of both worlds?
└─ Hybrid (JWT + Cookies)
Need enhanced security & ease?
└─ Better Auth / Auth Libraries
Best For: APIs, microservices, mobile apps, single-page applications
# Python/FastAPI
from datetime import datetime, timedelta
from jose import JWTError, jwt
from passlib.context import CryptContext
class JWTManager:
def __init__(self, secret_key: str, algorithm: str = "HS256"):
self.secret_key = secret_key
self.algorithm = algorithm
self.pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def hash_password(self, password: str) -> str:
return self.pwd_context.hash(password)
def verify_password(self, plain: str, hashed: str) -> bool:
return self.pwd_context.verify(plain, hashed)
def create_access_token(self, data: dict, expires_delta: timedelta = None) -> str:
to_encode = data.copy()
expire = datetime.utcnow() + (expires_delta or timedelta(minutes=15))
to_encode.update({"exp": expire, "type": "access"})
return jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
def create_refresh_token(self, user_id: int) -> str:
payload = {
"sub": str(user_id),
"type": "refresh",
"exp": datetime.utcnow() + timedelta(days=7)
}
return jwt.encode(payload, self.secret_key, algorithm=self.algorithm)
def decode_token(self, token: str) -> dict:
try:
payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
return payload
except JWTError:
return None
// JavaScript/Node.js/Express
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
class JWTManager {
constructor(secretKey, algorithm = 'HS256') {
this.secretKey = secretKey;
this.algorithm = algorithm;
}
hashPassword(password) {
return bcrypt.hashSync(password, 10);
}
verifyPassword(plain, hashed) {
return bcrypt.compareSync(plain, hashed);
}
createAccessToken(data, expiresIn = '15m') {
return jwt.sign(
{ ...data, type: 'access' },
this.secretKey,
{ algorithm: this.algorithm, expiresIn }
);
}
createRefreshToken(userId) {
return jwt.sign(
{ sub: userId, type: 'refresh' },
this.secretKey,
{ expiresIn: '7d' }
);
}
decodeToken(token) {
try {
return jwt.verify(token, this.secretKey);
} catch (error) {
return null;
}
}
}
module.exports = JWTManager;
// TypeScript/Next.js
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
interface TokenPayload {
sub: string;
type: 'access' | 'refresh';
iat: number;
exp: number;
}
class JWTManager {
private secretKey: string;
private algorithm: string = 'HS256';
constructor(secretKey: string) {
this.secretKey = secretKey;
}
hashPassword(password: string): string {
return bcrypt.hashSync(password, 10);
}
verifyPassword(plain: string, hashed: string): boolean {
return bcrypt.compareSync(plain, hashed);
}
createAccessToken(data: any, expiresIn: string = '15m'): string {
return jwt.sign(
{ ...data, type: 'access' },
this.secretKey,
{ algorithm: this.algorithm, expiresIn }
);
}
createRefreshToken(userId: number): string {
return jwt.sign(
{ sub: userId, type: 'refresh' },
this.secretKey,
{ expiresIn: '7d' }
);
}
decodeToken(token: string): TokenPayload | null {
try {
return jwt.verify(token, this.secretKey) as TokenPayload;
} catch (error) {
return null;
}
}
}
export default JWTManager;
Best For: Traditional web apps, server-rendered applications, CSRF protection needed
# Python/Flask or FastAPI with sessions
from sqlalchemy.orm import Session
from datetime import datetime, timedelta
import secrets
class SessionManager:
def __init__(self, db: Session, session_timeout_minutes: int = 30):
self.db = db
self.timeout = timedelta(minutes=session_timeout_minutes)
def create_session(self, user_id: int) -> str:
"""Create new session and return session ID"""
session_token = secrets.token_urlsafe(32)
session_record = {
'user_id': user_id,
'token': session_token,
'created_at': datetime.utcnow(),
'expires_at': datetime.utcnow() + self.timeout,
'last_activity': datetime.utcnow()
}
# Save to database
self.db.create(UserSession, session_record)
self.db.commit()
return session_token
def get_session(self, token: str) -> dict | None:
"""Retrieve and validate session"""
session = self.db.query(UserSession).filter(
UserSession.token == token,
UserSession.expires_at > datetime.utcnow()
).first()
if session:
# Update last activity
session.last_activity = datetime.utcnow()
self.db.commit()
return {'user_id': session.user_id}
return None
def invalidate_session(self, token: str) -> bool:
"""Logout - invalidate session"""
session = self.db.query(UserSession).filter(
UserSession.token == token
).first()
if session:
self.db.delete(session)
self.db.commit()
return True
return False
// JavaScript/Express with express-session
const session = require('express-session');
const RedisStore = require('connect-redis').default;
const { createClient } = require('redis');
const redisClient = createClient();
redisClient.connect();
const sessionMiddleware = session({
store: new RedisStore({ client: redisClient }),
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // No JS access
sameSite: 'strict',
maxAge: 30 * 60 * 1000 // 30 minutes
}
});
app.use(sessionMiddleware);
app.post('/login', (req, res) => {
if (authenticateUser(req.body)) {
req.session.userId = user.id;
req.session.role = user.role;
res.json({ message: 'Logged in' });
}
});
app.post('/logout', (req, res) => {
req.session.destroy((err) => {
if (err) return res.status(500).json({ error: 'Logout failed' });
res.json({ message: 'Logged out' });
});
});
Best For: Web applications, maximum XSS protection
// Express/Node.js - Setting HTTP-Only Cookies
app.post('/login', async (req, res) => {
const user = await authenticateUser(req.body.email, req.body.password);
if (!user) {
return res.status(401).json({ error: 'Invalid credentials' });
}
const accessToken = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId: user.id },
process.env.REFRESH_SECRET,
{ expiresIn: '7d' }
);
// Set HTTP-Only cookie - cannot be accessed by JavaScript
res.cookie('accessToken', accessToken, {
httpOnly: true, // No JS access (prevents XSS)
secure: true, // HTTPS only
sameSite: 'strict', // CSRF protection
maxAge: 15 * 60 * 1000, // 15 minutes
path: '/',
domain: process.env.COOKIE_DOMAIN
});
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000, // 7 days
path: '/api/auth/refresh'
});
res.json({ message: 'Login successful' });
});
// Middleware to extract token from cookies
function authenticateRequest(req, res, next) {
const token = req.cookies.accessToken;
if (!token) {
return res.status(401).json({ error: 'No token' });
}
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
req.userId = decoded.userId;
req.role = decoded.role;
next();
} catch (error) {
return res.status(401).json({ error: 'Invalid token' });
}
}
app.get('/api/protected', authenticateRequest, (req, res) => {
res.json({ data: 'Protected content', userId: req.userId });
});
// Next.js - Handling cookies securely
import { cookies } from 'next/headers';
import jwt from 'jsonwebtoken';
export async function login(email: string, password: string) {
const user = await authenticateUser(email, password);
if (!user) throw new Error('Invalid credentials');
const accessToken = jwt.sign(
{ userId: user.id, role: user.role },
process.env.JWT_SECRET,
{ expiresIn: '15m' }
);
const refreshToken = jwt.sign(
{ userId: user.id },
process.env.REFRESH_SECRET,
{ expiresIn: '7d' }
);
const cookieStore = await cookies();
// Set HTTP-Only cookie
cookieStore.set('accessToken', accessToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 15 * 60, // seconds
path: '/'
});
cookieStore.set('refreshToken', refreshToken, {
httpOnly: true,
secure: process.env.NODE_ENV === 'production',
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60,
path: '/api/auth/refresh'
});
}
export async function getUser() {
const cookieStore = await cookies();
const token = cookieStore.get('accessToken')?.value;
if (!token) return null;
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET);
return decoded;
} catch {
return null;
}
}
Best For: Maximum security + flexibility, modern web apps
# FastAPI - Hybrid JWT + HTTP-Only Cookies
from fastapi import FastAPI, Cookie, Depends, HTTPException
from fastapi.responses import JSONResponse
app = FastAPI()
@app.post("/login")
async def login(email: str, password: str):
user = authenticate_user(email, password)
if not user:
raise HTTPException(status_code=401, detail="Invalid credentials")
# Create tokens
access_token = create_access_token({"sub": str(user.id)})
refresh_token = create_refresh_token(user.id)
# Store refresh token in database for revocation
store_refresh_token(user.id, refresh_token)
response = JSONResponse(content={"access_token": access_token})
# Set refresh token in HTTP-Only cookie
response.set_cookie(
key="refresh_token",
value=refresh_token,
httponly=True,
secure=True,
samesite="strict",
max_age=7 * 24 * 60 * 60
)
return response
async def get_current_user(
access_token: str = Cookie(None),
refresh_token: str = Cookie(None)
):
"""Validate access token, refresh if needed"""
if access_token:
try:
payload = jwt.decode(access_token, SECRET_KEY)
return payload["sub"]
except JWTError:
pass
# Try refresh token
if refresh_token:
user_id = verify_refresh_token(refresh_token)
if user_id:
new_access = create_access_token({"sub": str(user_id)})
# Return new access token
return user_id
raise HTTPException(status_code=401, detail="Not authenticated")
@app.get("/protected")
async def protected_route(user_id: str = Depends(get_current_user)):
return {"user_id": user_id}
# FastAPI with TOTP (Google Authenticator)
from pyotp import TOTP
from qrcode import QRCode
class MFAManager:
@staticmethod
def generate_secret() -> str:
"""Generate TOTP secret"""
return TOTP.new().secret
@staticmethod
def get_provisioning_uri(secret: str, user_email: str, issuer: str) -> str:
"""Get QR code URI for authenticator app"""
totp = TOTP(secret)
return totp.provisioning_uri(name=user_email, issuer_name=issuer)
@staticmethod
def verify_token(secret: str, token: str) -> bool:
"""Verify TOTP token"""
totp = TOTP(secret)
return totp.verify(token)
@app.post("/auth/mfa/setup")
async def setup_mfa(current_user: User = Depends(get_current_user)):
"""Generate MFA secret and QR code"""
secret = MFAManager.generate_secret()
uri = MFAManager.get_provisioning_uri(secret, current_user.email, "MyApp")
# Return QR code and secret
return {
"secret": secret,
"qr_code_uri": uri
}
@app.post("/auth/mfa/enable")
async def enable_mfa(
mfa_token: str,
mfa_secret: str,
current_user: User = Depends(get_current_user)
):
"""Enable MFA after verification"""
if not MFAManager.verify_token(mfa_secret, mfa_token):
raise HTTPException(status_code=400, detail="Invalid MFA token")
# Save secret to database
update_user_mfa(current_user.id, mfa_secret)
return {"message": "MFA enabled"}
@app.post("/auth/login-mfa")
async def login_with_mfa(email: str, password: str, mfa_token: str):
"""Login with MFA verification"""
user = authenticate_user(email, password)
if not user:
raise HTTPException(status_code=401)
if not MFAManager.verify_token(user.mfa_secret, mfa_token):
raise HTTPException(status_code=401, detail="Invalid MFA token")
access_token = create_access_token({"sub": str(user.id)})
return {"access_token": access_token}
# FastAPI with Email Verification
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail
import secrets
class EmailVerificationManager:
@staticmethod
def create_verification_token(user_id: int) -> str:
token = secrets.token_urlsafe(32)
store_verification_token(user_id, token)
return token
@staticmethod
def send_verification_email(email: str, token: str):
verification_link = f"https://yourapp.com/auth/verify?token={token}"
message = Mail(
from_email="[email protected]",
to_emails=email,
subject="Verify your email",
html_content=f'<a href="{verification_link}">Click to verify</a>'
)
sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
sg.send(message)
@staticmethod
def verify_email(token: str) -> int | None:
user_id = get_user_id_from_token(token)
if user_id and is_token_valid(token):
mark_email_verified(user_id)
delete_verification_token(token)
return user_id
return None
@app.post("/auth/register")
async def register(email: str, password: str):
user = create_user(email, hash_password(password))
token = EmailVerificationManager.create_verification_token(user.id)
EmailVerificationManager.send_verification_email(email, token)
return {"message": "Verification email sent"}
@app.get("/auth/verify")
async def verify_email(token: str):
user_id = EmailVerificationManager.verify_email(token)
if user_id:
return {"message": "Email verified"}
raise HTTPException(status_code=400, detail="Invalid token")
# FastAPI with Google OAuth2
from google.auth.transport import requests
from google.oauth2 import id_token
class GoogleOAuth:
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
@staticmethod
def verify_token(token: str) -> dict | None:
try:
idinfo = id_token.verify_oauth2_token(
token,
requests.Request(),
GoogleOAuth.GOOGLE_CLIENT_ID
)
return idinfo
except ValueError:
return None
@app.post("/auth/google")
async def google_login(token: str):
idinfo = GoogleOAuth.verify_token(token)
if not idinfo:
raise HTTPException(status_code=400, detail="Invalid token")
# Create or get user
user = get_or_create_user(
email=idinfo["email"],
name=idinfo["name"],
picture=idinfo["picture"]
)
access_token = create_access_token({"sub": str(user.id)})
return {"access_token": access_token, "user": user}
// Next.js with Google OAuth2
import GoogleProvider from "next-auth/providers/google";
import { NextAuthOptions } from "next-auth";
export const authOptions: NextAuthOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!
})
],
callbacks: {
async jwt({ token, account }) {
if (account) {
token.accessToken = account.access_token;
}
return token;
},
async session({ session, token }) {
session.user.id = token.sub;
return session;
}
}
};
# FastAPI RBAC
from enum import Enum
class Role(str, Enum):
ADMIN = "admin"
MODERATOR = "moderator"
USER = "user"
class Permission(str, Enum):
READ = "read"
WRITE = "write"
DELETE = "delete"
MANAGE_USERS = "manage_users"
ROLE_PERMISSIONS = {
Role.ADMIN: [Permission.READ, Permission.WRITE, Permission.DELETE, Permission.MANAGE_USERS],
Role.MODERATOR: [Permission.READ, Permission.WRITE, Permission.DELETE],
Role.USER: [Permission.READ]
}
def has_permission(required_permission: Permission):
async def permission_checker(current_user: User = Depends(get_current_user)):
user_permissions = ROLE_PERMISSIONS.get(current_user.role, [])
if required_permission not in user_permissions:
raise HTTPException(status_code=403, detail="Permission denied")
return current_user
return permission_checker
@app.delete("/users/{user_id}")
async def delete_user(
user_id: int,
current_user: User = Depends(has_permission(Permission.MANAGE_USERS))
):
delete_user_from_db(user_id)
return {"message": "User deleted"}
# Python/FastAPI
from passlib.context import CryptContext
pwd_context = CryptContext(
schemes=["bcrypt"],
deprecated="auto",
bcrypt__rounds=12 # Cost factor - higher = more secure but slower
)
def hash_password(password: str) -> str:
# Ensure password is at least 8 chars, has uppercase, digit, special char
if len(password) < 8:
raise ValueError("Password must be at least 8 characters")
if not any(c.isupper() for c in password):
raise ValueError("Password must contain uppercase letter")
if not any(c.isdigit() for c in password):
raise ValueError("Password must contain digit")
if not any(c in "!@#$%^&*.-_" for c in password):
raise ValueError("Password must contain special character")
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
// JavaScript/Node.js
const bcrypt = require('bcrypt');
const SALT_ROUNDS = 12;
async function hashPassword(password) {
// Validate password strength
const strongRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
if (!strongRegex.test(password)) {
throw new Error('Password must be 8+ chars with uppercase, digit, and special char');
}
return bcrypt.hash(password, SALT_ROUNDS);
}
async function verifyPassword(plainPassword, hashedPassword) {
return bcrypt.compare(plainPassword, hashedPassword);
}
Better Auth is a modern authentication library that simplifies many patterns:
// Next.js with Better Auth
import { betterAuth } from "better-auth";
import { nextCookies } from "better-auth/next-js";
export const auth = betterAuth({
database: prisma,
secret: process.env.BETTER_AUTH_SECRET,
plugins: [
nextCookies()
],
user: {
additionalFields: {
role: {
type: "string",
required: false,
defaultValue: "user"
}
}
},
emailVerification: {
sendVerificationEmail: async ({ email, url }) => {
await sendEmail({
to: email,
subject: "Verify your email",
html: `<a href="${url}">Verify email</a>`
});
}
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET
},
github: {
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET
}
}
});
// Usage in Next.js
export { auth as default } from '@/auth';
// Client-side
import { signIn, signOut, useSession } from "better-auth/client";
export function LoginButton() {
return (
<button onClick={() => signIn.social({ provider: "google" })}>
Login with Google
</button>
);
}
# FastAPI - Token Revocation (Blacklist)
from redis import Redis
redis_client = Redis(host='localhost', port=6379, db=0)
class TokenRevocationManager:
@staticmethod
def revoke_token(token: str, ttl_seconds: int):
"""Add token to blacklist"""
redis_client.setex(f"revoked_token:{token}", ttl_seconds, "1")
@staticmethod
def is_revoked(token: str) -> bool:
"""Check if token is revoked"""
return redis_client.exists(f"revoked_token:{token}") > 0
async def get_current_user(token: str = Depends(oauth2_scheme)):
if TokenRevocationManager.is_revoked(token):
raise HTTPException(status_code=401, detail="Token revoked")
payload = jwt.decode(token, SECRET_KEY)
return payload["sub"]
@app.post("/auth/logout")
async def logout(current_user: User = Depends(get_current_user), token: str = Header()):
# Revoke token
payload = jwt.decode(token, SECRET_KEY)
remaining_time = payload["exp"] - datetime.utcnow().timestamp()
TokenRevocationManager.revoke_token(token, int(remaining_time))
return {"message": "Logged out"}
✅ Password Security
✅ Token Security
✅ Database Security
✅ API Security
✅ Frontend Security
✅ Infrastructure
xiaohongshu
technical spec
product ux expert
database patterns
Conduct multi-agent task orchestration and workflow coordination.
Initialize project with Conductor artifacts (product definition,
Expert in web animations, transitions, and motion design using Framer Motion and CSS
Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...
PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.
Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...
Display project status, active tracks, and next actions
Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience