commit ac16c46e0120e36b7c1793ab5af46c28a335b087 Author: Stefan Krulj Date: Sun Aug 11 12:13:11 2019 +0200 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/model/models.py b/model/models.py new file mode 100644 index 0000000..c3ec4fd --- /dev/null +++ b/model/models.py @@ -0,0 +1,27 @@ +from datetime import datetime,timedelta +from uuid import uuid1 +import secrets + +class Nounce(object): + def __init__(self): + self.id = uuid1() + self.expiration = datetime.now()+timedelta(seconds=60) + self.token = secrets.token_urlsafe() + + def expired(self): + return datetime.now() > self.expiration + + def bump(self): + self.expiration = datetime.now()+timedelta(seconds=60) + +class AuthSession(object): + def __init__(self, username): + self.id = uuid1() + self.expiration = datetime.now()+timedelta(minutes=30) + self.username = username + + def expired(self): + return datetime.now() > self.expiration + + def bumpExpiration(self): + self.expiration = datetime.now()+timedelta(minutes=30) \ No newline at end of file diff --git a/nonce.py b/nonce.py new file mode 100644 index 0000000..3f3062f --- /dev/null +++ b/nonce.py @@ -0,0 +1,109 @@ +from flask import * +import secrets, hashlib +from model.models import * +import json + +app = Blueprint('nounce', __name__) + +SID = 'SID' +nonces = {} +authSessions = {} +users = {} + +def loadUsers(path): + global users + with open(path) as json_file: + users = json.load(json_file) + +@app.route('/nonce', methods=['GET']) +def nounce(): + n = tryGetSessionNonce() + if n == None or n.expired(): + n = generateSessionNonce() + n.bump() + return jsonify(n.__dict__),201 + +@app.route('/login', methods=['POST']) +def login(): + if isLoggedIn(): + return 'already logged in', 400 + + n = tryGetSessionNonce() + if n == None: + return 'no nonce was generated', 400 + if n.expired(): + clearSessionNonce() + return 'nonce expired', 408 + + user = request.form['user'] + cnonce = request.form['cnonce'] + pwdhash = request.form['pwdhash'] + + pwdHashed_sha256 = '' + if user in users: + pwdHashed_sha256 = users[user] + else: + abort(403) + + hash = generateHash(pwdHashed_sha256, cnonce, n.token) + if hash == pwdhash: + s = generateAuthSession(user) + return jsonify(s.__dict__),201 + else: + abort(403) + +@app.route('/check-login', methods=['GET']) +def checkLogin(): + if isLoggedIn(): + asession = authSessions[session[SID]] + asession.bumpExpiration() + return jsonify(asession.__dict__) + else: + return abort(403) + +@app.route('/login-page', methods=['GET']) +def loginPage(): + return render_template('login-page.html') + +def isLoggedIn(): + if SID in session and session[SID] in authSessions: + return not(authSessions[session[SID]].expired()) + return False + +def generateAuthSession(username): + asession = AuthSession(username) + authSessions[session[SID]] = asession + return asession + +def getAuthSession(): + if not SID in session: + return None + if not session[SID]: + return None + return authSessions[session[SID]] + +def clearSessionNonce(): + if not SID in session: + return + if not session[SID] in nonces: + return + del nonces[session[SID]] + +def tryGetSessionNonce(): + if not SID in session: + return None + if not session[SID] in nonces: + return None + return nonces[session[SID]] + +def generateSessionNonce(): + n = Nounce() + session[SID] = secrets.token_urlsafe() + nonces[session[SID]] = n + return n + +def generateHash(pwdsha256,cnonce,nonce): + all = pwdsha256+cnonce+nonce + sha256 = hashlib.sha256( ) + sha256.update( all.encode('utf8') ) + return sha256.hexdigest() diff --git a/simple_auth_service.py b/simple_auth_service.py new file mode 100644 index 0000000..b303c5f --- /dev/null +++ b/simple_auth_service.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +from flask import * +import secrets +import nonce +import os.path + +app = Flask(__name__) +app.secret_key = secrets.token_urlsafe() +app.register_blueprint(nonce.app) + +ROUTES = {'routes': ['/', '/nonce'] } +@app.route('/') +def home(): + return jsonify(ROUTES) + +nonce.loadUsers( os.path.join('data','userlist.json') ) +if __name__ == '__main__': + app.run( host='0.0.0.0', port=7070) + diff --git a/templates/login-page.html b/templates/login-page.html new file mode 100644 index 0000000..da2e7ae --- /dev/null +++ b/templates/login-page.html @@ -0,0 +1,179 @@ + + + + + + + + + + +
+ + + +
Login failed!
+
+ + \ No newline at end of file