import { Request, Response, NextFunction } from 'express';
import { getCustomerByToken, isValidTokenFormat } from '../db/supabase.js';
// Extend Express Request to include customer data
declare global {
namespace Express {
interface Request {
customer?: {
id: string;
email: string;
subscription_status: string;
};
}
}
}
export async function authenticateToken(
req: Request,
res: Response,
next: NextFunction
): Promise<void> {
// Get token from Authorization header
const authHeader = req.headers.authorization;
const token = authHeader && authHeader.startsWith('Bearer ')
? authHeader.substring(7)
: null;
// No token provided
if (!token) {
res.status(401).json({
error: 'Unauthorized',
message: 'Missing access token. Please provide a valid Bearer token in the Authorization header.',
});
return;
}
// Invalid token format
if (!isValidTokenFormat(token)) {
res.status(401).json({
error: 'Unauthorized',
message: 'Invalid token format.',
});
return;
}
// Look up customer by token
const customer = await getCustomerByToken(token);
if (!customer) {
res.status(401).json({
error: 'Unauthorized',
message: 'Invalid or expired access token.',
});
return;
}
// Check subscription status
if (customer.subscription_status !== 'active' && customer.subscription_status !== 'trialing') {
res.status(403).json({
error: 'Forbidden',
message: `Subscription is ${customer.subscription_status}. Please update your subscription to continue.`,
});
return;
}
// Attach customer to request
req.customer = {
id: customer.id,
email: customer.email,
subscription_status: customer.subscription_status,
};
next();
}