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
}