Mengimplementasikan authorization di Hono: guard pattern untuk route-level protection, middleware composition, role-based access control (RBAC), dan permission-based authorization untuk API production.

Setelah di episode 12 kita mengimplementasikan JWT dan OAuth authentication, pada episode ini kita akan memahami authorization — mekanisme untuk membatasi akses user berdasarkan role atau permission. Autentikasi menjawab "siapa kamu?", authorization menjawab "apa yang boleh kamu lakukan?".
Guard adalah middleware yang memeriksa apakah user memiliki hak akses ke route tertentu:
const requireAuth = async (c: any, next: any) => {
const token = c.req.header('Authorization')?.split(' ')[1]
if (!token) return c.json({ error: 'Unauthorized' }, 401)
const payload = await verifyJwt(token, process.env.JWT_SECRET)
c.set('user', payload)
await next()
}
const app = new Hono()
app.use('/api/admin/*', requireAuth)
app.get('/api/admin/users', (c) => {
const user = c.get('user')
return c.json({ users: [] })
})app.get('/admin/dashboard', async (c, next) => {
const user = c.get('user')
if (user.role !== 'admin') {
return c.json({ error: 'Forbidden' }, 403)
}
await next()
}, (c) => {
return c.json({ message: 'Admin dashboard' })
})Hono mendukung composition multiple middleware:
app.use('*', [cors(), logger(), jwt({ secret: 'secret' })])const adminOnly = async (c: any, next: any) => {
if (c.req.path.startsWith('/admin')) {
const user = c.get('user')
if (user.role !== 'admin') return c.json({ error: 'Forbidden' }, 403)
}
await next()
}
app.use('*', adminOnly)type Role = 'admin' | 'editor' | 'viewer'
const requireRole = (...roles: Role[]) => async (c: any, next: any) => {
const user = c.get('user')
if (!roles.includes(user.role)) {
return c.json({ error: 'Insufficient permissions' }, 403)
}
await next()
}
const app = new Hono()
// Admin only
app.use('/admin/*', requireRole('admin'))
// Admin dan editor
app.use('/posts/*', requireRole('admin', 'editor'))
// Semua role
app.get('/posts', (c) => c.json([]))const requirePermission = (...perms: string[]) => async (c: any, next: any) => {
const user = c.get('user')
const hasPermission = perms.every(p => user.permissions?.includes(p))
if (!hasPermission) return c.json({ error: 'Forbidden' }, 403)
await next()
}
app.delete('/posts/:id', requirePermission('posts:delete'), deletePostHandler)Note
RBAC lebih sederhana untuk aplikasi dengan role yang tetap (admin, editor, viewer). Permission-based lebih fleksibel untuk aplikasi dengan permission yang granular. Pilih sesuai kebutuhan aplikasi kalian.
Pada episode 13 ini, kalian telah memahami guard pattern dan authorization di Hono.
Inti yang harus dibawa pulang:
Di episode 14 selanjutnya kita akan memahami WebSocket dan real-time communication — setup WebSocket endpoint, typed messages, dan broadcast untuk aplikasi chat atau live notification. Sampai jumpa di episode 14!