aboutsummaryrefslogtreecommitdiffstats
path: root/cloud_mdir_sync/oauth.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloud_mdir_sync/oauth.py')
-rw-r--r--cloud_mdir_sync/oauth.py60
1 files changed, 60 insertions, 0 deletions
diff --git a/cloud_mdir_sync/oauth.py b/cloud_mdir_sync/oauth.py
new file mode 100644
index 0000000..449d16c
--- /dev/null
+++ b/cloud_mdir_sync/oauth.py
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: GPL-2.0+
+import asyncio
+
+import aiohttp
+import aiohttp.web
+
+
+class WebServer(object):
+ """A small web server is used to manage oauth requests. The user should point a browser
+ window at localhost. The program will generate redirects for the browser to point at
+ OAUTH servers when interactive authentication is required."""
+ url = "http://localhost:8080/"
+ runner = None
+
+ def __init__(self):
+ self.auth_redirs = {}
+ self.web_app = aiohttp.web.Application()
+ self.web_app.router.add_get("/", self._start)
+ self.web_app.router.add_get("/oauth2/msal", self._oauth2_msal)
+
+ async def go(self):
+ self.runner = aiohttp.web.AppRunner(self.web_app)
+ await self.runner.setup()
+ site = aiohttp.web.TCPSite(self.runner, 'localhost', 8080)
+ await site.start()
+
+ async def close(self):
+ if self.runner:
+ await self.runner.cleanup()
+
+ async def auth_redir(self, url, state):
+ """Call as part of an OAUTH flow to hand the URL off to interactive browser
+ based authentication. The flow will resume when the OAUTH server
+ redirects back to the localhost server. The final query paremeters
+ will be returned by this function"""
+ queue = asyncio.Queue()
+ self.auth_redirs[state] = (url, queue)
+ return await queue.get()
+
+ def _start(self, request):
+ """Feed redirects to the web browser until all authing is done. FIXME: Some
+ fancy java script should be used to fetch new interactive auth
+ requests"""
+ for I in self.auth_redirs.values():
+ raise aiohttp.web.HTTPFound(I[0])
+ return aiohttp.web.Response(text="Authentication done")
+
+ def _oauth2_msal(self, request):
+ """Use for the Azure AD authentication response redirection"""
+ state = request.query["state"]
+ try:
+ queue = self.auth_redirs[state][1]
+ del self.auth_redirs[state]
+ queue.put_nowait(request.query)
+ except KeyError:
+ pass
+
+ for I in self.auth_redirs.values():
+ raise aiohttp.web.HTTPFound(I[0])
+ raise aiohttp.web.HTTPFound(self.url)