@@ -90,23 +90,42 @@ async def error_response(
9090 error_description : str | None ,
9191 attempt_load_client : bool = True ,
9292 ):
93+ # Error responses take two different formats:
94+ # 1. The request has a valid client ID & redirect_uri: we issue a redirect
95+ # back to the redirect_uri with the error response fields as query
96+ # parameters. This allows the client to be notified of the error.
97+ # 2. Otherwise, we return an error response directly to the end user;
98+ # we choose to do so in JSON, but this is left undefined in the
99+ # specification.
100+ # See https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1
101+ #
102+ # This logic is a bit awkward to handle, because the error might be thrown
103+ # very early in request validation, before we've done the usual Pydantic
104+ # validation, loaded the client, etc. To handle this, error_response()
105+ # contains fallback logic which attempts to load the parameters directly
106+ # from the request.
107+
93108 nonlocal client , redirect_uri , state
94109 if client is None and attempt_load_client :
95110 # make last-ditch attempt to load the client
96111 client_id = best_effort_extract_string ("client_id" , params )
97112 client = client_id and await self .provider .get_client (client_id )
98113 if redirect_uri is None and client :
99114 # make last-ditch effort to load the redirect uri
100- if params is not None and "redirect_uri" not in params :
101- raw_redirect_uri = None
102- else :
103- raw_redirect_uri = AnyHttpUrlModel .model_validate (
104- best_effort_extract_string ("redirect_uri" , params )
105- ).root
106115 try :
116+ if params is not None and "redirect_uri" not in params :
117+ raw_redirect_uri = None
118+ else :
119+ raw_redirect_uri = AnyHttpUrlModel .model_validate (
120+ best_effort_extract_string ("redirect_uri" , params )
121+ ).root
107122 redirect_uri = client .validate_redirect_uri (raw_redirect_uri )
108123 except (ValidationError , InvalidRedirectUriError ):
124+ # if the redirect URI is invalid, ignore it & just return the
125+ # initial error
109126 pass
127+
128+ # the error response MUST contain the state specified by the client, if any
110129 if state is None :
111130 # make last-ditch effort to load state
112131 state = best_effort_extract_string ("state" , params )
0 commit comments