|
10 | 10 | import asyncio
|
11 | 11 | import secrets
|
12 | 12 | from datetime import datetime, timezone
|
13 |
| -from typing import Optional, cast |
| 13 | +from typing import List, Optional, Tuple, cast |
14 | 14 |
|
15 | 15 | import fastapi
|
16 | 16 | from fastapi import HTTPException, Request, WebSocket, status
|
|
89 | 89 | )
|
90 | 90 |
|
91 | 91 |
|
| 92 | +def _get_bearer_token_or_received_api_key(api_key: str) -> str: |
| 93 | + if api_key.startswith("Bearer "): # ensure Bearer token passed in |
| 94 | + api_key = api_key.replace("Bearer ", "") # extract the token |
| 95 | + elif api_key.startswith("Basic "): |
| 96 | + api_key = api_key.replace("Basic ", "") # handle langfuse input |
| 97 | + elif api_key.startswith("bearer "): |
| 98 | + api_key = api_key.replace("bearer ", "") |
| 99 | + |
| 100 | + return api_key |
| 101 | + |
| 102 | + |
92 | 103 | def _get_bearer_token(
|
93 | 104 | api_key: str,
|
94 | 105 | ):
|
@@ -217,6 +228,53 @@ def get_rbac_role(jwt_handler: JWTHandler, scopes: List[str]) -> str:
|
217 | 228 | return LitellmUserRoles.TEAM
|
218 | 229 |
|
219 | 230 |
|
| 231 | +def get_api_key( |
| 232 | + custom_litellm_key_header: Optional[str], |
| 233 | + api_key: str, |
| 234 | + azure_api_key_header: Optional[str], |
| 235 | + anthropic_api_key_header: Optional[str], |
| 236 | + google_ai_studio_api_key_header: Optional[str], |
| 237 | + azure_apim_header: Optional[str], |
| 238 | + pass_through_endpoints: Optional[List[dict]], |
| 239 | + route: str, |
| 240 | + request: Request, |
| 241 | +) -> Tuple[str, Optional[str]]: |
| 242 | + """ |
| 243 | + Returns: |
| 244 | + Tuple[Optional[str], Optional[str]]: Tuple of the api_key and the passed_in_key |
| 245 | + """ |
| 246 | + api_key = api_key |
| 247 | + passed_in_key: Optional[str] = None |
| 248 | + if isinstance(custom_litellm_key_header, str): |
| 249 | + passed_in_key = custom_litellm_key_header |
| 250 | + api_key = _get_bearer_token_or_received_api_key(custom_litellm_key_header) |
| 251 | + elif isinstance(api_key, str): |
| 252 | + passed_in_key = api_key |
| 253 | + api_key = _get_bearer_token(api_key=api_key) |
| 254 | + elif isinstance(azure_api_key_header, str): |
| 255 | + passed_in_key = azure_api_key_header |
| 256 | + api_key = azure_api_key_header |
| 257 | + elif isinstance(anthropic_api_key_header, str): |
| 258 | + passed_in_key = anthropic_api_key_header |
| 259 | + api_key = anthropic_api_key_header |
| 260 | + elif isinstance(google_ai_studio_api_key_header, str): |
| 261 | + passed_in_key = google_ai_studio_api_key_header |
| 262 | + api_key = google_ai_studio_api_key_header |
| 263 | + elif isinstance(azure_apim_header, str): |
| 264 | + passed_in_key = azure_apim_header |
| 265 | + api_key = azure_apim_header |
| 266 | + elif pass_through_endpoints is not None: |
| 267 | + for endpoint in pass_through_endpoints: |
| 268 | + if endpoint.get("path", "") == route: |
| 269 | + headers: Optional[dict] = endpoint.get("headers", None) |
| 270 | + if headers is not None: |
| 271 | + header_key: str = headers.get("litellm_user_api_key", "") |
| 272 | + if request.headers.get(key=header_key) is not None: |
| 273 | + api_key = request.headers.get(key=header_key) |
| 274 | + passed_in_key = api_key |
| 275 | + return api_key, passed_in_key |
| 276 | + |
| 277 | + |
220 | 278 | async def _user_api_key_auth_builder( # noqa: PLR0915
|
221 | 279 | request: Request,
|
222 | 280 | api_key: str,
|
@@ -260,28 +318,17 @@ async def _user_api_key_auth_builder( # noqa: PLR0915
|
260 | 318 | )
|
261 | 319 | passed_in_key: Optional[str] = None
|
262 | 320 | ## CHECK IF X-LITELM-API-KEY IS PASSED IN - supercedes Authorization header
|
263 |
| - if isinstance(custom_litellm_key_header, str): |
264 |
| - api_key = custom_litellm_key_header |
265 |
| - elif isinstance(api_key, str): |
266 |
| - passed_in_key = api_key |
267 |
| - api_key = _get_bearer_token(api_key=api_key) |
268 |
| - elif isinstance(azure_api_key_header, str): |
269 |
| - api_key = azure_api_key_header |
270 |
| - elif isinstance(anthropic_api_key_header, str): |
271 |
| - api_key = anthropic_api_key_header |
272 |
| - elif isinstance(google_ai_studio_api_key_header, str): |
273 |
| - api_key = google_ai_studio_api_key_header |
274 |
| - elif isinstance(azure_apim_header, str): |
275 |
| - api_key = azure_apim_header |
276 |
| - elif pass_through_endpoints is not None: |
277 |
| - for endpoint in pass_through_endpoints: |
278 |
| - if endpoint.get("path", "") == route: |
279 |
| - headers: Optional[dict] = endpoint.get("headers", None) |
280 |
| - if headers is not None: |
281 |
| - header_key: str = headers.get("litellm_user_api_key", "") |
282 |
| - if request.headers.get(key=header_key) is not None: |
283 |
| - api_key = request.headers.get(key=header_key) |
284 |
| - |
| 321 | + api_key, passed_in_key = get_api_key( |
| 322 | + custom_litellm_key_header=custom_litellm_key_header, |
| 323 | + api_key=api_key, |
| 324 | + azure_api_key_header=azure_api_key_header, |
| 325 | + anthropic_api_key_header=anthropic_api_key_header, |
| 326 | + google_ai_studio_api_key_header=google_ai_studio_api_key_header, |
| 327 | + azure_apim_header=azure_apim_header, |
| 328 | + pass_through_endpoints=pass_through_endpoints, |
| 329 | + route=route, |
| 330 | + request=request, |
| 331 | + ) |
285 | 332 | # if user wants to pass LiteLLM_Master_Key as a custom header, example pass litellm keys as X-LiteLLM-Key: Bearer sk-1234
|
286 | 333 | custom_litellm_key_header_name = general_settings.get("litellm_key_header_name")
|
287 | 334 | if custom_litellm_key_header_name is not None:
|
|
0 commit comments