application and pwhash

This commit is contained in:
Wolfgang Hottgenroth 2021-01-26 21:27:17 +01:00
parent c9478935cd
commit ca9e0b81d3
Signed by: wn
GPG Key ID: E49AF3B9EF6DD469
3 changed files with 64 additions and 24 deletions

54
auth.py
View File

@ -5,7 +5,7 @@ import werkzeug
import os
import mariadb
from collections import namedtuple
from pbkdf2 import crypt
DB_USER = os.environ["DB_USER"]
DB_PASS = os.environ["DB_PASS"]
@ -13,14 +13,21 @@ DB_HOST = os.environ["DB_HOST"]
DB_NAME = os.environ["DB_NAME"]
class NoUserException(Exception): pass
class ManyUsersException(Exception): pass
class NoUserException(Exception):
pass
UserEntry = namedtuple('UserEntry', ['id', 'login', 'issuer', 'secret', 'expiry', 'claims'])
class ManyUsersException(Exception):
pass
class PasswordMismatchException(Exception):
pass
UserEntry = namedtuple('UserEntry', ['id', 'login', 'pwhash', 'issuer', 'secret', 'expiry', 'claims'])
def getUserEntryFromDB(login: str, password: str) -> UserEntry:
def getUserEntryFromDB(application: str, login: str) -> UserEntry:
conn = None
cur = None
try:
@ -29,9 +36,9 @@ def getUserEntryFromDB(login: str, password: str) -> UserEntry:
conn.autocommit = False
cur = conn.cursor(dictionary=True)
# print("DEBUG: getUserEntryFromDB: login: <{}>, password: <{}>".format(login, password))
cur.execute("SELECT id, issuer, secret, expiry FROM user_and_issuer WHERE login = ? AND password = ?",
[login, password])
cur.execute("SELECT id, password, issuer, secret, expiry FROM user_application_and_issuer " +
" WHERE application = ? AND login = ?",
[application, login])
resObj = cur.next()
print("DEBUG: getUserEntryFromDB: resObj: {}".format(resObj))
if not resObj:
@ -55,9 +62,9 @@ def getUserEntryFromDB(login: str, password: str) -> UserEntry:
else:
claims[claimObj["key"]] = claimObj["value"]
userEntry = UserEntry(id=userId, login=login, secret=resObj["secret"],
issuer=resObj["issuer"], expiry=resObj["expiry"],
claims=claims)
userEntry = UserEntry(id=userId, login=login, pwhash=resObj["password"],
secret=resObj["secret"], issuer=resObj["issuer"],
expiry=resObj["expiry"], claims=claims)
return userEntry
except mariadb.Error as err:
@ -69,17 +76,23 @@ def getUserEntryFromDB(login: str, password: str) -> UserEntry:
conn.rollback()
conn.close()
def getUserEntry(login: str, password: str) -> UserEntry:
return getUserEntryFromDB(login, password)
def checkPassword(inputPassword, passwordHash) -> bool:
print("DEBUG, checkPassword: {} {}".format(inputPassword, passwordHash))
if passwordHash != crypt(inputPassword, passwordHash, 100000):
raise PasswordMismatchException()
return True
def generateToken(**args):
try:
body = args["body"]
application = body["application"]
login = body["login"]
password = body["password"]
userEntry = getUserEntryFromDB(login, password)
inputPassword = body["password"]
userEntry = getUserEntryFromDB(application, login)
if inputPassword != crypt(inputPassword, userEntry.pwhash, 100000):
raise PasswordMismatchException()
timestamp = int(time.time())
payload = {
@ -94,13 +107,16 @@ def generateToken(**args):
return jwt.encode(payload, userEntry.secret)
except NoUserException:
print("ERROR: generateToken: no user found, login or password wrong")
print("ERROR: generateToken: no user found, login or application wrong")
raise werkzeug.exceptions.Unauthorized()
except ManyUsersException:
print("ERROR: generateToken: too many users found")
raise werkzeug.exceptions.Unauthorized()
except PasswordMismatchException:
print("ERROR: generateToken: wrong password")
raise werkzeug.exceptions.Unauthorized()
except KeyError:
print("ERROR: generateToken: login or password missing")
print("ERROR: generateToken: application, login or password missing")
raise werkzeug.exceptions.Unauthorized()
except Exception as e:
print("ERROR: generateToken: unspecific exception: {}".format(str(e)))

View File

@ -8,7 +8,14 @@ CREATE TABLE `issuers` (
) ENGINE=InnoDB;
ALTER TABLE `issuers`
MODIFY COLUMN `max_expiry` int(10) unsigned NOT NULL;
MODIFY COLUMN `max_expiry` int(10) unsigned NOT NULL;
CREATE TABLE `applications` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL,
CONSTRAINT PRIMARY KEY (`id`),
CONSTRAINT UNIQUE KEY `uk_applications_name` (`name`)
) ENGINE=InnoDB;
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
@ -58,6 +65,16 @@ CREATE TABLE `user_claims_mapping` (
REFERENCES `claims`(`id`)
) ENGINE=InnoDB;
CREATE TABLE `user_applications_mapping` (
`user` int(10) unsigned NOT NULL,
`application` int(10) unsigned NOT NULL,
CONSTRAINT UNIQUE KEY `uk_user_applications_mapping` (`user`, `application` ),
CONSTRAINT FOREIGN KEY `fk_user_applications_mapping_user` (`user`)
REFERENCES `users`(`id`),
CONSTRAINT FOREIGN KEY `fk_user_applications_mapping_application` (`application`)
REFERENCES `applications`(`id`)
) ENGINE=InnoDB;
CREATE OR REPLACE VIEW claims_for_user AS
SELECT u.id AS user,
c.`key` AS `key`,
@ -68,14 +85,19 @@ CREATE OR REPLACE VIEW claims_for_user AS
WHERE m.user = u.id AND
m.claim = c.id;
CREATE OR REPLACE VIEW user_and_issuer AS
CREATE OR REPLACE VIEW user_application_and_issuer AS
SELECT u.login AS login,
u.password AS password,
u.id AS id,
a.name as application,
i.name AS issuer,
i.secret AS secret,
least(u.expiry, i.max_expiry) AS expiry
FROM users u,
issuers i
WHERE u.issuer = i.id;
issuers i,
applications a,
user_applications_mapping m
WHERE u.issuer = i.id AND
u.id = m.user AND
a.id = m.application;

View File

@ -45,9 +45,11 @@ components:
x-bearerInfoFunc: test.decodeToken
schemas:
User:
description: Login/Password tuple
description: Application/Login/Password tuple
type: object
properties:
application:
type: string
login:
type: string
password: