1+ import os
2+ import requests
3+ import jwt
4+ import time
5+ import json
6+ import webbrowser
7+ import http .server
8+ from urllib .parse import urlencode , parse_qs
9+
10+ def get_discovery_document (url ):
11+ response = requests .get (url )
12+ return response .json ()
13+
14+
15+ def request_device_code (discovery_doc , client_credentials ):
16+ data = {}
17+ data .update (client_credentials )
18+ data .update ({'scope' : 'offline_access' })
19+ response = requests .post (
20+ discovery_doc ["device_authorization_endpoint" ], data = data
21+ )
22+ if response .status_code == 200 :
23+ return response .json ()
24+ else :
25+ print (f"Failed to obtain device code. Status code: { response .status_code } " )
26+ print (f"Response content: { response .content } " )
27+ return None
28+
29+
30+
31+ def poll_for_access_token (
32+ discovery_doc , client_credentials , device_code , interval , timeout
33+ ):
34+ payload = {
35+ "grant_type" : "urn:ietf:params:oauth:grant-type:device_code" ,
36+ "device_code" : device_code ,
37+ "client_id" : client_credentials ["client_id" ]
38+ }
39+ start_time = time .time ()
40+ print ("\n Waiting for device to be authorized ..." )
41+ while time .time () - start_time < timeout :
42+ response = requests .post (discovery_doc ["token_endpoint" ], data = payload )
43+ if response .status_code == 200 :
44+ return response .json ()
45+ elif response .status_code == 400 :
46+ error = response .json ().get ("error" , "" )
47+ if error == "authorization_pending" :
48+ print ("Waiting for device to be authorized ..." )
49+ time .sleep (interval )
50+ else :
51+ return None
52+ else :
53+ return None
54+
55+
56+ def device_login (discovery_doc , client_credentials ):
57+ device_code_response = request_device_code (discovery_doc , client_credentials )
58+ if device_code_response :
59+ verification_uri_complete = device_code_response .get ("verification_uri_complete" , None )
60+ webbrowser .open (verification_uri_complete )
61+ if verification_uri_complete :
62+ print (
63+ f"The following URL has been opened in your browser: { verification_uri_complete } "
64+ )
65+ else :
66+ print (f"Something went wrong" )
67+
68+
69+ interval = device_code_response ["interval" ]
70+ timeout = device_code_response ["expires_in" ]
71+ device_login = poll_for_access_token (
72+ discovery_doc ,
73+ client_credentials ,
74+ device_code_response ["device_code" ],
75+ interval ,
76+ timeout ,
77+ )
78+ if device_login :
79+ print ("Device login successfull" )
80+ return device_login
81+ else :
82+ print ("Failed to obtain an device login" )
83+ return None
84+ else :
85+ print ("Failed to obtain device code" )
86+ return None
0 commit comments