Jen.js includes built-in JWT authentication utilities for securing your application.
JWT Authentication
Basic Setup
import { signToken, verifyToken } from '@src/auth/jwt';
// Create a token
const token = signToken({ userId: '123' }, '7d');
// Verify a token
const payload = verifyToken(token);
Creating Tokens
Sign a token with user data:
const token = signToken(
{
userId: user.id,
email: user.email,
role: user.role
},
'7d' // Expires in 7 days
);
Verifying Tokens
Verify and decode tokens:
try {
const payload = verifyToken(token);
console.log(payload.userId); // Access claims
} catch (err) {
console.error('Invalid token');
}
Login Route
Create an API route for login:
// site/api/(login).ts
import { signToken } from '@src/auth/jwt';
export async function handle(req, res) {
if (req.method === 'POST') {
let body = '';
req.on('data', chunk => body += chunk);
req.on('end', () => {
const { email, password } = JSON.parse(body);
// Verify credentials (check database)
const user = await verifyCredentials(email, password);
if (user) {
const token = signToken({ userId: user.id }, '7d');
res.writeHead(200, { 'content-type': 'application/json' });
res.end(JSON.stringify({ token }));
} else {
res.writeHead(401);
res.end('Invalid credentials');
}
});
}
}
Middleware for Protected Routes
Create auth middleware:
// src/middleware/auth.ts
import { verifyToken } from '@src/auth/jwt';
export async function authMiddleware(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) {
res.writeHead(401);
res.end('No token provided');
return;
}
try {
const payload = verifyToken(token);
req.user = payload;
next();
} catch (err) {
res.writeHead(401);
res.end('Invalid token');
}
}
Protected Pages
// site/dashboard/($userId).tsx
import { verifyToken } from '@src/auth/jwt';
export async function loader(ctx) {
const token = ctx.request.headers.authorization?.split(' ')[1];
try {
const payload = verifyToken(token);
// Token is valid, load user data
return { user: payload };
} catch (err) {
// Redirect to login
ctx.response.writeHead(302, { location: '/login' });
ctx.response.end();
return {};
}
}
export default function Dashboard({ data }) {
return <h1>Welcome, {data.user.userId}</h1>;
}
Configuration
In jen.config.ts:
const config: FrameworkConfig = {
auth: {
secret: process.env.JWT_SECRET,
algorithm: 'HS256',
issuer: 'your-app'
}
};
Best Practices
- Use environment variables for secrets
- Set appropriate expiration (shorter = more secure)
- Validate tokens on protected routes
- Use HTTPS in production
- Store tokens securely on client (httpOnly cookies)
- Implement refresh tokens for long sessions
- Hash passwords before storing