@unclex/auth
v0.0.2
Published
A Hono middleware for JWT-based authentication with your custom auth service.
Readme
@unclex/auth
A Hono middleware for JWT-based authentication with your custom auth service.
Installation
bun add @unclex/authFeatures
- 🔒 JWT token verification from cookies
- 🎯 Simple API similar to Clerk's middleware
- 🔧 Flexible configuration options
- 🚀 Built for Hono framework
- 📝 Full TypeScript support
Quick Start
Basic Usage
import { Hono } from 'hono'
import { authMiddleware, getAuth } from '@unclex/auth'
type Bindings = {
JWT_SECRET: string
}
const app = new Hono<{ Bindings: Bindings }>()
// Apply middleware globally
app.use('*', authMiddleware())
// Access auth in routes
app.get('/profile', (c) => {
const auth = getAuth(c)
if (!auth || !auth.isValid) {
return c.json({ error: 'Unauthorized' }, 401)
}
return c.json({ email: auth.email })
})
export default appWith Custom Options
app.use('*', authMiddleware({
jwtSecret: 'your-secret-key',
tokenCookieName: 'custom_token',
throwOnError: true,
onUnauthorized: (c) => c.json({ error: 'Please login' }, 401)
}))Protected Routes
Use the requireAuth() helper to protect specific routes:
import { requireAuth, getAuth } from '@unclex/auth'
// This route requires authentication
app.get('/protected', requireAuth(), async (c) => {
const auth = getAuth(c)! // Guaranteed to be non-null
return c.json({ email: auth.email })
})API Reference
authMiddleware(options?)
Creates the authentication middleware.
Options:
jwtSecret?: string- JWT secret key for token verification. If not provided, will useJWT_SECRETfrom context envtokenCookieName?: string- Cookie name for the JWT token. Default:'token'throwOnError?: boolean- Whether to throw on authentication errors. Default:falseonUnauthorized?: (c: Context) => Response | Promise<Response>- Custom unauthorized response handler
Returns: Hono middleware handler
getAuth(c)
Retrieves the authentication session from context.
Parameters:
c: Context- Hono context object
Returns: AuthSession | null
interface AuthSession {
email: string // User's email from JWT
exp: number // Token expiration timestamp
isValid: boolean // Whether the session is valid
}requireAuth()
Helper middleware that requires a valid authentication session.
Returns: Hono middleware handler that returns 401 if not authenticated
Type Augmentation
The middleware automatically augments Hono's context with auth variables:
import type { AuthVariables } from '@unclex/auth'
// These are automatically available in your context
declare module 'hono' {
interface ContextVariableMap extends AuthVariables {}
}
// Access via context
app.get('/user', (c) => {
const getAuthFn = c.get('getAuth') // Function to get auth
const authSession = c.get('authSession') // Current auth session
// Or use the helper
const auth = getAuth(c)
})Integration with Auth Service
This middleware is designed to work with the @unclex/auth-service backend. The backend handles:
- Email-based authentication with verification codes
- JWT token generation and signing
- Session management
The middleware validates the JWT tokens issued by the auth service.
Authentication Flow
- User requests login via auth service (
POST /login) - User enters verification code (
POST /verify) - Auth service sets JWT token in HTTP-only cookie
- Subsequent requests include the cookie automatically
- Middleware validates the JWT and sets auth context
Environment Variables
When using environment-based configuration:
JWT_SECRET=your-secret-key-heretype Bindings = {
JWT_SECRET: string
}
const app = new Hono<{ Bindings: Bindings }>()
app.use('*', authMiddleware()) // Will use JWT_SECRET from envError Handling
By default, the middleware sets authSession to null on authentication errors. You can change this behavior:
// Return 401 on invalid tokens
app.use('*', authMiddleware({
throwOnError: true,
onUnauthorized: (c) => c.json({
error: 'Authentication required'
}, 401)
}))Examples
Conditional Authentication
// Allow both authenticated and anonymous users
app.get('/mixed', (c) => {
const auth = getAuth(c)
if (auth?.isValid) {
return c.json({
message: 'Welcome back!',
email: auth.email
})
}
return c.json({ message: 'Hello, guest!' })
})Multiple Auth Strategies
// Different auth for different routes
app.use('/api/*', authMiddleware())
app.use('/admin/*', authMiddleware({
throwOnError: true,
onUnauthorized: (c) => c.redirect('/login')
}))License
MIT
