Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
d521e146cf
|
|||
0d698568d4
|
|||
3541226964
|
|||
216e1c0684
|
|||
f8afd95a82
|
|||
e29ce48971
|
|||
7163db9ce9
|
|||
629a85fc3e
|
|||
b2e1ecab2b
|
|||
5b1209679b
|
|||
9929b38db7
|
|||
91178b1fa7
|
|||
1f55ef0a80
|
|||
19b8aab8c2
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,6 @@
|
||||
__pycache__/
|
||||
ENV
|
||||
config/
|
||||
*~
|
||||
.*~
|
||||
|
||||
|
20
asadduser.py
20
asadduser.py
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import mariadb
|
||||
import psycopg2
|
||||
from pbkdf2 import crypt
|
||||
import argparse
|
||||
import os
|
||||
@ -23,30 +23,26 @@ password = args.password
|
||||
application = args.application
|
||||
|
||||
|
||||
DB_USER = os.environ["DB_USER"]
|
||||
DB_PASS = os.environ["DB_PASS"]
|
||||
DB_HOST = os.environ["DB_HOST"]
|
||||
DB_NAME = os.environ["DB_NAME"]
|
||||
DB_NAME = "authservice"
|
||||
|
||||
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 = psycopg2.connect(database = DB_NAME)
|
||||
conn.autocommit = False
|
||||
|
||||
cur = conn.cursor()
|
||||
cur.execute("""
|
||||
INSERT INTO users (login, pwhash)
|
||||
VALUES(?, ?)
|
||||
INSERT INTO user_t (login, pwhash)
|
||||
VALUES(%s, %s)
|
||||
""", [user, pwhash])
|
||||
cur.execute("""
|
||||
INSERT INTO user_applications_mapping (application, user)
|
||||
INSERT INTO user_application_mapping_t (application,"user")
|
||||
VALUES(
|
||||
(SELECT id FROM applications WHERE name = ?),
|
||||
(SELECT id FROM users WHERE login = ?)
|
||||
(SELECT id FROM application_t WHERE name = %s),
|
||||
(SELECT id FROM user_t WHERE login = %s)
|
||||
)
|
||||
""", [application, user])
|
||||
conn.commit()
|
||||
|
316
auth.py
316
auth.py
@ -1,48 +1,81 @@
|
||||
import time
|
||||
import connexion
|
||||
from jose import JWTError, jwt
|
||||
from jose import JWTError, jwt, jwe
|
||||
import json
|
||||
from jose.exceptions import ExpiredSignatureError
|
||||
import werkzeug
|
||||
import os
|
||||
import psycopg2
|
||||
from collections import namedtuple
|
||||
from pbkdf2 import crypt
|
||||
from loguru import logger
|
||||
|
||||
DB_USER = os.environ["DB_USER"]
|
||||
DB_PASS = os.environ["DB_PASS"]
|
||||
DB_HOST = os.environ["DB_HOST"]
|
||||
DB_NAME = os.environ["DB_NAME"]
|
||||
|
||||
JWT_ISSUER = os.environ["JWT_ISSUER"]
|
||||
|
||||
import configparser
|
||||
import random
|
||||
import string
|
||||
from flask import request
|
||||
|
||||
|
||||
DB_USER = ""
|
||||
DB_PASS = ""
|
||||
DB_HOST = ""
|
||||
DB_NAME = ""
|
||||
JWT_ISSUER = ""
|
||||
try:
|
||||
DB_USER = os.environ["DB_USER"]
|
||||
DB_PASS = os.environ["DB_PASS"]
|
||||
DB_HOST = os.environ["DB_HOST"]
|
||||
DB_NAME = os.environ["DB_NAME"]
|
||||
JWT_ISSUER = os.environ["JWT_ISSUER"]
|
||||
except KeyError:
|
||||
config = configparser.ConfigParser()
|
||||
config.read('./config/config.ini')
|
||||
DB_USER = config["database"]["user"]
|
||||
DB_PASS = config["database"]["pass"]
|
||||
DB_HOST = config["database"]["host"]
|
||||
DB_NAME = config["database"]["name"]
|
||||
JWT_ISSUER = config["jwt"]["issuer"]
|
||||
|
||||
|
||||
class NoUserException(Exception):
|
||||
pass
|
||||
|
||||
class RefreshTokenExpiredException(Exception):
|
||||
pass
|
||||
|
||||
class NoTokenException(Exception):
|
||||
pass
|
||||
|
||||
class NoValidTokenException(Exception):
|
||||
pass
|
||||
|
||||
class ManyUsersException(Exception):
|
||||
pass
|
||||
|
||||
class ManyTokensException(Exception):
|
||||
pass
|
||||
|
||||
class PasswordMismatchException(Exception):
|
||||
pass
|
||||
|
||||
class RefreshTokenExpiredException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
UserEntry = namedtuple('UserEntry', ['id', 'login', 'pwhash', 'expiry', 'claims'])
|
||||
RefreshTokenEntry = namedtuple('RefreshTokenEntry', ['id', 'salt', 'login', 'app', 'expiry'])
|
||||
|
||||
JWT_PRIV_KEY = ""
|
||||
try:
|
||||
JWT_PRIV_KEY = os.environ["JWT_PRIV_KEY"]
|
||||
except KeyError:
|
||||
with open('/opt/app/config/authservice.key', 'r') as f:
|
||||
with open('./config/authservice.key', 'r') as f:
|
||||
JWT_PRIV_KEY = f.read()
|
||||
|
||||
JWT_PUB_KEY = ""
|
||||
try:
|
||||
JWT_PUB_KEY = os.environ["JWT_PUB_KEY"]
|
||||
except KeyError:
|
||||
with open('/opt/app/config/authservice.pub', 'r') as f:
|
||||
with open('./config/authservice.pub', 'r') as f:
|
||||
JWT_PUB_KEY = f.read()
|
||||
|
||||
|
||||
@ -60,7 +93,7 @@ def getUserEntryFromDB(application: str, login: str):
|
||||
" WHERE application = %s AND login = %s",
|
||||
(application, login))
|
||||
userObj = cur.fetchone()
|
||||
logger.debug("getUserEntryFromDB: userObj: {}".format(userObj))
|
||||
logger.debug("userObj: {}".format(userObj))
|
||||
if not userObj:
|
||||
raise NoUserException()
|
||||
invObj = cur.fetchone()
|
||||
@ -72,7 +105,7 @@ def getUserEntryFromDB(application: str, login: str):
|
||||
cur.execute('SELECT key, value FROM claims_for_user_v where "user" = %s and application = %s',
|
||||
(userObj[0], application))
|
||||
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 isinstance(claims[claimObj[0]], list):
|
||||
claims[claimObj[0]].append(claimObj[1])
|
||||
@ -91,20 +124,111 @@ def getUserEntryFromDB(application: str, login: str):
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
def getRefreshTokenFromDB(application, login, httpClientIp):
|
||||
conn = None
|
||||
cur = None
|
||||
try:
|
||||
conn = psycopg2.connect(user = DB_USER, password = DB_PASS,
|
||||
host = DB_HOST, database = DB_NAME)
|
||||
conn.autocommit = False
|
||||
|
||||
with conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute('SELECT u.id, u.expiry, a.name FROM user_t u, application_t a, user_application_mapping_t m' +
|
||||
' WHERE u.login = %s AND ' +
|
||||
' a.name = %s AND ' +
|
||||
' a.id = m.application AND u.id = m."user"',
|
||||
(login, application))
|
||||
userObj = cur.fetchone()
|
||||
logger.debug("userObj: {}".format(userObj))
|
||||
if not userObj:
|
||||
raise NoUserException()
|
||||
invObj = cur.fetchone()
|
||||
if invObj:
|
||||
raise ManyUsersException()
|
||||
|
||||
with conn.cursor() as cur:
|
||||
salt = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(64))
|
||||
cur.execute('INSERT INTO token_t ("user", salt, expiry, client_ip) VALUES (%s, %s, %s, %s) RETURNING id',
|
||||
(userObj[0], salt, userObj[1], httpClientIp))
|
||||
tokenObj = cur.fetchone()
|
||||
logger.debug("tokenObj: {}".format(tokenObj))
|
||||
if not tokenObj:
|
||||
raise NoTokenException()
|
||||
invObj = cur.fetchone()
|
||||
if invObj:
|
||||
raise ManyTokensException()
|
||||
|
||||
refreshTokenEntry = RefreshTokenEntry(id=tokenObj[0], salt=salt, login=login, app=userObj[2], expiry=userObj[1])
|
||||
|
||||
return refreshTokenEntry
|
||||
except psycopg2.Error as err:
|
||||
raise Exception("Error when connecting to database: {}".format(err))
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
def getUserEntry(application, login, password):
|
||||
userEntry = getUserEntryFromDB(application, login)
|
||||
if userEntry.pwhash != crypt(password, userEntry.pwhash):
|
||||
raise PasswordMismatchException()
|
||||
return userEntry
|
||||
|
||||
def generateToken(**args):
|
||||
def generateToken(func, **args):
|
||||
try:
|
||||
body = args["body"]
|
||||
|
||||
application = ""
|
||||
login = ""
|
||||
password = ""
|
||||
if (("application" in body) and
|
||||
("login" in body) and
|
||||
("password" in body)):
|
||||
application = body["application"]
|
||||
login = body["login"]
|
||||
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")
|
||||
|
||||
userEntry = getUserEntry(application, login, password)
|
||||
if request.headers.getlist("X-Forwarded-For"):
|
||||
httpClientIp = request.headers.getlist("X-Forwarded-For")[0]
|
||||
else:
|
||||
httpClientIp = request.remote_addr
|
||||
|
||||
logger.debug(f"Tuple: {application} {login} {password} {httpClientIp}")
|
||||
|
||||
return func(application, login, password, httpClientIp)
|
||||
except NoTokenException:
|
||||
logger.error("no token created")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except ManyTokensException:
|
||||
logger.error("too many tokens created")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except NoUserException:
|
||||
logger.error("no user found, login or application wrong")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except ManyUsersException:
|
||||
logger.error("too many users found")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except PasswordMismatchException:
|
||||
logger.error("wrong password")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except KeyError:
|
||||
logger.error("application, login or password missing")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except Exception as e:
|
||||
logger.error("unspecific exception: {}".format(str(e)))
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
|
||||
|
||||
def _makeSimpleToken(application, login, password, httpClientIp, refresh=False):
|
||||
userEntry = getUserEntry(application, login, password) if not refresh else getUserEntryFromDB(application, login)
|
||||
|
||||
timestamp = int(time.time())
|
||||
payload = {
|
||||
@ -116,30 +240,40 @@ def generateToken(**args):
|
||||
}
|
||||
logger.debug("claims: {}".format(userEntry.claims))
|
||||
for claim in userEntry.claims.items():
|
||||
logger.debug("generateToken: add claim {}".format(claim))
|
||||
logger.debug("add claim {}".format(claim))
|
||||
payload[claim[0]] = claim[1]
|
||||
|
||||
return jwt.encode(payload, JWT_PRIV_KEY, algorithm='RS256')
|
||||
except NoUserException:
|
||||
logger.error("generateToken: no user found, login or application wrong")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except ManyUsersException:
|
||||
logger.error("generateToken: too many users found")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except PasswordMismatchException:
|
||||
logger.error("generateToken: wrong password")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except KeyError:
|
||||
logger.error("generateToken: application, login or password missing")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except Exception as e:
|
||||
logger.error("generateToken: unspecific exception: {}".format(str(e)))
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
|
||||
def generateTokenFromEnc(**args):
|
||||
cryptContent = args["body"]
|
||||
raise werkzeug.exceptions.NotImplemented("Stay tuned, will be added soon")
|
||||
return str(cryptContent)
|
||||
def _makeRefreshToken(application, login, password, httpClientIp):
|
||||
refreshTokenEntry = getRefreshTokenFromDB(application, login, httpClientIp)
|
||||
|
||||
timestamp = int(time.time())
|
||||
payload = {
|
||||
"iss": JWT_ISSUER,
|
||||
"iat": int(timestamp),
|
||||
"exp": int(timestamp + refreshTokenEntry.expiry),
|
||||
"sub": str(refreshTokenEntry.login),
|
||||
"xap": str(refreshTokenEntry.app),
|
||||
"xid": str(refreshTokenEntry.id),
|
||||
"xal": str(refreshTokenEntry.salt)
|
||||
}
|
||||
|
||||
return jwt.encode(payload, JWT_PRIV_KEY, algorithm='RS256')
|
||||
|
||||
def _makeRefreshableTokens(application, login, password, httpClientIp):
|
||||
authToken = _makeSimpleToken(application, login, password, httpClientIp)
|
||||
refreshToken = _makeRefreshToken(application, login, password, httpClientIp)
|
||||
return {
|
||||
"authToken": authToken,
|
||||
"refreshToken": refreshToken
|
||||
}
|
||||
|
||||
def generateSimpleToken(**args):
|
||||
|
||||
return generateToken(_makeSimpleToken, **args)
|
||||
def generateRefreshableTokens(**args):
|
||||
return generateToken(_makeRefreshableTokens, **args)
|
||||
|
||||
def getPubKey():
|
||||
return JWT_PUB_KEY
|
||||
@ -148,12 +282,112 @@ def decodeToken(token):
|
||||
try:
|
||||
return jwt.decode(token, JWT_PUB_KEY, audience="test")
|
||||
except JWTError as e:
|
||||
logger.error("decodeToken: {}".format(e))
|
||||
logger.error("{}".format(e))
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
|
||||
def testToken(user, token_info):
|
||||
return {
|
||||
"message": f"You are user_id {user} and the provided token has been signed by this issuers. Fine.",
|
||||
"details": token_info
|
||||
}
|
||||
|
||||
|
||||
def checkAndInvalidateRefreshToken(login, xid, xal, httpClientIp):
|
||||
try:
|
||||
validTokenFound = False
|
||||
|
||||
conn = psycopg2.connect(user = DB_USER, password = DB_PASS,
|
||||
host = DB_HOST, database = DB_NAME)
|
||||
conn.autocommit = False
|
||||
|
||||
with conn:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute('SELECT t.id, t.client_ip FROM token_t t, user_t u' +
|
||||
' WHERE t.valid = true AND ' +
|
||||
' t.id = %s AND ' +
|
||||
' t.salt = %s AND ' +
|
||||
' t."user" = u.id AND ' +
|
||||
' u.login = %s',
|
||||
(xid, xal, login))
|
||||
tokenObj = cur.fetchone()
|
||||
logger.debug("tokenObj: {}".format(tokenObj))
|
||||
if not tokenObj:
|
||||
raise NoTokenException()
|
||||
invObj = cur.fetchone()
|
||||
if invObj:
|
||||
raise ManyTokensException()
|
||||
|
||||
if (tokenObj[1] == httpClientIp):
|
||||
with conn.cursor() as cur:
|
||||
cur.execute('UPDATE token_t SET used = used + 1 WHERE id = %s',
|
||||
[ xid ])
|
||||
validTokenFound = True
|
||||
else:
|
||||
logger.warning(f"Client IP in token {tokenObj[1]} and current one {httpClientIp} does not match")
|
||||
with conn.cursor() as cur:
|
||||
cur.execute('UPDATE token_t SET valid = false WHERE id = %s',
|
||||
[ xid ])
|
||||
if (not validTokenFound):
|
||||
raise NoValidTokenException()
|
||||
|
||||
except psycopg2.Error as err:
|
||||
raise Exception("Error when connecting to database: {}".format(err))
|
||||
finally:
|
||||
if conn:
|
||||
conn.close()
|
||||
|
||||
|
||||
def refreshTokens(**args):
|
||||
try:
|
||||
refreshToken = args["body"]
|
||||
refreshTokenObj = jwt.decode(refreshToken, JWT_PUB_KEY)
|
||||
logger.info(str(refreshTokenObj))
|
||||
|
||||
if request.headers.getlist("X-Forwarded-For"):
|
||||
httpClientIp = request.headers.getlist("X-Forwarded-For")[0]
|
||||
else:
|
||||
httpClientIp = request.remote_addr
|
||||
|
||||
if refreshTokenObj["exp"] < int(time.time()):
|
||||
raise RefreshTokenExpiredException()
|
||||
|
||||
checkAndInvalidateRefreshToken(refreshTokenObj["sub"], refreshTokenObj["xid"], refreshTokenObj["xal"], httpClientIp)
|
||||
|
||||
authToken = _makeSimpleToken(refreshTokenObj["xap"], refreshTokenObj["sub"], "", httpClientIp, refresh=True)
|
||||
refreshToken = _makeRefreshToken(refreshTokenObj["xap"], refreshTokenObj["sub"], "", httpClientIp)
|
||||
return {
|
||||
"authToken": authToken,
|
||||
"refreshToken": refreshToken
|
||||
}
|
||||
except JWTError as e:
|
||||
logger.error("jwt.decode failed: {}".format(e))
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except RefreshTokenExpiredException:
|
||||
logger.error("refresh token expired")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except NoTokenException:
|
||||
logger.error("no token created/found")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except NoValidTokenException:
|
||||
logger.error("no valid token found")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except ManyTokensException:
|
||||
logger.error("too many tokens created/found")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except NoUserException:
|
||||
logger.error("no user found, login or application wrong")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except ManyUsersException:
|
||||
logger.error("too many users found")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except PasswordMismatchException:
|
||||
logger.error("wrong password")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except KeyError:
|
||||
logger.error("application, login or password missing")
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
except Exception as e:
|
||||
logger.error("unspecific exception: {}".format(str(e)))
|
||||
raise werkzeug.exceptions.Unauthorized()
|
||||
|
||||
def getSecret(user, token_info):
|
||||
return '''
|
||||
You are user_id {user} and the secret is 'wbevuec'.
|
||||
Decoded token claims: {token_info}.
|
||||
'''.format(user=user, token_info=token_info)
|
||||
|
||||
|
2
build.sh
2
build.sh
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
IMAGE_NAME="registry.hottis.de/wolutator/authservice"
|
||||
VERSION=0.0.1
|
||||
VERSION=0.3.x
|
||||
|
||||
docker build -t ${IMAGE_NAME}:${VERSION} .
|
||||
# docker push ${IMAGE_NAME}:${VERSION}
|
||||
|
@ -12,6 +12,14 @@ create table user_t (
|
||||
expiry integer not null default 600
|
||||
);
|
||||
|
||||
create sequence token_s start with 1 increment by 1;
|
||||
create table token_t (
|
||||
id integer primary key not null default nextval('token_s'),
|
||||
"user" integer not null references user_t (id),
|
||||
salt varchar(64) not null,
|
||||
valid boolean not null default true
|
||||
);
|
||||
|
||||
create sequence claim_s start with 1 increment by 1;
|
||||
create table claim_t (
|
||||
id integer primary key not null default nextval('claim_s'),
|
||||
|
82
openapi.yaml
82
openapi.yaml
@ -4,16 +4,18 @@ info:
|
||||
version: "0.1"
|
||||
|
||||
paths:
|
||||
/auth:
|
||||
/token:
|
||||
post:
|
||||
tags: [ "JWT" ]
|
||||
summary: Accept login and password, return JWT token
|
||||
operationId: auth.generateToken
|
||||
summary: Accepts encrypted or clear set of credentials, returns JWT token
|
||||
operationId: auth.generateSimpleToken
|
||||
requestBody:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/User'
|
||||
- $ref: '#/components/schemas/EncUser'
|
||||
responses:
|
||||
'200':
|
||||
description: JWT token
|
||||
@ -21,35 +23,54 @@ paths:
|
||||
'text/plain':
|
||||
schema:
|
||||
type: string
|
||||
/authe:
|
||||
/refreshable:
|
||||
post:
|
||||
tags: [ "JWT" ]
|
||||
summary: Accept encrypted set of credentials, return JWT token
|
||||
operationId: auth.generateTokenFromEnc
|
||||
summary: Accepts encrypted or clear set of credentials, returns tuple of AuthToken and RefreshToken
|
||||
operationId: auth.generateRefreshableTokens
|
||||
requestBody:
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
anyOf:
|
||||
- $ref: '#/components/schemas/User'
|
||||
- $ref: '#/components/schemas/EncUser'
|
||||
responses:
|
||||
'200':
|
||||
description: Token tuple
|
||||
content:
|
||||
'application/json':
|
||||
schema:
|
||||
$ref: '#/components/schemas/TokenTuple'
|
||||
/refresh:
|
||||
post:
|
||||
tags: [ "JWT" ]
|
||||
summary: Accepts refresh token, returns tuple of AuthToken and RefreshToken
|
||||
operationId: auth.refreshTokens
|
||||
requestBody:
|
||||
content:
|
||||
'text/plain':
|
||||
schema:
|
||||
type: string
|
||||
$ref: '#/components/schemas/RefreshToken'
|
||||
responses:
|
||||
'200':
|
||||
description: JWT token
|
||||
description: Token tuple
|
||||
content:
|
||||
'text/plain':
|
||||
'application/json':
|
||||
schema:
|
||||
type: string
|
||||
/secret:
|
||||
$ref: '#/components/schemas/TokenTuple'
|
||||
/test:
|
||||
get:
|
||||
tags: [ "JWT" ]
|
||||
tags: [ "Test" ]
|
||||
summary: Return secret string
|
||||
operationId: auth.getSecret
|
||||
operationId: auth.testToken
|
||||
responses:
|
||||
'200':
|
||||
description: secret response
|
||||
content:
|
||||
'text/plain':
|
||||
'application/json':
|
||||
schema:
|
||||
type: string
|
||||
$ref: '#/components/schemas/TestOutput'
|
||||
security:
|
||||
- jwt: ['secret']
|
||||
/pubkey:
|
||||
@ -84,3 +105,32 @@ components:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
EncUser:
|
||||
description: Encrypted Application/Login/Password tuple
|
||||
type: object
|
||||
properties:
|
||||
encAleTuple:
|
||||
type: string
|
||||
TestOutput:
|
||||
description: Test Output
|
||||
type: object
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
details:
|
||||
type: object
|
||||
AuthToken:
|
||||
description: Token for authentication purposes, just a string
|
||||
type: string
|
||||
RefreshToken:
|
||||
description: Token for refresh purposes, just a string
|
||||
type: string
|
||||
TokenTuple:
|
||||
description: Test Output
|
||||
type: object
|
||||
properties:
|
||||
authToken:
|
||||
$ref: '#/components/schemas/AuthToken'
|
||||
refreshToken:
|
||||
$ref: '#/components/schemas/RefreshToken'
|
||||
|
||||
|
2
test.py
2
test.py
@ -1,7 +1,7 @@
|
||||
import connexion
|
||||
import logging
|
||||
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
app = connexion.App('authservice')
|
||||
app.add_api('./openapi.yaml')
|
||||
|
27
testjwe.py
27
testjwe.py
@ -1,9 +1,28 @@
|
||||
import unittest
|
||||
from jose import jwe
|
||||
|
||||
import os
|
||||
import json
|
||||
|
||||
JWT_PUB_KEY = os.environ["JWT_PUB_KEY"]
|
||||
JWT_PRIV_KEY = os.environ["JWT_PRIV_KEY"]
|
||||
|
||||
plainText = "BlaBlaBla123"
|
||||
cryptText = jwe.encrypt(plainText, JWT_PUB_KEY, "A256GCM", "RSA-OAEP")
|
||||
class JweTestMethods(unittest.TestCase):
|
||||
def test_encryptDecrypt(self):
|
||||
inObj = {"application":"hv2", "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