summaryrefslogtreecommitdiff
path: root/server.py
diff options
context:
space:
mode:
authorYves Fischer <yvesf-git@xapek.org>2016-07-09 21:36:50 +0200
committerYves Fischer <yvesf-git@xapek.org>2016-07-09 21:48:26 +0200
commit045f9bc3b68f03d88b9623a0893eeca3ff1ff372 (patch)
tree043d0b4e261f8f41ae74938f210e5aa542652f9a /server.py
parent5d6a8c8939382c4c6fb9f3205a865606a28c9b42 (diff)
downloadauth-xmppmessage-045f9bc3b68f03d88b9623a0893eeca3ff1ff372.tar.gz
auth-xmppmessage-045f9bc3b68f03d88b9623a0893eeca3ff1ff372.zip
implement server for nginx auth_request
Diffstat (limited to 'server.py')
-rwxr-xr-xserver.py76
1 files changed, 76 insertions, 0 deletions
diff --git a/server.py b/server.py
new file mode 100755
index 0000000..4b72f83
--- /dev/null
+++ b/server.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+import time
+import binascii
+import random
+import argparse
+import functions
+import logging
+from http.server import BaseHTTPRequestHandler, HTTPServer
+
+logging.basicConfig(level=logging.INFO)
+
+LAST_REQUEST_TIME = 0
+CACHE = {}
+
+
+def send_token(conf, username, orig_uri):
+ message = functions.token_message(username, conf.secret, conf.validsec, orig_uri)
+ if conf.skip_xmpp: # used for testing
+ print(message)
+ else:
+ functions.send_message(conf.jid, conf.password, username, message)
+
+
+class RequestHandler(BaseHTTPRequestHandler):
+ def do_GET(self):
+ global LAST_REQUEST_TIME, CACHE
+ if 'Authorization' in self.headers:
+ method, value = self.headers['Authorization'].split(' ')
+ if method != 'Basic':
+ self.send_response(400, 'Unsupported authentication method')
+ elif value in CACHE and CACHE[value] > time.time() - 60: # cache cred for 60s for performance
+ logging.info("Authorized (cached) %s", value)
+ self.send_response(200, "OK go forward")
+ else:
+ username, password = binascii.a2b_base64(value.encode('utf-8')).decode('utf-8').split(':')
+ if password == "" and username in conf.users:
+ if LAST_REQUEST_TIME == 0 or time.time() - LAST_REQUEST_TIME > 15: # max 1 msg per 15 sec
+ LAST_REQUEST_TIME = time.time()
+ send_token(conf, username, self.headers['X-Original-URI'])
+ self.send_response(401, "Token sent, retry")
+ else:
+ self.send_response(429, 'Too Many Requests')
+ else:
+ if functions.verify_token(username, password, conf.secret, conf.validsec):
+ logging.info("Authorized %s", username)
+ CACHE[value] = time.time()
+ self.send_response(200, "OK go forward")
+ else:
+ logging.info("Denied %s", username)
+ self.send_response(401, "Authentication failed, username or password wrong")
+ else:
+ self.send_response(401)
+ self.send_header("WWW-Authenticate", "Basic realm=\"xmppmessage auth\"")
+
+ self.end_headers()
+
+
+def run(conf):
+ httpd = HTTPServer((conf.server_host, conf.server_port), RequestHandler)
+ httpd.conf = conf
+ httpd.serve_forever()
+
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--secret', default="".join([chr(random.randint(ord('0'), ord('Z'))) for x in range(20)]))
+ parser.add_argument('--validsec', type=int, default=60 * 60 * 48)
+ parser.add_argument('--user', '-u', nargs='+', default=['yvesf@xapek.org', 'marc@xapek.org'], dest='users')
+ parser.add_argument('--jid', help="Bot jid", default="bot@xapek.org")
+ parser.add_argument('--password', help="Bot jid password")
+ parser.add_argument('--server-host', default="127.0.0.1")
+ parser.add_argument('--server-port', default=8081, type=int)
+ parser.add_argument('--skip-xmpp', default=False, type=bool)
+
+ conf = parser.parse_args()
+ run(conf)