diff --git a/ENV.tmpl b/ENV.tmpl index dff8c2c..e5dbece 100644 --- a/ENV.tmpl +++ b/ENV.tmpl @@ -5,3 +5,7 @@ export DB_USER="hausverwaltung-ui" export DB_PASS="test123" export DB_NAME="hausverwaltung" +export JWT_ISSUER='de.hottis.hausverwaltung' +export JWT_SECRET='streng_geheim' +export JWT_LIFETIME_SECONDS=60 +export JWT_ALGORITHM='HS256' diff --git a/auth.py b/auth.py new file mode 100755 index 0000000..645f298 --- /dev/null +++ b/auth.py @@ -0,0 +1,41 @@ +import time +import connexion +import six +from werkzeug.exceptions import Unauthorized +from jose import JWTError, jwt +import os + +JWT_ISSUER = os.environ['JWT_ISSUER'] +JWT_SECRET = os.environ['JWT_SECRET'] +JWT_LIFETIME_SECONDS = int(os.environ['JWT_LIFETIME_SECONDS']) +JWT_ALGORITHM = os.environ['JWT_ALGORITHM'] + + +def generate_token(user_id): + timestamp = _current_timestamp() + payload = { + "iss": JWT_ISSUER, + "iat": int(timestamp), + "exp": int(timestamp + JWT_LIFETIME_SECONDS), + "sub": str(user_id), + } + return jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM) + + +def decode_token(token): + try: + return jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM]) + except JWTError as e: + six.raise_from(Unauthorized, e) + + +def get_secret(user, token_info) -> str: + return ''' + You are user_id {user} and the secret is 'wbevuec'. + Decoded token claims: {token_info}. + '''.format(user=user, token_info=token_info) + + +def _current_timestamp() -> int: + return int(time.time()) + diff --git a/swagger.yaml b/openapi.yaml similarity index 88% rename from swagger.yaml rename to openapi.yaml index c937c4d..a4e0471 100644 --- a/swagger.yaml +++ b/openapi.yaml @@ -126,6 +126,9 @@ paths: description: No Mieter available 500: description: Some server error + security: + - jwt: ['secret'] + /hv/mieter/{id}: get: tags: [ "Mieter" ] @@ -296,24 +299,65 @@ paths: description: Neither Forderungen nor Zahlungen available 500: description: Some server error -# /hv/zahlung: -# post: -# tags: [ "Zahlung" ] -# operationId: ZahlungenForderungen.put_zahlung -# summary: Inserts a new Zahlung -# parameters: -# - name: zahlung -# in: body -# schema: -# $ref: '#/components/schemas/Zahlung' -# responses: -# 202: -# description: Zahlung successfully inserted -# 500: -# description: Some server or database error + /hv/zahlung: + post: + tags: [ "Zahlung" ] + operationId: ZahlungenForderungen.put_zahlung + summary: Inserts a new Zahlung + parameters: + - name: zahlung + in: body + schema: + $ref: '#/components/schemas/Zahlung' + responses: + 202: + description: Zahlung successfully inserted + 500: + description: Some server or database error + /auth/{user_id}: + get: + tags: [ "JWT" ] + summary: Return JWT token + operationId: auth.generate_token + parameters: + - name: user_id + description: User unique identifier + in: path + required: true + example: 12 + schema: + type: integer + responses: + '200': + description: JWT token + content: + 'text/plain': + schema: + type: string + /secret: + get: + tags: [ "JWT" ] + summary: Return secret string + operationId: auth.get_secret + responses: + '200': + description: secret response + content: + 'text/plain': + schema: + type: string + security: + - jwt: ['secret'] + components: + securitySchemes: + jwt: + type: http + scheme: bearer + bearerFormat: JWT + x-bearerInfoFunc: auth.decode_token schemas: Objekt: description: Objekt type diff --git a/server.py b/server.py index 301dfe0..24585de 100644 --- a/server.py +++ b/server.py @@ -3,7 +3,7 @@ from flask_cors import CORS # instantiate the webservice app = connexion.App(__name__) -app.add_api('swagger.yaml') +app.add_api('openapi.yaml') # CORSify it - otherwise Angular won't accept it CORS(app.app)