spotify-backup/spotifybackup/authorization.py

53 lines
1.6 KiB
Python

import http.server
import secrets
import urllib.parse
class _RequestHandler(http.server.BaseHTTPRequestHandler):
server: "Server"
def do_GET(self):
url = urllib.parse.urlsplit(self.path)
if url.path == self.server.REDIRECT_PATH:
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.end_headers()
self.wfile.write(
f"<script>location.replace(\"{self.server.TOKEN_PATH}?\" + "
"location.hash.slice(1));</script>"
.encode()
)
elif url.path == self.server.TOKEN_PATH:
query = urllib.parse.parse_qs(url.query)
if query["state"][0] != self.server.state:
self.send_error(401)
self.server.token = query["access_token"][0]
self.send_response(200)
self.send_header("Content-Type", "text/html")
self.end_headers()
self.wfile.write(
b"<script>close()</script>Thanks! You may now close this "
b"window."
)
def log_message(self, format, *args) -> None:
pass
class Server(http.server.HTTPServer):
_HOST = "127.0.0.1"
_PORT = 43019
REDIRECT_PATH = "/redirect"
TOKEN_PATH = "/token"
def __init__(self) -> None:
self.state = "".join(
chr(secrets.choice(range(0x20, 0x7E + 1))) for _ in range(32)
)
self.token: str | None = None
super().__init__((self._HOST, self._PORT), _RequestHandler)
@classmethod
def redirect_uri(cls) -> str:
return f"http://{cls._HOST}:{cls._PORT}{cls.REDIRECT_PATH}"