Some explanation on components used for the authentication proxy...
Creates an object of the class HTTPServer which takes as parameter:
from http.server import BaseHTTPRequestHandler, HTTPServer
httpd = HTTPServer(('', 8000), BaseHTTPRequestHandler)
httpd.serve_forever()
To actually answer http requests, a new class has to be defined which inherits BaseHTTPRequestHandler an overwrites the functions to handle different http request types such a GET, POST, ...
from http.server import BaseHTTPRequestHandler, HTTPServer
HOST='localhost'
PORT=8000
s = """<html>
<head><title>hello, world</title></head>
<body>hello, world</body>
</html>"""
class OtpRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200) #OK
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes(s, "utf-8"))
httpd = HTTPServer((HOST, PORT), OtpRequestHandler)
httpd.serve_forever()
To test: curl http://localhost:8000/
from http.server import BaseHTTPRequestHandler, HTTPServer
class OtpRequestHandler(BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers['Content-Length'])
print(self.headers['content-type'])
print(self.rfile.read(length))
httpd = HTTPServer(('localhost', 8000), OtpRequestHandler)
httpd.serve_forever()
To Test: curl -d "hello, world" -X POST http://localhost:8000/
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import parse_qs
class OtpRequestHandler(BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers['Content-Length'])
parms = parse_qs(self.rfile.read(length).decode("utf-8"))
print("User: " + ''.join(parms["user"]) )
print("OTP: " + ''.join(parms["otp"]) )
httpd = HTTPServer(('localhost', 8000), OtpRequestHandler)
httpd.serve_forever()
To Test: curl -d "user=jdoe&otp=204177" -X POST http://localhost:8000/
from http.server import BaseHTTPRequestHandler, HTTPServer
from http.cookies import SimpleCookie
import secrets
cookie = SimpleCookie()
cookie['token'] = secrets.token_urlsafe(16)
#cookie["token"]["domain"] = "s-up.net"
cookie["token"]["path"] = "/"
#cookie["token"]["secure"] = True
cookie["token"]["httponly"] = True
cookies.Morsel._reserved.setdefault('samesite', 'SameSite')
cookie["token"]["samesite"] = "strict"
cookie["token"]["expires"] = 60 * 60 * 6 # 6h
class OtpRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200) #OK
self.send_header("Content-type", "text/html")
self.send_header('Set-Cookie', cookie.output(header=''))
self.end_headers()
self.wfile.write(bytes("Hello", "utf-8"))
httpd = HTTPServer(('localhost', 8000), OtpRequestHandler)
httpd.serve_forever()
from http.server import BaseHTTPRequestHandler, HTTPServer
from http.cookies import SimpleCookie
import secrets
class OtpRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200) #OK
self.send_header("Content-type", "text/html")
self.end_headers()
cookies = SimpleCookie(self.headers.get('Cookie'))
token = cookies['token'].value
self.wfile.write(bytes(token, "utf-8"))
print(token)
httpd = HTTPServer(('localhost', 8000), OtpRequestHandler)
httpd.serve_forever()
import pyotp
import time
# Get a random secret
secret=pyotp.random_base32()
print(secret)
# Calculate OTP
otp=pyotp.TOTP(secret).now()
print(otp)
# Verify OTP, should be true
pyotp.TOTP(secret).verify(otp)
# Verify OTP again after 30s, should be false
time.sleep(30)
pyotp.TOTP(secret).verify(otp)