File size: 2,795 Bytes
1f21206 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | /**
* Authentication middleware
*
* 本地桌面应用场景下,使用 Anthropic API Key 做简单鉴权。
* 验证请求头中的 Authorization: Bearer <key> 与 .env 中的 ANTHROPIC_API_KEY 是否匹配。
*/
import { H5AccessService } from '../services/h5AccessService.js'
type AuthResult = { valid: boolean; error?: string }
function parseBearerToken(authHeader: string | null): AuthResult & { token?: string } {
if (!authHeader) {
return { valid: false, error: 'Missing Authorization header' }
}
const [scheme, token] = authHeader.split(' ')
if (scheme !== 'Bearer' || !token) {
return { valid: false, error: 'Invalid Authorization format. Use: Bearer <token>' }
}
return { valid: true, token }
}
export function validateAuth(req: Request): AuthResult {
const parsedAuth = parseBearerToken(req.headers.get('Authorization'))
if (!parsedAuth.valid || !parsedAuth.token) {
return parsedAuth
}
const apiKey = process.env.ANTHROPIC_API_KEY
if (!apiKey) {
return { valid: false, error: 'Server ANTHROPIC_API_KEY not configured' }
}
if (parsedAuth.token !== apiKey) {
return { valid: false, error: 'Invalid API key' }
}
return { valid: true }
}
/**
* Helper to check auth and return 401 if invalid
*/
export async function validateRequestAuth(
req: Request,
tokenOverride?: string | null,
): Promise<AuthResult> {
const anthropicAuth = validateAuth(req)
if (anthropicAuth.valid) {
return anthropicAuth
}
const parsedAuth = parseBearerToken(req.headers.get('Authorization'))
const h5Token = tokenOverride ?? parsedAuth.token
if (h5Token) {
const h5AccessService = new H5AccessService()
if (await h5AccessService.validateToken(h5Token)) {
return { valid: true }
}
return { valid: false, error: 'Invalid H5 access token' }
}
return anthropicAuth
}
export async function requireAuth(req: Request, tokenOverride?: string | null): Promise<Response | null> {
const { valid, error } = await validateRequestAuth(req, tokenOverride)
if (!valid) {
return Response.json({ error: 'Unauthorized', message: error }, { status: 401 })
}
return null
}
export async function requireH5Token(req: Request, tokenOverride?: string | null): Promise<Response | null> {
const parsedAuth = parseBearerToken(req.headers.get('Authorization'))
const h5Token = tokenOverride ?? parsedAuth.token
if (!h5Token) {
return Response.json(
{ error: 'Unauthorized', message: 'Missing H5 access token' },
{ status: 401 },
)
}
const h5AccessService = new H5AccessService()
if (!await h5AccessService.validateToken(h5Token)) {
return Response.json(
{ error: 'Unauthorized', message: 'Invalid H5 access token' },
{ status: 401 },
)
}
return null
}
|