Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Python3 http.server supporting basic HTTP Auth (username/password)
# Extended python -m http.serve with --username and --password parameters for
# basic auth, based on https://gist.github.com/fxsjy/5465353
from functools import partial
from http.server import SimpleHTTPRequestHandler, test
import base64
import os
class AuthHTTPRequestHandler(SimpleHTTPRequestHandler):
""" Main class to present webpages and authentication. """
def __init__(self, *args, **kwargs):
username = kwargs.pop("username")
password = kwargs.pop("password")
self._auth = base64.b64encode(f"{username}:{password}".encode()).decode()
super().__init__(*args, **kwargs)
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="Test"')
self.send_header("Content-type", "text/html")
self.end_headers()
def do_GET(self):
""" Present frontpage with user authentication. """
if self.headers.get("Authorization") == None:
self.do_AUTHHEAD()
self.wfile.write(b"no auth header received")
elif self.headers.get("Authorization") == "Basic " + self._auth:
SimpleHTTPRequestHandler.do_GET(self)
else:
self.do_AUTHHEAD()
self.wfile.write(self.headers.get("Authorization").encode())
self.wfile.write(b"not authenticated")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--cgi", action="store_true", help="Run as CGI Server")
parser.add_argument(
"--bind",
"-b",
metavar="ADDRESS",
default="127.0.0.1",
help="Specify alternate bind address " "[default: all interfaces]",
)
parser.add_argument(
"--directory",
"-d",
default=os.getcwd(),
help="Specify alternative directory " "[default:current directory]",
)
parser.add_argument(
"port",
action="store",
default=8000,
type=int,
nargs="?",
help="Specify alternate port [default: 8000]",
)
parser.add_argument("--username", "-u", metavar="USERNAME")
parser.add_argument("--password", "-p", metavar="PASSWORD")
args = parser.parse_args()
handler_class = partial(
AuthHTTPRequestHandler,
username=args.username,
password=args.password,
directory=args.directory,
)
test(HandlerClass=handler_class, port=args.port, bind=args.bind)
@nguyencanhlich

This comment has been minimized.

Copy link

@nguyencanhlich nguyencanhlich commented Nov 21, 2019

I don't know how to log in. Please help me. Thanks you pro!

@Madave94

This comment has been minimized.

Copy link

@Madave94 Madave94 commented Jan 22, 2020

I had to change line 17 from super().__init__(*args, **kwargs) to super().__init__(*args) otherwise i received an error that the parent class got some invalid arguments. Can you confirm that or tell me why i got that error?

@lionelyoung

This comment has been minimized.

Copy link

@lionelyoung lionelyoung commented Feb 9, 2020

I don't know how to log in. Please help me. Thanks you pro!

  1. Run python -m http_server_auth -u USERNAME -p PASSWORD -d .
  2. Open your browser, and go to http://localhost:8000
@lionelyoung

This comment has been minimized.

Copy link

@lionelyoung lionelyoung commented Feb 9, 2020

I had to change line 17 from super().__init__(*args, **kwargs) to super().__init__(*args) otherwise i received an error that the parent class got some invalid arguments. Can you confirm that or tell me why i got that error?

Yes, same here. Works if you remove it, I went ahead and did that and put it into this gist: https://gist.github.com/lionelyoung/8cad668d4d30fa392842fa08d50d2bc6

@kcraft09

This comment has been minimized.

Copy link

@kcraft09 kcraft09 commented Apr 8, 2020

The -d or --directory argument does not seem to work. I have tried both and upon logging in, I am always in my current working directory. I cannot seem to find the issue. Has anyone else had this issue. I am using python version 3.8.

@jenciso

This comment has been minimized.

Copy link

@jenciso jenciso commented Apr 14, 2020

I had to change line 17 from super().__init__(*args, **kwargs) to super().__init__(*args) otherwise i received an error that the parent class got some invalid arguments. Can you confirm that or tell me why i got that error?

Yes, same here. Works if you remove it, I went ahead and did that and put it into this gist: https://gist.github.com/lionelyoung/8cad668d4d30fa392842fa08d50d2bc6

Thanks

@Christoph460

This comment has been minimized.

Copy link

@Christoph460 Christoph460 commented Aug 7, 2020

@kcraft09 Setting the directory via the command line was also not working for me. I fixed it with the change of the first lines to
`

def init(self, *args, **kwargs):
username = kwargs.pop("username")
password = kwargs.pop("password")
directory = kwargs.pop("directory")

 self._auth = base64.b64encode(f"{username}:{password}".encode()).decode()
 super().__init__(*args, directory=directory)

`

@13-Voin

This comment has been minimized.

Copy link

@13-Voin 13-Voin commented Aug 17, 2020

Good day, everyone. Please tell me how to screw ssl (https) here. Thank.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.