MCPcopy Create free account
hub / github.com/21st-dev/21st-sdk / authMiddleware

Function authMiddleware

apps/relay/src/auth.ts:20–136  ·  view source on GitHub ↗
(req: Request, res: Response, next: NextFunction)

Source from the content-addressed store, hash-verified

18}
19
20export async function authMiddleware(req: Request, res: Response, next: NextFunction) {
21 const authHeader = req.headers.authorization;
22 if (!authHeader?.startsWith('Bearer ')) {
23 res.status(401).json({ error: 'Missing or invalid Authorization header' });
24 return;
25 }
26
27 const key = authHeader.slice(7);
28 const keyHash = hashApiKey(key);
29
30 let teamId: string | undefined;
31
32 if (key.startsWith('an_t_')) {
33 // JWT token — local verification, no DB lookup
34 const jwt = key.slice(5);
35 try {
36 const { payload } = await jwtVerify(jwt, getJwtSecret());
37 teamId = payload.team_id as string;
38 (req as any).tokenClaims = payload;
39 } catch {
40 res.status(401).json({ error: 'Invalid or expired token' });
41 return;
42 }
43 } else if (isAgentApiKey(key)) {
44 // Current 21st keys and legacy an_sk_ keys share the an_api_keys table.
45 const [anKey] = await db
46 .select()
47 .from(anApiKeys)
48 .where(or(eq(anApiKeys.key_hash, keyHash), eq(anApiKeys.key, key)))
49 .limit(1);
50
51 if (!anKey) {
52 res.status(401).json({ error: 'Invalid API key' });
53 return;
54 }
55 if (!anKey.is_active) {
56 res.status(403).json({ error: 'API key is inactive' });
57 return;
58 }
59 if (anKey.expires_at && anKey.expires_at < new Date()) {
60 res.status(403).json({ error: 'API key has expired' });
61 return;
62 }
63
64 teamId = anKey.team_id;
65 (req as any).apiKeySource = 'an';
66
67 db.update(anApiKeys)
68 .set({ last_used_at: new Date() })
69 .where(eq(anApiKeys.id, anKey.id))
70 .then(() => {})
71 .catch((err) => console.error('[AUTH] Failed to update last_used_at:', err));
72
73 (req as any).apiKey = anKey;
74 } else {
75 // Try proxy JWT (RS256) first, fall through to legacy API key
76 let resolved = false;
77 try {

Callers 1

auth.test.tsFile · 0.85

Calls 5

hashApiKeyFunction · 0.90
isAgentApiKeyFunction · 0.90
getJwtSecretFunction · 0.85
getProxyPublicKeyFunction · 0.85
setMethod · 0.65

Tested by

no test coverage detected