Cara Membangun Sistem Authentication dengan Claude Code (JWT dan OAuth)
Cara Membangun Sistem Authentication dengan Claude Code (JWT dan OAuth). Panduan praktis dengan contoh kode.
Keuntungan Menggunakan Claude Code untuk Membangun Sistem Authentication
Authentication adalah fungsionalitas yang langsung terkait keamanan, dan kesalahan implementasi bisa menyebabkan kerentanan serius. Claude Code men-generate implementasi dengan mempertimbangkan best practice keamanan, dan juga menyarankan penanggulangan terhadap vektor serangan yang sering terlewat.
Implementasi JWT Authentication
> Implementasikan JWT authentication dengan Express + TypeScript.
> Dengan metode 2-token: access token (15 menit) dan refresh token (7 hari).
> Kelola refresh token dengan httpOnly cookie.
Service Authentication
import jwt from 'jsonwebtoken';
import bcrypt from 'bcrypt';
import { prisma } from './db';
const ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET!;
const REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET!;
interface TokenPayload {
userId: string;
email: string;
}
export class AuthService {
async register(email: string, password: string, name: string) {
const existing = await prisma.user.findUnique({ where: { email } });
if (existing) throw new Error('Email already registered');
const hashedPassword = await bcrypt.hash(password, 12);
const user = await prisma.user.create({
data: { email, password: hashedPassword, name },
});
return this.generateTokens({ userId: user.id, email: user.email });
}
async login(email: string, password: string) {
const user = await prisma.user.findUnique({ where: { email } });
if (!user) throw new Error('Invalid credentials');
const valid = await bcrypt.compare(password, user.password);
if (!valid) throw new Error('Invalid credentials');
return this.generateTokens({ userId: user.id, email: user.email });
}
async refreshToken(token: string) {
const payload = jwt.verify(token, REFRESH_TOKEN_SECRET) as TokenPayload;
// Konfirmasi validitas refresh token di DB
const stored = await prisma.refreshToken.findFirst({
where: { token, userId: payload.userId, revoked: false },
});
if (!stored) throw new Error('Invalid refresh token');
// Invalidasi token lama (rotasi token)
await prisma.refreshToken.update({
where: { id: stored.id },
data: { revoked: true },
});
return this.generateTokens(payload);
}
private async generateTokens(payload: TokenPayload) {
const accessToken = jwt.sign(payload, ACCESS_TOKEN_SECRET, {
expiresIn: '15m',
});
const refreshToken = jwt.sign(payload, REFRESH_TOKEN_SECRET, {
expiresIn: '7d',
});
await prisma.refreshToken.create({
data: { token: refreshToken, userId: payload.userId },
});
return { accessToken, refreshToken };
}
}
Middleware Authentication
import { Request, Response, NextFunction } from 'express';
import jwt from 'jsonwebtoken';
export function authMiddleware(req: Request, res: Response, next: NextFunction) {
const header = req.headers.authorization;
if (!header?.startsWith('Bearer ')) {
return res.status(401).json({ error: 'No token provided' });
}
const token = header.slice(7);
try {
const payload = jwt.verify(token, process.env.ACCESS_TOKEN_SECRET!);
req.user = payload as TokenPayload;
next();
} catch (err) {
return res.status(401).json({ error: 'Invalid or expired token' });
}
}
Konfigurasi Router
import { Router } from 'express';
import { AuthService } from './auth-service';
const router = Router();
const auth = new AuthService();
router.post('/register', async (req, res) => {
try {
const { accessToken, refreshToken } = await auth.register(
req.body.email, req.body.password, req.body.name
);
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000,
});
res.json({ accessToken });
} catch (err) {
res.status(400).json({ error: (err as Error).message });
}
});
router.post('/login', async (req, res) => {
try {
const { accessToken, refreshToken } = await auth.login(
req.body.email, req.body.password
);
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000,
});
res.json({ accessToken });
} catch (err) {
res.status(401).json({ error: 'Invalid credentials' });
}
});
router.post('/refresh', async (req, res) => {
try {
const token = req.cookies.refreshToken;
const { accessToken, refreshToken } = await auth.refreshToken(token);
res.cookie('refreshToken', refreshToken, {
httpOnly: true,
secure: true,
sameSite: 'strict',
maxAge: 7 * 24 * 60 * 60 * 1000,
});
res.json({ accessToken });
} catch (err) {
res.status(401).json({ error: 'Invalid refresh token' });
}
});
export default router;
Integrasi OAuth (Google)
> Tambahkan Google login dengan PassportJS. Integrasikan dengan JWT authentication yang sudah ada.
import passport from 'passport';
import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
passport.use(new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
callbackURL: '/auth/google/callback',
}, async (accessToken, refreshToken, profile, done) => {
let user = await prisma.user.findFirst({
where: { providerId: profile.id, provider: 'google' },
});
if (!user) {
user = await prisma.user.create({
data: {
email: profile.emails![0].value,
name: profile.displayName,
provider: 'google',
providerId: profile.id,
},
});
}
done(null, user);
}));
Checklist Keamanan
Kamu bisa meminta Claude Code melakukan audit keamanan dengan prompt berikut.
> Review kode terkait authentication dari perspektif keamanan.
> Periksa berdasarkan OWASP Top 10.
Item pemeriksaan utama:
- Apakah menggunakan bcrypt untuk password hashing
- Apakah JWT secret key cukup panjang
- Apakah rotasi refresh token diimplementasikan
- Apakah perlindungan CSRF diterapkan
- Apakah rate limiting diatur
Untuk mempertahankan kualitas kode termasuk keamanan, Otomasi Refactoring juga efektif. Dengan mendokumentasikan kebijakan konfigurasi authentication di CLAUDE.md, Claude Code akan men-generate kode yang konsisten.
Summary
Dengan Claude Code, kamu bisa membangun sistem authentication yang robust termasuk JWT authentication dan integrasi OAuth secara efisien. Karena kode di-generate dengan mempertimbangkan best practice keamanan, kerentanan yang sering terlewat juga lebih mudah ditangani. Pastikan untuk selalu menerapkan manajemen secret key yang aman dan komunikasi HTTPS di lingkungan produksi.
Untuk detail, lihat Dokumentasi Resmi Anthropic.
PDF Gratis: Cheatsheet Claude Code dalam 5 Menit
Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.
Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.
Tentang Penulis
Masa
Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.
Artikel Terkait
7 pemeriksaan sebelum menerbitkan artikel Claude Code multibahasa setiap hari
Checklist praktis agar artikel Claude Code multibahasa yang diterbitkan setiap hari tidak kehilangan locale, tidak merusak CTA, dan tidak meninggalkan halaman lama di production.
Apa itu Codex Automations? Membiarkan AI mengurus konten saat kamu tidur
Panduan praktis memakai Codex Automations untuk analytics, artikel, CTA, deploy, dan monetisasi.
Claude Code × GCP Cloud Functions Panduan Lengkap | Pengembangan Serverless Super Cepat
Optimalkan GCP Cloud Functions dengan Claude Code. Implementasikan trigger HTTP/Pub/Sub/Firestore, pengujian lokal, dan otomatisasi deployment dengan contoh kode nyata dari pengalaman Masa.