@@ -40,22 +40,25 @@ Examples:
4040""" )
4141 sys .exit (0 )
4242
43- import trustme
44- import http .server
43+ import keyring
4544import os
46- import threading
4745import urllib .parse
48- import tempfile
49- import random
50- import keyring
51- import ssl
5246
5347from msal import PublicClientApplication
5448
55- ClientId = "9e5f94bc-e8a4-4e73-b8be-63364c29d753"
49+ # https://github.com/mozilla/releases-comm-central/blob/master/mailnews/base/src/OAuth2Providers.sys.mjs
50+ ClientId_Thunderbird = "9e5f94bc-e8a4-4e73-b8be-63364c29d753"
51+
52+ # https://gitlab.gnome.org/GNOME/evolution-data-server/-/commit/7554d3b95124486ac98d9a5052e069e46242a216
53+ ClientId_Evolution = "cc6e0693-0e26-4220-8322-9d363e308fc6"
54+
5655Scopes = ['https://outlook.office.com/POP.AccessAsUser.All' ,'https://outlook.office.com/IMAP.AccessAsUser.All' ,'https://outlook.office.com/SMTP.Send' ]
5756ServiceName = "git-credential-outlook"
5857
58+ # ClientId to be used
59+
60+ ClientId = ClientId_Thunderbird
61+
5962def save_refresh_token (refresh_token ):
6063 keyring .set_password (ServiceName , "refresh_token" , refresh_token )
6164
@@ -81,76 +84,47 @@ if "--authenticate" in sys.argv:
8184 from PyQt6 .QtWebEngineWidgets import QWebEngineView
8285 from PyQt6 .QtCore import QUrl , QLoggingCategory
8386
84- random_port = random .randint (1024 , 65535 )
85- redirect_uri = f"https://localhost:{ random_port } /"
87+ redirect_uri = f"https://login.live.com/oauth20_desktop.srf"
8688
8789 url = app .get_authorization_request_url (Scopes , redirect_uri = redirect_uri )
8890
89- print ("Navigate to the following url in a web browser, if doesn't open automatically:\n " )
90- print (f"{ url } \n " )
91-
92- class Handler (http .server .BaseHTTPRequestHandler ):
93- def log_message (self , format , * args ):
94- # Override to prevent logging to console
95- pass
96- def do_GET (self ):
97- parsed_url = urllib .parse .urlparse (self .path )
98- parsed_query = urllib .parse .parse_qs (parsed_url .query )
99- global code
100- code = parsed_query .get ('code' , ['' ])[0 ]
101- response_body = b'Success. You may close this window now.\r \n '
102- self .send_response (200 )
103- self .send_header ('Content-Type' , 'text/plain' )
104- self .send_header ('Content-Length' , len (response_body ))
105- self .end_headers ()
106- self .wfile .write (response_body )
107-
108- global httpd
109- threading .Thread (target = lambda : httpd .shutdown ()).start ()
110-
111-
112- code = ''
113-
114- ca = trustme .CA ()
115- cert_file = os .path .join (tempfile .gettempdir (), "cert.crt" )
116- server_cert = ca .issue_cert ("localhost" )
117- server_cert .private_key_and_cert_chain_pem .write_to_path (cert_file )
118-
119- server_address = ('' , random_port )
120- httpd = http .server .HTTPServer (server_address , Handler )
121- context = ssl .SSLContext (ssl .PROTOCOL_TLS_SERVER )
122- context .load_cert_chain (cert_file )
123- httpd .socket = context .wrap_socket (
124- httpd .socket ,
125- server_side = True ,
126- )
127-
128- threading .Thread (target = httpd .serve_forever , daemon = True ).start ()
129-
13091 if "--verbose" in sys .argv :
13192 loglevel = 0
13293 else :
13394 loglevel = 3
13495 QLoggingCategory ("qt.webenginecontext" ).setFilterRules ("*.info=false" ) # Suppress info logs
13596
136- os .environ ["QTWEBENGINE_CHROMIUM_FLAGS" ] = f"--enable-logging --log-level={ loglevel } --ignore-certificate-errors"
97+ os .environ ["QTWEBENGINE_CHROMIUM_FLAGS" ] = f"--enable-logging --log-level={ loglevel } "
98+
99+ print ("Opening a browser window for authentication...\n " )
100+
101+ code = ''
137102
138103 class BrowserWindow (QMainWindow ):
104+
105+ def handle_url_change (self , url ):
106+ if "code=" in url .toString ():
107+ parsed_url = urllib .parse .urlparse (url .toString ())
108+ parsed_query = urllib .parse .parse_qs (parsed_url .query )
109+ global code
110+ code = parsed_query .get ('code' , ['' ])[0 ]
111+ self .close ()
112+
139113 def __init__ (self ):
140114 super ().__init__ ()
141115 self .setWindowTitle ("OAuth2 Login" )
142116 self .resize (800 , 600 )
143117 self .browser = QWebEngineView ()
144118 self .setCentralWidget (self .browser )
145119 self .browser .load (QUrl (url ))
120+ self .browser .urlChanged .connect (self .handle_url_change )
146121 self .show ()
147122
148123 webapp = QApplication (sys .argv )
149124 window = BrowserWindow ()
150125 webapp .exec ()
151126
152127 token = app .acquire_token_by_authorization_code (code , Scopes , redirect_uri = redirect_uri )
153- os .remove (cert_file )
154128
155129 if 'error' in token :
156130 print (token )
0 commit comments