Mengimplementasikan autentikasi di Hono: JWT verification dengan built-in middleware, custom JWT validation, OAuth social login dengan @hono/oauth-providers, dan session management dengan cookie atau header.

Setelah di episode 11 kita mengamankan API dengan CORS, security headers, dan rate limiting, pada episode ini kita akan membangun lapisan autentikasi — mekanisme untuk memverifikasi identitas user sebelum mengakses resource yang dilindungi.
import { jwt } from 'hono/jwt'
const app = new Hono()
app.use('/api/*', jwt({ secret: process.env.JWT_SECRET }))app.get('/api/profile', (c) => {
const payload = c.get('jwtPayload')
return c.json({ userId: payload.sub, name: payload.name })
})import { jwt, verify } from 'hono/jwt'
app.use('/api/*', async (c, next) => {
const authHeader = c.req.header('Authorization')
if (!authHeader?.startsWith('Bearer ')) {
return c.json({ error: 'No token' }, 401)
}
const token = authHeader.split(' ')[1]
try {
const payload = await verify(token, process.env.JWT_SECRET)
c.set('jwtPayload', payload)
await next()
} catch {
return c.json({ error: 'Invalid token' }, 401)
}
})bun add @hono/oauth-providersimport { Hono } from 'hono'
import { githubAuth } from '@hono/oauth-providers/github'
const app = new Hono()
app.get('/auth/github', githubAuth({
clientId: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
scope: ['user:email'],
}))
app.get('/auth/github/callback', async (c) => {
const { token } = c.get('github-token')
const user = await fetch('https://api.github.com/user', {
headers: { Authorization: `Bearer ${token}` },
}).then(r => r.json())
return c.json({ user })
})import { googleAuth } from '@hono/oauth-providers/google'
app.get('/auth/google', googleAuth({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
scope: ['openid', 'email', 'profile'],
}))import { getCookie, setCookie } from 'hono/cookie'
app.post('/auth/login', async (c) => {
const body = await c.req.json()
const user = await authenticateUser(body.email, body.password)
if (!user) return c.json({ error: 'Invalid' }, 401)
const token = await signJwt({ sub: user.id, exp: '7d' }, process.env.JWT_SECRET)
setCookie(c, 'session', token, {
httpOnly: true,
secure: true,
sameSite: 'Lax',
path: '/',
})
return c.json({ message: 'Logged in' })
})app.get('/api/profile', async (c) => {
const token = c.req.header('Authorization')?.split(' ')[1]
if (!token) return c.json({ error: 'No token' }, 401)
const payload = await verifyJwt(token, process.env.JWT_SECRET)
return c.json({ userId: payload.sub })
})Tip
Cookie-based session lebih aman dari localStorage karena httpOnly cookie tidak bisa diakses oleh JavaScript — membuatnya t terhadap XSS attacks. Gunakan cookie untuk web apps, header untuk API mobile/third-party.
Pada episode 12 ini, kalian telah memahami autentikasi di Hono — dari JWT hingga OAuth social login dan session management.
Inti yang harus dibawa pulang:
jwt({ secret }) untuk verification.@hono/oauth-providers untuk GitHub, Google, Discord.setCookie() untuk web apps.Authorization: Bearer untuk API.Di episode 13 selanjutnya kita akan memahami guard pattern dan route-level authorization — middleware composition, RBAC, dan permission-based authorization. Sampai jumpa di episode 13!