Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
ca17c556d6
|
|||
ef1b8ddf30
|
|||
e1b9597fdb
|
|||
ca9e0b81d3
|
@ -24,7 +24,8 @@ RUN \
|
||||
pip3 install uwsgi && \
|
||||
pip3 install flask-cors && \
|
||||
pip3 install six && \
|
||||
pip3 install python-jose[cryptography]
|
||||
pip3 install python-jose[cryptography] && \
|
||||
pip3 install pbkdf2
|
||||
|
||||
RUN \
|
||||
mkdir -p ${APP_DIR} && \
|
||||
|
67
asadduser.py
Executable file
67
asadduser.py
Executable file
@ -0,0 +1,67 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import mariadb
|
||||
from pbkdf2 import crypt
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
parser = argparse.ArgumentParser(description='asadduser')
|
||||
parser.add_argument('--user', '-u',
|
||||
help='Login',
|
||||
required=True)
|
||||
parser.add_argument('--password', '-p',
|
||||
help='Password',
|
||||
required=True)
|
||||
parser.add_argument('--application', '-a',
|
||||
help='Application',
|
||||
required=True)
|
||||
parser.add_argument('--issuer', '-i',
|
||||
help='Issuer',
|
||||
required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
user = args.user
|
||||
password = args.password
|
||||
application = args.application
|
||||
issuer = args.issuer
|
||||
|
||||
|
||||
DB_USER = os.environ["DB_USER"]
|
||||
DB_PASS = os.environ["DB_PASS"]
|
||||
DB_HOST = os.environ["DB_HOST"]
|
||||
DB_NAME = os.environ["DB_NAME"]
|
||||
|
||||
pwhash = crypt(password, iterations=100000)
|
||||
|
||||
conn = None
|
||||
cur = None
|
||||
try:
|
||||
conn = mariadb.connect(user = DB_USER, password = DB_PASS,
|
||||
host = DB_HOST, database = DB_NAME)
|
||||
conn.autocommit = False
|
||||
|
||||
cur = conn.cursor()
|
||||
cur.execute("""
|
||||
INSERT INTO users (issuer, login, password)
|
||||
VALUES(
|
||||
(SELECT id FROM issuers WHERE name = ?),
|
||||
?,
|
||||
?
|
||||
)
|
||||
""", [issuer, user, pwhash])
|
||||
cur.execute("""
|
||||
INSERT INTO user_applications_mapping (application, user)
|
||||
VALUES(
|
||||
(SELECT id FROM applications WHERE name = ?),
|
||||
(SELECT id FROM users WHERE login = ?)
|
||||
)
|
||||
""", [application, user])
|
||||
conn.commit()
|
||||
finally:
|
||||
if cur:
|
||||
cur.close()
|
||||
if conn:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
|
49
auth.py
49
auth.py
@ -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
|
||||
|
||||
class ManyUsersException(Exception):
|
||||
pass
|
||||
|
||||
class PasswordMismatchException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
UserEntry = namedtuple('UserEntry', ['id', 'login', 'issuer', 'secret', 'expiry', 'claims'])
|
||||
|
||||
|
||||
|
||||
def getUserEntryFromDB(login: str, password: str) -> UserEntry:
|
||||
def getUserEntryFromDB(application: str, login: str):
|
||||
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,11 +62,11 @@ 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,
|
||||
secret=resObj["secret"], issuer=resObj["issuer"],
|
||||
expiry=resObj["expiry"], claims=claims)
|
||||
|
||||
return userEntry
|
||||
return userEntry, resObj["password"]
|
||||
except mariadb.Error as err:
|
||||
raise Exception("Error when connecting to database: {}".format(err))
|
||||
finally:
|
||||
@ -69,17 +76,20 @@ def getUserEntryFromDB(login: str, password: str) -> UserEntry:
|
||||
conn.rollback()
|
||||
conn.close()
|
||||
|
||||
|
||||
def getUserEntry(login: str, password: str) -> UserEntry:
|
||||
return getUserEntryFromDB(login, password)
|
||||
|
||||
def getUserEntry(application, login, password):
|
||||
userEntry, pwhash = getUserEntryFromDB(application, login)
|
||||
if pwhash != crypt(password, pwhash):
|
||||
raise PasswordMismatchException()
|
||||
return userEntry
|
||||
|
||||
def generateToken(**args):
|
||||
try:
|
||||
body = args["body"]
|
||||
application = body["application"]
|
||||
login = body["login"]
|
||||
password = body["password"]
|
||||
userEntry = getUserEntryFromDB(login, password)
|
||||
|
||||
userEntry = getUserEntry(application, login, password)
|
||||
|
||||
timestamp = int(time.time())
|
||||
payload = {
|
||||
@ -94,13 +104,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)))
|
||||
|
@ -10,6 +10,13 @@ CREATE TABLE `issuers` (
|
||||
ALTER TABLE `issuers`
|
||||
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,
|
||||
`login` varchar(64) NOT NULL,
|
||||
@ -40,6 +47,9 @@ ALTER TABLE `users`
|
||||
ALTER TABLE `users`
|
||||
MODIFY COLUMN expiry int(10) unsigned NOT NULL;
|
||||
|
||||
ALTER TABLE `users`
|
||||
MODIFY COLUMN expiry int(10) unsigned NOT NULL DEFAULT 600;
|
||||
|
||||
CREATE TABLE `claims` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`key` varchar(64) NOT NULL,
|
||||
@ -58,6 +68,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 +88,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;
|
||||
|
||||
|
@ -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:
|
||||
|
Reference in New Issue
Block a user