Files
Genarrative/server-node/src/middleware/auth.ts
2026-04-21 10:30:12 +08:00

46 lines
1.5 KiB
TypeScript

import type { NextFunction, Request, Response } from 'express';
import { readAccessSessionToken } from '../auth/accessSessionCookie.js';
import { verifyAccessToken } from '../auth/token.js';
import type { AppConfig } from '../config.js';
import { unauthorized } from '../errors.js';
import { type UserRepository } from '../repositories/userRepository.js';
function readBearerToken(request: Request) {
const authorization = request.header('authorization')?.trim() || '';
if (!authorization.startsWith('Bearer ')) {
return '';
}
return authorization.slice('Bearer '.length).trim();
}
export function requireJwtAuth(config: AppConfig, userRepository: UserRepository) {
return async (request: Request, _response: Response, next: NextFunction) => {
try {
const token =
readBearerToken(request) || readAccessSessionToken(request, config);
if (!token) {
throw unauthorized('缺少登录凭证');
}
const claims = await verifyAccessToken(token, config);
const user = await userRepository.findById(claims.userId);
if (!user) {
throw unauthorized('用户不存在');
}
if (user.accountStatus === 'disabled') {
throw unauthorized('账号已被禁用');
}
if (user.tokenVersion !== claims.tokenVersion) {
throw unauthorized('登录状态已失效,请重新登录');
}
request.auth = claims;
request.userId = claims.userId;
next();
} catch (error) {
next(error);
}
};
}