@@ -95,17 +95,22 @@ def do_GET(self):
95
95
if qs .get ('code' ) or qs .get ("error" ): # So, it is an auth response
96
96
auth_response = _qs2kv (qs )
97
97
logger .debug ("Got auth response: %s" , auth_response )
98
- template = ( self .server .success_template
99
- if "code" in qs else self . server . error_template )
100
- if _is_html ( template . template ):
101
- safe_data = _escape ( auth_response )
98
+ if self . server . auth_state and self .server .auth_state != auth_response . get ( "state" ):
99
+ # OAuth2 successful and error responses contain state when it was used
100
+ # https://www.rfc-editor.org/rfc/rfc6749#section-4.2.2.1
101
+ self . _send_full_response ( "State mismatch" ) # Possibly an attack
102
102
else :
103
- safe_data = auth_response
104
- self ._send_full_response (template .safe_substitute (** safe_data ))
105
- self .server .auth_response = auth_response # Set it now, after the response is likely sent
106
- # NOTE: Don't do self.server.shutdown() here. It'll halt the server.
103
+ template = (self .server .success_template
104
+ if "code" in qs else self .server .error_template )
105
+ if _is_html (template .template ):
106
+ safe_data = _escape (auth_response ) # Foiling an XSS attack
107
+ else :
108
+ safe_data = auth_response
109
+ self ._send_full_response (template .safe_substitute (** safe_data ))
110
+ self .server .auth_response = auth_response # Set it now, after the response is likely sent
107
111
else :
108
112
self ._send_full_response (self .server .welcome_page )
113
+ # NOTE: Don't do self.server.shutdown() here. It'll halt the server.
109
114
110
115
def _send_full_response (self , body , is_ok = True ):
111
116
self .send_response (200 if is_ok else 400 )
@@ -295,16 +300,14 @@ def _get_auth_response(self, result, auth_uri=None, timeout=None, state=None,
295
300
296
301
self ._server .timeout = timeout # Otherwise its handle_timeout() won't work
297
302
self ._server .auth_response = {} # Shared with _AuthCodeHandler
303
+ self ._server .auth_state = state # So handler will check it before sending response
298
304
while not self ._closing : # Otherwise, the handle_request() attempt
299
305
# would yield noisy ValueError trace
300
306
# Derived from
301
307
# https://docs.python.org/2/library/basehttpserver.html#more-examples
302
308
self ._server .handle_request ()
303
309
if self ._server .auth_response :
304
- if state and state != self ._server .auth_response .get ("state" ):
305
- logger .debug ("State mismatch. Ignoring this noise." )
306
- else :
307
- break
310
+ break
308
311
result .update (self ._server .auth_response ) # Return via writable result param
309
312
310
313
def close (self ):
0 commit comments