79 lines
2.9 KiB
Python
79 lines
2.9 KiB
Python
"""Authentication Provider Plugin
|
|
Allows simple authentication using Username-Password pair with password saved into
|
|
Flaschengeist database (as User attribute)
|
|
"""
|
|
|
|
import os
|
|
import hashlib
|
|
import binascii
|
|
from werkzeug.exceptions import BadRequest
|
|
from flaschengeist.plugins import AuthPlugin, plugins_installed
|
|
from flaschengeist.models.user import User, Role, Permission
|
|
from flaschengeist.database import db
|
|
from flaschengeist import logger
|
|
|
|
|
|
class AuthPlain(AuthPlugin):
|
|
id = "auth_plain"
|
|
|
|
def install(self):
|
|
plugins_installed(self.post_install)
|
|
|
|
def post_install(self, **kwargs):
|
|
if User.query.filter(User.deleted == False).count() == 0:
|
|
logger.info("Installing admin user")
|
|
role = Role.query.filter(Role.name == "Superuser").first()
|
|
if role is None:
|
|
role = Role(name="Superuser", permissions=Permission.query.all())
|
|
admin = User(
|
|
userid="admin",
|
|
firstname="Admin",
|
|
lastname="Admin",
|
|
mail="",
|
|
roles_=[role],
|
|
)
|
|
self.modify_user(admin, None, "admin")
|
|
db.session.add(admin)
|
|
db.session.commit()
|
|
logger.warning(
|
|
"New administrator user was added, please change the password or remove it before going into"
|
|
"production mode. Initial credentials:\n"
|
|
"name: admin\n"
|
|
"password: admin"
|
|
)
|
|
|
|
def login(self, user: User, password: str):
|
|
if user.has_attribute("password"):
|
|
return AuthPlain._verify_password(user.get_attribute("password"), password)
|
|
return False
|
|
|
|
def modify_user(self, user, password, new_password=None):
|
|
if password is not None and not self.login(user, password):
|
|
raise BadRequest
|
|
if new_password:
|
|
user.set_attribute("password", AuthPlain._hash_password(new_password))
|
|
|
|
def create_user(self, user, password):
|
|
if not user.userid:
|
|
raise BadRequest("userid is missing for new user")
|
|
hashed = AuthPlain._hash_password(password)
|
|
user.set_attribute("password", hashed)
|
|
|
|
def delete_user(self, user):
|
|
pass
|
|
|
|
@staticmethod
|
|
def _hash_password(password):
|
|
salt = hashlib.sha256(os.urandom(60)).hexdigest().encode("ascii")
|
|
pass_hash = hashlib.pbkdf2_hmac("sha3-512", password.encode("utf-8"), salt, 100000)
|
|
pass_hash = binascii.hexlify(pass_hash)
|
|
return (salt + pass_hash).decode("ascii")
|
|
|
|
@staticmethod
|
|
def _verify_password(stored_password, provided_password):
|
|
salt = stored_password[:64]
|
|
stored_password = stored_password[64:]
|
|
pass_hash = hashlib.pbkdf2_hmac("sha3-512", provided_password.encode("utf-8"), salt.encode("ascii"), 100000)
|
|
pass_hash = binascii.hexlify(pass_hash).decode("ascii")
|
|
return pass_hash == stored_password
|