1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
#!/usr/bin/python3
from passlib.apache import HtpasswdFile
from flask import Flask, request, make_response, jsonify, redirect
import python_jwt as jwt
from jwcrypto.jwk import JWK
import datetime
from json import dumps
import argparse
app = Flask(__name__)
def authorized_request():
args = request.form
user = args['user'] if 'user' in args else None
pswd = args['pass'] if 'pass' in args else None
remember = args['remember'] if 'remember' in args else None
valid = user is not None and pswd is not None
valid = valid and user in htpasswd.users()
valid = valid and htpasswd.check_password(user, pswd)
return valid, user, pswd, remember
@app.route('/auth', methods=['POST'])
def authorize():
# on success, redirect to /. on failure, redirect to /login
auth, user, _, remember = authorized_request()
if auth:
resp = redirect('/')
if remember:
exp = None
else:
exp = datetime.timedelta(minutes=exptime)
token = jwt.generate_jwt({}, privkey, "EdDSA", exp)
resp.set_cookie('auth', token, max_age=exp)
return resp
# this stuff too
else:
resp = redirect('/login?err')
return resp
@app.route('/logout', methods=['GET'])
def logout():
resp = redirect('/login')
resp.delete_cookie('auth')
return resp
if __name__ == '__main__':
# argparse arguments
parser = argparse.ArgumentParser(
prog='login.py',
description='A web server that handles htpasswd-file JWT auth logic')
parser.add_argument('htpasswd')
parser.add_argument('privkey')
parser.add_argument('-e', '--expireminutes', default=30, type=int)
args = parser.parse_args()
htpasswd_filename = args.htpasswd
privkey_filename = args.privkey
exptime = args.expireminutes
htpasswd = HtpasswdFile(htpasswd_filename)
with open(privkey_filename, 'rb') as privkey_file:
privkey = JWK()
privkey.import_from_pem(privkey_file.read())
app.run(debug=True)
|