Created
March 11, 2021 17:42
-
-
Save anderson-marques/bb86adfccf7ddb9cf6a74331053fddcf to your computer and use it in GitHub Desktop.
oauth2_device_flow.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| OAuth2 Device Flow adaptation from Implicit Flow - Useful for CLIs | |
| """ | |
| from http.server import SimpleHTTPRequestHandler, HTTPServer | |
| import os | |
| from os.path import expanduser | |
| import json | |
| callback_html = """ | |
| <body style="font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif"> | |
| <script> | |
| let originalHash = window.location.hash; | |
| window.location.hash = ''; | |
| let accessToken; | |
| if (originalHash.split('#').length == 2) { | |
| for (var param of originalHash.split('#')[1].split('&')){ | |
| let paramName = param.split('=')[0] | |
| let paramValue = param.split('=')[1] | |
| if (paramName === 'access_token'){ | |
| accessToken = paramValue; | |
| } | |
| } | |
| } | |
| if (accessToken !== undefined) { | |
| let title = document.createElement('h4'); | |
| title.textContent = 'Copy the device code and paste in the terminal:'; | |
| let deviceCode = document.createElement('p'); | |
| deviceCode.textContent = accessToken; | |
| document.body.appendChild(title); | |
| document.body.appendChild(deviceCode); | |
| } else { | |
| let title = document.createElement('h4'); | |
| title.textContent = 'Not autenticated!' | |
| document.body.appendChild(title); | |
| } | |
| </script> | |
| </body> | |
| """ | |
| config_folder_name = 'device_flow' | |
| config_file_name = 'config' | |
| class OAuth2CallbackHandler( SimpleHTTPRequestHandler ): | |
| def do_GET(self): | |
| if (self.path == '/cb'): | |
| self.send_response(200) | |
| self.send_header('Content-type', 'text/html') | |
| self.send_header("Content-Length", str(len(callback_html))) | |
| self.end_headers() | |
| self.wfile.write(callback_html.encode('utf-8')) | |
| access_token = input("Enter the code value: ") | |
| home = expanduser("~") | |
| config_path = f'{home}/.{config_folder_name}' | |
| file_path = f"{config_path}/{config_file_name}.json" | |
| if not os.path.exists(config_path): | |
| os.makedirs(config_path) | |
| f = open(file_path, "a") | |
| config = { "access_token": f'{access_token}' } | |
| f.write(json.dumps(config)) | |
| f.close() | |
| self.server.server_close() | |
| print("\nUser authenticated!") | |
| exit(0) | |
| def login(config={}): | |
| base_url = config['base_url'] | |
| client_id = config['client_id'] | |
| redirect_uri = config['redirect_uri'] | |
| state = config['state'] | |
| scope = config['scope'] | |
| port = config['port'] if 'port' in config.keys() else 4321 | |
| if 'folder_name' in config.keys(): | |
| global config_folder_name | |
| config_folder_name = config['folder_name'] | |
| if 'file_name' in config.keys(): | |
| global config_file_name | |
| config_file_name = config['file_name'] | |
| login_url = f'{base_url}?client_id={client_id}&redirect_uri={redirect_uri}&response_type=token&state={state}&scope={scope}' | |
| print(f'\nCopy and paste this in your browser: \n\n\t{login_url}') | |
| httpd = HTTPServer(('', port), OAuth2CallbackHandler) | |
| try: | |
| httpd.serve_forever() | |
| except KeyboardInterrupt: | |
| pass | |
| httpd.server_close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment