|
9 | 9 | from starlette.responses import RedirectResponse, Response
|
10 | 10 |
|
11 | 11 | from mcp.server.auth.errors import (
|
12 |
| - InvalidRequestError, |
13 | 12 | OAuthError,
|
14 | 13 | stringify_pydantic_error,
|
15 | 14 | )
|
|
19 | 18 | OAuthServerProvider,
|
20 | 19 | construct_redirect_uri,
|
21 | 20 | )
|
22 |
| -from mcp.shared.auth import OAuthClientInformationFull |
| 21 | +from mcp.shared.auth import ( |
| 22 | + InvalidRedirectUriError, |
| 23 | + InvalidScopeError, |
| 24 | +) |
23 | 25 |
|
24 | 26 | logger = logging.getLogger(__name__)
|
25 | 27 |
|
@@ -66,37 +68,6 @@ class AuthorizationErrorResponse(BaseModel):
|
66 | 68 | state: str | None = None
|
67 | 69 |
|
68 | 70 |
|
69 |
| -def validate_scope( |
70 |
| - requested_scope: str | None, client: OAuthClientInformationFull |
71 |
| -) -> list[str] | None: |
72 |
| - if requested_scope is None: |
73 |
| - return None |
74 |
| - requested_scopes = requested_scope.split(" ") |
75 |
| - allowed_scopes = [] if client.scope is None else client.scope.split(" ") |
76 |
| - for scope in requested_scopes: |
77 |
| - if scope not in allowed_scopes: |
78 |
| - raise InvalidRequestError(f"Client was not registered with scope {scope}") |
79 |
| - return requested_scopes |
80 |
| - |
81 |
| - |
82 |
| -def validate_redirect_uri( |
83 |
| - redirect_uri: AnyHttpUrl | None, client: OAuthClientInformationFull |
84 |
| -) -> AnyHttpUrl: |
85 |
| - if redirect_uri is not None: |
86 |
| - # Validate redirect_uri against client's registered redirect URIs |
87 |
| - if redirect_uri not in client.redirect_uris: |
88 |
| - raise InvalidRequestError( |
89 |
| - f"Redirect URI '{redirect_uri}' not registered for client" |
90 |
| - ) |
91 |
| - return redirect_uri |
92 |
| - elif len(client.redirect_uris) == 1: |
93 |
| - return client.redirect_uris[0] |
94 |
| - else: |
95 |
| - raise InvalidRequestError( |
96 |
| - "redirect_uri must be specified when client has multiple registered URIs" |
97 |
| - ) |
98 |
| - |
99 |
| - |
100 | 71 | def best_effort_extract_string(
|
101 | 72 | key: str, params: None | FormData | QueryParams
|
102 | 73 | ) -> str | None:
|
@@ -146,8 +117,8 @@ async def error_response(
|
146 | 117 | best_effort_extract_string("redirect_uri", params)
|
147 | 118 | ).root
|
148 | 119 | try:
|
149 |
| - redirect_uri = validate_redirect_uri(raw_redirect_uri, client) |
150 |
| - except (ValidationError, InvalidRequestError): |
| 120 | + redirect_uri = client.validate_redirect_uri(raw_redirect_uri) |
| 121 | + except (ValidationError, InvalidRedirectUriError): |
151 | 122 | pass
|
152 | 123 | if state is None:
|
153 | 124 | # make last-ditch effort to load state
|
@@ -213,22 +184,22 @@ async def error_response(
|
213 | 184 |
|
214 | 185 | # Validate redirect_uri against client's registered URIs
|
215 | 186 | try:
|
216 |
| - redirect_uri = validate_redirect_uri(auth_request.redirect_uri, client) |
217 |
| - except InvalidRequestError as validation_error: |
| 187 | + redirect_uri = client.validate_redirect_uri(auth_request.redirect_uri) |
| 188 | + except InvalidRedirectUriError as validation_error: |
218 | 189 | # For redirect_uri validation errors, return direct error (no redirect)
|
219 | 190 | return await error_response(
|
220 | 191 | error="invalid_request",
|
221 |
| - error_description=validation_error.error_description, |
| 192 | + error_description=validation_error.message, |
222 | 193 | )
|
223 | 194 |
|
224 | 195 | # Validate scope - for scope errors, we can redirect
|
225 | 196 | try:
|
226 |
| - scopes = validate_scope(auth_request.scope, client) |
227 |
| - except InvalidRequestError as validation_error: |
| 197 | + scopes = client.validate_scope(auth_request.scope) |
| 198 | + except InvalidScopeError as validation_error: |
228 | 199 | # For scope errors, redirect with error parameters
|
229 | 200 | return await error_response(
|
230 | 201 | error="invalid_scope",
|
231 |
| - error_description=validation_error.error_description, |
| 202 | + error_description=validation_error.message, |
232 | 203 | )
|
233 | 204 |
|
234 | 205 | # Setup authorization parameters
|
|
0 commit comments