Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
91178b1fa7
|
|||
1f55ef0a80
|
|||
19b8aab8c2
|
47
auth.py
47
auth.py
@ -1,6 +1,7 @@
|
|||||||
import time
|
import time
|
||||||
import connexion
|
import connexion
|
||||||
from jose import JWTError, jwt
|
from jose import JWTError, jwt, jwe
|
||||||
|
import json
|
||||||
import werkzeug
|
import werkzeug
|
||||||
import os
|
import os
|
||||||
import psycopg2
|
import psycopg2
|
||||||
@ -60,7 +61,7 @@ def getUserEntryFromDB(application: str, login: str):
|
|||||||
" WHERE application = %s AND login = %s",
|
" WHERE application = %s AND login = %s",
|
||||||
(application, login))
|
(application, login))
|
||||||
userObj = cur.fetchone()
|
userObj = cur.fetchone()
|
||||||
logger.debug("getUserEntryFromDB: userObj: {}".format(userObj))
|
logger.debug("userObj: {}".format(userObj))
|
||||||
if not userObj:
|
if not userObj:
|
||||||
raise NoUserException()
|
raise NoUserException()
|
||||||
invObj = cur.fetchone()
|
invObj = cur.fetchone()
|
||||||
@ -72,7 +73,7 @@ def getUserEntryFromDB(application: str, login: str):
|
|||||||
cur.execute('SELECT key, value FROM claims_for_user_v where "user" = %s and application = %s',
|
cur.execute('SELECT key, value FROM claims_for_user_v where "user" = %s and application = %s',
|
||||||
(userObj[0], application))
|
(userObj[0], application))
|
||||||
for claimObj in cur:
|
for claimObj in cur:
|
||||||
logger.debug("getUserEntryFromDB: add claim {} -> {}".format(claimObj[0], claimObj[1]))
|
logger.debug("add claim {} -> {}".format(claimObj[0], claimObj[1]))
|
||||||
if claimObj[0] in claims:
|
if claimObj[0] in claims:
|
||||||
if isinstance(claims[claimObj[0]], list):
|
if isinstance(claims[claimObj[0]], list):
|
||||||
claims[claimObj[0]].append(claimObj[1])
|
claims[claimObj[0]].append(claimObj[1])
|
||||||
@ -100,9 +101,26 @@ def getUserEntry(application, login, password):
|
|||||||
def generateToken(**args):
|
def generateToken(**args):
|
||||||
try:
|
try:
|
||||||
body = args["body"]
|
body = args["body"]
|
||||||
|
|
||||||
|
application = ""
|
||||||
|
login = ""
|
||||||
|
password = ""
|
||||||
|
if (("application" in body) and
|
||||||
|
("login" in body) and
|
||||||
|
("password" in body)):
|
||||||
application = body["application"]
|
application = body["application"]
|
||||||
login = body["login"]
|
login = body["login"]
|
||||||
password = body["password"]
|
password = body["password"]
|
||||||
|
elif ("encAleTuple" in body):
|
||||||
|
clearContent = jwe.decrypt(body["encAleTuple"], JWT_PRIV_KEY)
|
||||||
|
clearObj = json.loads(clearContent)
|
||||||
|
application = clearObj["application"]
|
||||||
|
login = clearObj["login"]
|
||||||
|
password = clearObj["password"]
|
||||||
|
else:
|
||||||
|
raise KeyError("Neither application, login and password nor encAleTuple given")
|
||||||
|
|
||||||
|
logger.debug(f"Tuple: {application} {login} {password}")
|
||||||
|
|
||||||
userEntry = getUserEntry(application, login, password)
|
userEntry = getUserEntry(application, login, password)
|
||||||
|
|
||||||
@ -116,31 +134,26 @@ def generateToken(**args):
|
|||||||
}
|
}
|
||||||
logger.debug("claims: {}".format(userEntry.claims))
|
logger.debug("claims: {}".format(userEntry.claims))
|
||||||
for claim in userEntry.claims.items():
|
for claim in userEntry.claims.items():
|
||||||
logger.debug("generateToken: add claim {}".format(claim))
|
logger.debug("add claim {}".format(claim))
|
||||||
payload[claim[0]] = claim[1]
|
payload[claim[0]] = claim[1]
|
||||||
|
|
||||||
return jwt.encode(payload, JWT_PRIV_KEY, algorithm='RS256')
|
return jwt.encode(payload, JWT_PRIV_KEY, algorithm='RS256')
|
||||||
except NoUserException:
|
except NoUserException:
|
||||||
logger.error("generateToken: no user found, login or application wrong")
|
logger.error("no user found, login or application wrong")
|
||||||
raise werkzeug.exceptions.Unauthorized()
|
raise werkzeug.exceptions.Unauthorized()
|
||||||
except ManyUsersException:
|
except ManyUsersException:
|
||||||
logger.error("generateToken: too many users found")
|
logger.error("too many users found")
|
||||||
raise werkzeug.exceptions.Unauthorized()
|
raise werkzeug.exceptions.Unauthorized()
|
||||||
except PasswordMismatchException:
|
except PasswordMismatchException:
|
||||||
logger.error("generateToken: wrong password")
|
logger.error("wrong password")
|
||||||
raise werkzeug.exceptions.Unauthorized()
|
raise werkzeug.exceptions.Unauthorized()
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.error("generateToken: application, login or password missing")
|
logger.error("application, login or password missing")
|
||||||
raise werkzeug.exceptions.Unauthorized()
|
raise werkzeug.exceptions.Unauthorized()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error("generateToken: unspecific exception: {}".format(str(e)))
|
logger.error("unspecific exception: {}".format(str(e)))
|
||||||
raise werkzeug.exceptions.Unauthorized()
|
raise werkzeug.exceptions.Unauthorized()
|
||||||
|
|
||||||
def generateTokenFromEnc(**args):
|
|
||||||
cryptContent = args["body"]
|
|
||||||
raise werkzeug.exceptions.NotImplemented("Stay tuned, will be added soon")
|
|
||||||
return str(cryptContent)
|
|
||||||
|
|
||||||
def getPubKey():
|
def getPubKey():
|
||||||
return JWT_PUB_KEY
|
return JWT_PUB_KEY
|
||||||
|
|
||||||
@ -148,12 +161,12 @@ def decodeToken(token):
|
|||||||
try:
|
try:
|
||||||
return jwt.decode(token, JWT_PUB_KEY, audience="test")
|
return jwt.decode(token, JWT_PUB_KEY, audience="test")
|
||||||
except JWTError as e:
|
except JWTError as e:
|
||||||
logger.error("decodeToken: {}".format(e))
|
logger.error("{}".format(e))
|
||||||
raise werkzeug.exceptions.Unauthorized()
|
raise werkzeug.exceptions.Unauthorized()
|
||||||
|
|
||||||
def getSecret(user, token_info):
|
def testToken(user, token_info):
|
||||||
return '''
|
return '''
|
||||||
You are user_id {user} and the secret is 'wbevuec'.
|
You are user_id {user} and the provided token has been signed by this issuers. Fine.'.
|
||||||
Decoded token claims: {token_info}.
|
Decoded token claims: {token_info}.
|
||||||
'''.format(user=user, token_info=token_info)
|
'''.format(user=user, token_info=token_info)
|
||||||
|
|
||||||
|
37
openapi.yaml
37
openapi.yaml
@ -4,16 +4,18 @@ info:
|
|||||||
version: "0.1"
|
version: "0.1"
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
/auth:
|
/token:
|
||||||
post:
|
post:
|
||||||
tags: [ "JWT" ]
|
tags: [ "JWT" ]
|
||||||
summary: Accept login and password, return JWT token
|
summary: Accept encrypted or clear set of credentials, return JWT token
|
||||||
operationId: auth.generateToken
|
operationId: auth.generateToken
|
||||||
requestBody:
|
requestBody:
|
||||||
content:
|
content:
|
||||||
'application/json':
|
'application/json':
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/User'
|
anyOf:
|
||||||
|
- $ref: '#/components/schemas/User'
|
||||||
|
- $ref: '#/components/schemas/EncUser'
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: JWT token
|
description: JWT token
|
||||||
@ -21,28 +23,11 @@ paths:
|
|||||||
'text/plain':
|
'text/plain':
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
/authe:
|
/test:
|
||||||
post:
|
|
||||||
tags: [ "JWT" ]
|
|
||||||
summary: Accept encrypted set of credentials, return JWT token
|
|
||||||
operationId: auth.generateTokenFromEnc
|
|
||||||
requestBody:
|
|
||||||
content:
|
|
||||||
'text/plain':
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
responses:
|
|
||||||
'200':
|
|
||||||
description: JWT token
|
|
||||||
content:
|
|
||||||
'text/plain':
|
|
||||||
schema:
|
|
||||||
type: string
|
|
||||||
/secret:
|
|
||||||
get:
|
get:
|
||||||
tags: [ "JWT" ]
|
tags: [ "Test" ]
|
||||||
summary: Return secret string
|
summary: Return secret string
|
||||||
operationId: auth.getSecret
|
operationId: auth.testToken
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: secret response
|
description: secret response
|
||||||
@ -84,3 +69,9 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
password:
|
password:
|
||||||
type: string
|
type: string
|
||||||
|
EncUser:
|
||||||
|
description: Encrypted Application/Login/Password tuple
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
encAleTuple:
|
||||||
|
type: string
|
||||||
|
2
test.py
2
test.py
@ -1,7 +1,7 @@
|
|||||||
import connexion
|
import connexion
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
|
|
||||||
app = connexion.App('authservice')
|
app = connexion.App('authservice')
|
||||||
app.add_api('./openapi.yaml')
|
app.add_api('./openapi.yaml')
|
||||||
|
27
testjwe.py
27
testjwe.py
@ -1,9 +1,28 @@
|
|||||||
|
import unittest
|
||||||
from jose import jwe
|
from jose import jwe
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
JWT_PUB_KEY = os.environ["JWT_PUB_KEY"]
|
JWT_PUB_KEY = os.environ["JWT_PUB_KEY"]
|
||||||
|
JWT_PRIV_KEY = os.environ["JWT_PRIV_KEY"]
|
||||||
|
|
||||||
plainText = "BlaBlaBla123"
|
class JweTestMethods(unittest.TestCase):
|
||||||
cryptText = jwe.encrypt(plainText, JWT_PUB_KEY, "A256GCM", "RSA-OAEP")
|
def test_encryptDecrypt(self):
|
||||||
|
inObj = {"application":"test", "login":"wn", "password":"joshua"}
|
||||||
|
plainText = json.dumps(inObj)
|
||||||
|
|
||||||
print(cryptText)
|
cryptText = jwe.encrypt(plainText, JWT_PUB_KEY, "A256GCM", "RSA-OAEP")
|
||||||
|
print(cryptText)
|
||||||
|
|
||||||
|
clearText = jwe.decrypt(cryptText, JWT_PRIV_KEY)
|
||||||
|
print(clearText)
|
||||||
|
|
||||||
|
outObj = json.loads(clearText)
|
||||||
|
print(outObj)
|
||||||
|
|
||||||
|
self.assertEqual(outObj, inObj)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
|
Reference in New Issue
Block a user