mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 07:09:11 +02:00
Fix OAuth proxy override typing (#4612)
This commit is contained in:
parent
c556f07a66
commit
d8ac6cbfde
2 changed files with 37 additions and 40 deletions
|
|
@ -13,9 +13,8 @@ import hmac
|
|||
import json
|
||||
import secrets
|
||||
import time
|
||||
from base64 import urlsafe_b64encode
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from urllib.parse import urlencode, urlparse
|
||||
from typing import TYPE_CHECKING
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from pydantic import AnyUrl
|
||||
from starlette.requests import Request
|
||||
|
|
@ -277,43 +276,6 @@ class ConsentMixin:
|
|||
return False
|
||||
return hmac.compare_digest(actual, expected_token)
|
||||
|
||||
def _build_upstream_authorize_url(
|
||||
self: OAuthProxy, txn_id: str, transaction: dict[str, Any]
|
||||
) -> str:
|
||||
"""Construct the upstream IdP authorization URL using stored transaction data."""
|
||||
query_params: dict[str, Any] = {
|
||||
"response_type": "code",
|
||||
"client_id": self._upstream_client_id,
|
||||
"redirect_uri": f"{str(self.base_url).rstrip('/')}{self._redirect_path}",
|
||||
"state": txn_id,
|
||||
}
|
||||
|
||||
scopes_to_use = transaction.get("scopes") or self.required_scopes or []
|
||||
if scopes_to_use:
|
||||
query_params["scope"] = " ".join(scopes_to_use)
|
||||
|
||||
# If PKCE forwarding was enabled, include the proxy challenge
|
||||
proxy_code_verifier = transaction.get("proxy_code_verifier")
|
||||
if proxy_code_verifier:
|
||||
challenge_bytes = hashlib.sha256(proxy_code_verifier.encode()).digest()
|
||||
proxy_code_challenge = (
|
||||
urlsafe_b64encode(challenge_bytes).decode().rstrip("=")
|
||||
)
|
||||
query_params["code_challenge"] = proxy_code_challenge
|
||||
query_params["code_challenge_method"] = "S256"
|
||||
|
||||
# Forward resource indicator if present in transaction
|
||||
if self._forward_resource:
|
||||
if resource := transaction.get("resource"):
|
||||
query_params["resource"] = resource
|
||||
|
||||
# Extra configured parameters
|
||||
if self._extra_authorize_params:
|
||||
query_params.update(self._extra_authorize_params)
|
||||
|
||||
separator = "&" if "?" in self._upstream_authorization_endpoint else "?"
|
||||
return f"{self._upstream_authorization_endpoint}{separator}{urlencode(query_params)}"
|
||||
|
||||
async def _handle_consent(
|
||||
self: OAuthProxy, request: Request
|
||||
) -> HTMLResponse | RedirectResponse:
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ from collections import OrderedDict
|
|||
from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any, Literal
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import anyio
|
||||
import httpx2
|
||||
|
|
@ -789,6 +790,40 @@ class OAuthProxy(OAuthProvider, ConsentMixin):
|
|||
|
||||
return code_verifier, code_challenge
|
||||
|
||||
def _build_upstream_authorize_url(
|
||||
self, txn_id: str, transaction: dict[str, Any]
|
||||
) -> str:
|
||||
"""Construct the upstream IdP authorization URL using stored transaction data."""
|
||||
query_params: dict[str, Any] = {
|
||||
"response_type": "code",
|
||||
"client_id": self._upstream_client_id,
|
||||
"redirect_uri": f"{str(self.base_url).rstrip('/')}{self._redirect_path}",
|
||||
"state": txn_id,
|
||||
}
|
||||
|
||||
scopes_to_use = transaction.get("scopes") or self.required_scopes or []
|
||||
if scopes_to_use:
|
||||
query_params["scope"] = " ".join(scopes_to_use)
|
||||
|
||||
proxy_code_verifier = transaction.get("proxy_code_verifier")
|
||||
if proxy_code_verifier:
|
||||
challenge_bytes = hashlib.sha256(proxy_code_verifier.encode()).digest()
|
||||
proxy_code_challenge = (
|
||||
urlsafe_b64encode(challenge_bytes).decode().rstrip("=")
|
||||
)
|
||||
query_params["code_challenge"] = proxy_code_challenge
|
||||
query_params["code_challenge_method"] = "S256"
|
||||
|
||||
if self._forward_resource:
|
||||
if resource := transaction.get("resource"):
|
||||
query_params["resource"] = resource
|
||||
|
||||
if self._extra_authorize_params:
|
||||
query_params.update(self._extra_authorize_params)
|
||||
|
||||
separator = "&" if "?" in self._upstream_authorization_endpoint else "?"
|
||||
return f"{self._upstream_authorization_endpoint}{separator}{urlencode(query_params)}"
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Client Registration (Local Implementation)
|
||||
# -------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue