@@ -36,25 +36,11 @@ def obtain_auth_code(listen_port, auth_uri=None):
36
36
:param auth_uri: If provided, this function will try to open a local browser.
37
37
:return: Hang indefinitely, until it receives and then return the auth code.
38
38
"""
39
- exit_hint = "Visit http://localhost:{p}?code=exit to abort" .format (p = listen_port )
40
- logger .warning (exit_hint )
41
39
if auth_uri :
42
- page = "http://localhost:{p}?{q}" .format (p = listen_port , q = urlencode ({
43
- "text" : "Open this link to sign in. You may use incognito window" ,
44
- "link" : auth_uri ,
45
- "exit_hint" : exit_hint ,
46
- }))
47
40
browse (auth_uri )
48
- server = HTTPServer (("" , int (listen_port )), AuthCodeReceiver )
49
- try :
50
- server .authcode = None
51
- while not server .authcode :
52
- # Derived from
53
- # https://docs.python.org/2/library/basehttpserver.html#more-examples
54
- server .handle_request ()
55
- return server .authcode , server .state
56
- finally :
57
- server .server_close ()
41
+ server = AuthcodeRedirectServer (int (listen_port ))
42
+ return server .get_auth_code ()
43
+
58
44
59
45
def browse (auth_uri ):
60
46
controller = webbrowser .get () # Get a default controller
@@ -69,15 +55,16 @@ def browse(auth_uri):
69
55
logger .info ("Please open a browser on THIS device to visit: %s" % auth_uri )
70
56
controller .open (auth_uri )
71
57
58
+
72
59
class AuthCodeReceiver (BaseHTTPRequestHandler ):
73
60
def do_GET (self ):
74
61
# For flexibility, we choose to not check self.path matching redirect_uri
75
62
#assert self.path.startswith('/THE_PATH_REGISTERED_BY_THE_APP')
76
63
qs = parse_qs (urlparse (self .path ).query )
77
64
if qs .get ('code' ): # Then store it into the server instance
78
- ac = self .server .authcode = qs ['code' ][0 ]
79
- self .server .state = qs [ 'state' ] [0 ]
80
- self ._send_full_response ('Authcode: \n {}' . format ( ac )) #This is where the exit message will go
65
+ self .server .auth_code = qs ['code' ][0 ]
66
+ self .server .state = qs . get ( 'state' , [ None ]) [0 ]
67
+ self ._send_full_response ('Authentication complete. You can close this window' )
81
68
# NOTE: Don't do self.server.shutdown() here. It'll halt the server.
82
69
elif qs .get ('text' ) and qs .get ('link' ): # Then display a landing page
83
70
self ._send_full_response (
@@ -96,6 +83,32 @@ def _send_full_response(self, body, is_ok=True):
96
83
self .wfile .write (body .encode ("utf-8" ))
97
84
98
85
86
+ class AuthcodeRedirectServer (HTTPServer ):
87
+
88
+ def __init__ (self , port ):
89
+ HTTPServer .__init__ (self , ("" , port ), AuthCodeReceiver )
90
+ self .state = None
91
+ self .auth_code = None
92
+ self .timeout = 300
93
+
94
+ def get_auth_code (self ):
95
+ try :
96
+ while not self .auth_code :
97
+ try :
98
+ # Derived from
99
+ # https://docs.python.org/2/library/basehttpserver.html#more-examples
100
+ self .handle_request ()
101
+ except ValueError :
102
+ break
103
+ finally :
104
+ self .server_close ()
105
+
106
+ return self .auth_code , self .state
107
+
108
+ def handle_timeout (self ):
109
+ """Break the request-handling loop by tearing down the server"""
110
+ self .server_close ()
111
+
99
112
if __name__ == '__main__' :
100
113
logging .basicConfig (level = logging .INFO )
101
114
p = parser = argparse .ArgumentParser (
0 commit comments