summaryrefslogtreecommitdiffstats
path: root/auth.py
diff options
context:
space:
mode:
authorFulgen301 <tokmajigeorge@gmail.com>2018-09-16 16:58:21 +0200
committerFulgen301 <tokmajigeorge@gmail.com>2018-09-16 16:58:21 +0200
commit027139279aa0e83c123ba26139d84505f1d4af90 (patch)
treeff9ecd64cab21f2b034288a476870282fb944fa5 /auth.py
parent0184fbb68c8bf1d8d1a123929dfab0497d5236af (diff)
downloadparry-027139279aa0e83c123ba26139d84505f1d4af90.tar.gz
parry-027139279aa0e83c123ba26139d84505f1d4af90.zip
Use sqlalchemy as backend, implement JWT authentication, add uploading, commenting and voting
Diffstat (limited to 'auth.py')
-rw-r--r--auth.py82
1 files changed, 82 insertions, 0 deletions
diff --git a/auth.py b/auth.py
new file mode 100644
index 0000000..1f45844
--- /dev/null
+++ b/auth.py
@@ -0,0 +1,82 @@
+# Copyright (c) 2018, George Tokmaji
+
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+import os, hashlib, base64, jwt, json
+from .database import *
+from bottle import install, HTTPResponse, route, request, default_app, post
+from bottle_jwt import JWTProviderPlugin, jwt_auth_required, JWTProvider
+
+def calculateUserHash(username : str, password : str) -> object:
+ return hashlib.sha512(hashlib.sha512(username.encode("utf-8")).digest() + hashlib.sha512(password.encode("utf-8")).digest())
+
+class AuthBackend(object):
+ def authenticate_user(self, username, password):
+ if username is None or password is None:
+ raise HTTPResponse("Username or password missing", 400)
+ session = DBSession()
+ try:
+ user = session.query(User).filter_by(name=username, hash=calculateUserHash(username, password).hexdigest()).one()
+ except db.orm.exc.NoResultFound:
+ return
+
+ return {"id" : str(user.id), "name" : user.name, "email" : user.email}
+
+ def get_user(self, user_id):
+ session = DBSession()
+ user = session.query(User).get(user_id)
+ if user:
+ return {"id" : str(user.id), "name" : user.name, "email" : user.email}
+
+def custom_create_token(self, user, ttl=None):
+ user_id = json.dumps(user[self.id_field]).encode("utf-8")
+ payload = {
+ "sub" : base64.b64encode(user_id).decode("utf-8"),
+ "name" : user["name"],
+ "email" : user["email"]
+ }
+
+ if self.ttl:
+ payload["exp"] = datetime.utcnow() + datetime.timedelta(seconds=ttl) if ttl else self.expires
+
+ return jwt.encode(payload, self.secret, algorithm=self.algorithm), payload["exp"]
+
+JWTProvider.create_token = custom_create_token
+
+install(JWTProviderPlugin(
+ keyword="jwt",
+ auth_endpoint="/api/auth",
+ backend=AuthBackend(),
+ fields=("username", "password"),
+ secret=os.environ["PARRY_SECRET"],
+ ttl=30 * 60
+ ))
+
+
+def auth_basic(f):
+ def checkAuth(*args, **kwargs):
+ session = DBSession()
+ try:
+ User.query.filter_by(name=request.forms["username"], hash=calculateUserHash(request.forms["username"], request.forms["password"]).hexdigest()).first()
+ except db.orm.exc.NoResultFound:
+ return HTTPResponse(status=401)
+
+ del request.forms["password"]
+ return f(*args, **kwargs)
+ return checkAuth
+
+def get_user(session : DBSession):
+ try:
+ return session.query(User).filter_by(name=request.get_user()["name"]).one()
+ except db.orm.exc.NoResultFound:
+ raise HTTPResponse(status=401)