A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 05:30 UTC
Validate API tokens in constant time (#25781)
Signed-off-by: rentianyue-jk <rentianyue-jk@360shuke.com> Signed-off-by: Russell Bryant <rbryant@redhat.com> Co-authored-by: rentianyue-jk <rentianyue-jk@360shuke.com>
Russell Bryant committed
Sep 27, 2025 at 06:09 UTC
3f5d902d2a6fa752925d49b8c219b9515b37c0a6
1 file changed
+24
-4
vllm/entrypoints/openai/api_server.py
+24
-4
@@ -3,12 +3,14 @@
3
4
import asyncio
5
import gc
6
+import hashlib
7
import importlib
8
import inspect
9
import json
10
import multiprocessing
11
import multiprocessing.forkserver as forkserver
12
import os
13
+import secrets
14
import signal
15
import socket
16
import tempfile
@@ -1252,7 +1254,7 @@ def load_log_config(log_config_file: Optional[str]) -> Optional[dict]:
1254
class AuthenticationMiddleware:
1255
"""
1256
Pure ASGI middleware that authenticates each request by checking
1255
- if the Authorization header exists and equals "Bearer {api_key}".
1257
+ if the Authorization Bearer token exists and equals anyof "{api_key}".
1258
1259
Notes
1260
-----
@@ -1263,7 +1265,26 @@ class AuthenticationMiddleware:
1265
1266
def __init__(self, app: ASGIApp, tokens: list[str]) -> None:
1267
self.app = app
1266
- self.api_tokens = {f"Bearer {token}" for token in tokens}
1268
+ self.api_tokens = [
1269
+ hashlib.sha256(t.encode("utf-8")).digest() for t in tokens
1270
+ ]
1271
+
1272
+ def verify_token(self, headers: Headers) -> bool:
1273
+ authorization_header_value = headers.get("Authorization")
1274
+ if not authorization_header_value:
1275
+ return False
1276
+
1277
+ scheme, _, param = authorization_header_value.partition(" ")
1278
+ if scheme.lower() != "bearer":
1279
+ return False
1280
+
1281
+ param_hash = hashlib.sha256(param.encode("utf-8")).digest()
1282
+
1283
+ token_match = False
1284
+ for token_hash in self.api_tokens:
1285
+ token_match |= secrets.compare_digest(param_hash, token_hash)
1286
+
1287
+ return token_match
1288
1289
def __call__(self, scope: Scope, receive: Receive,
1290
send: Send) -> Awaitable[None]:
@@ -1276,8 +1297,7 @@ class AuthenticationMiddleware:
1297
url_path = URL(scope=scope).path.removeprefix(root_path)
1298
headers = Headers(scope=scope)
1299
# Type narrow to satisfy mypy.
1279
- if url_path.startswith("/v1") and headers.get(
1280
- "Authorization") not in self.api_tokens:
1300
+ if url_path.startswith("/v1") and not self.verify_token(headers):
1301
response = JSONResponse(content={"error": "Unauthorized"},
1302
status_code=401)
1303
return response(scope, receive, send)