diff --git a/.env-dist b/.env-dist index b960b66..8f680e4 100644 --- a/.env-dist +++ b/.env-dist @@ -1,4 +1,4 @@ -UNIFI_HOST = 'wlan.morz.de' +UNIFI_HOST = 'dein.unifi.controller' UNIFI_USERNAME = 'admin' UNIFI_PASSWORD = 'yourPassword' UNIFI_PORT = 443 @@ -6,3 +6,7 @@ UNIFI_SSL_VERIFY = True UNIFI_SITE_ID = 'yourSiteID' WLAN_SSID = 'your WLAN-SSID' WLAN_PASSWORD = 'your WLAN Passwort' +OIDC_CLIENT_ID = "linuxmuster-voucher" +OIDC_CLIENT_SECRET = "" +OIDC_ISSUER = "https://keycloak.deine-domain.de/realms/deinrealm" +OIDC_REDIRECT_URI = "https://voucher.deine-domain.tld/auth/callback" \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 19561b4..afddc60 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -15,7 +15,8 @@ services: working_dir: /app/script environment: - - DEV=false + - DEV=true + - DEBUG=true - PYTHONUNBUFFERED=1 env_file: - .env diff --git a/script/app.py b/script/app.py index 10b31c0..64d97d1 100644 --- a/script/app.py +++ b/script/app.py @@ -9,6 +9,7 @@ import json import qrcode import base64 import io +import datetime @@ -28,6 +29,7 @@ UNIFI_SITE_ID = os.getenv('UNIFI_SITE_ID', '') DEBUG = str_to_bool(os.getenv('DEBUG', 'False')) LOGO_FILE = os.getenv('LOGO_FILE', '/static/logo.jpg') WIFI_ICON = os.getenv('WIFI_ICON', '/static/wifi-icon.png') + if DEBUG: print("DEBUG mode is enabled.") print(f"UNIFI_HOST: {UNIFI_HOST}") @@ -36,6 +38,9 @@ if DEBUG: print(f"UNIFI_PORT: {UNIFI_PORT}") print(f"UNIFI_SSL_VERIFY: {UNIFI_SSL_VERIFY}") print(f"UNIFI_SITE_ID: {UNIFI_SITE_ID}") + print(f"LOGO_FILE: {LOGO_FILE}") + print(f"WIFI_ICON: {WIFI_ICON}") + LOGLEVEL = os.getenv('LOGLEVEL', 'INFO') @@ -122,6 +127,24 @@ buffer.seek(0) app = Flask(__name__) +# Keycloak-Konfiguration +app.secret_key = 'paiqwrqwrsfuhkcp8sdfisuhckjhyli' # ohne den geht Keycloak nicht +app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1) +app.config['OIDC_CLIENT_ID'] = os.getenv('OIDC_CLIENT_ID') +app.config['OIDC_CLIENT_SECRET'] = os.getenv('OIDC_CLIENT_SECRET') +app.config['OIDC_ISSUER'] = os.getenv('OIDC_ISSUER') +app.config['OIDC_REDIRECT_URI'] = os.getenv('OIDC_REDIRECT_URI') +app.config['SERVER_NAME'] = os.getenv('OIDC_REDIRECT_URI') +oauth = OAuth(app) +oauth.register( + name="keycloak", + client_id=app.config["OIDC_CLIENT_ID"], + client_secret=app.config["OIDC_CLIENT_SECRET"], + server_metadata_url=f"{app.config['OIDC_ISSUER']}/.well-known/openid-configuration", + client_kwargs={"scope": "openid profile email"}, +) + + # b64encode-Filter registrieren @app.template_filter('b64encode') def b64encode_filter(data): @@ -137,13 +160,17 @@ def b64encode_filter(data): @app.route("/") def home(): - return render_template("index.html", logo=LOGO_FILE) + if "user" not in session: + return redirect(url_for("login")) + return render_template("index.html", logo=LOGO_FILE, name=session['user']['given_name']) @app.route("/voucher/") def create_voucher(minutes): + if "user" not in session: + return redirect(url_for("login")) try: c = Controller(UNIFI_HOST, UNIFI_USERNAME, UNIFI_PASSWORD, port=UNIFI_PORT, ssl_verify=UNIFI_SSL_VERIFY, site_id=check_site_id(UNIFI_SITE_ID)) - code = api_create_voucher(c, time=minutes) # Platzhalter für echten Code + code = api_create_voucher(c, time=minutes, note=f"{session['user']['preferred_username']} - {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") # code aufbereiten: 5 Zeichen Bindestrich, 5 Zeichen Bindestrich, 5 Zeichen Bindestrich, 5 Zeichen code = f"{code[:5]}-{code[5:10]}" except Exception as e: @@ -152,6 +179,38 @@ def create_voucher(minutes): return render_template("voucher.html", code=code, minutes=minutes, qr_code=buffer, wifi_icon=WIFI_ICON) +@app.route('/login') +def login(): + # Generiere einen eindeutigen nonce-Wert + nonce = str(uuid.uuid4()) + session['nonce'] = nonce # Speichere den nonce in der Session + + redirect_uri = url_for('authorize', _external=True) + return oauth.keycloak.authorize_redirect(redirect_uri, nonce=nonce) + +@app.route('/authorize') +def authorize(): + token = oauth.keycloak.authorize_access_token() + print(token) + nonce = session.pop('nonce', None) # Hole den nonce aus der Session + if not nonce: + return "Fehler: nonce fehlt in der Session", 400 + print(nonce) + + user_info = oauth.keycloak.parse_id_token(token, nonce=nonce) + session['user'] = user_info + print(user_info) + print(session['user']) + return redirect(url_for('home')) + +# Logout-Route +@app.route("/logout") +def logout(): + session.pop("user", None) + return redirect(app.config["OIDC_ISSUER"] + "/protocol/openid-connect/logout?redirect_uri=" + url_for("home", _external=True)) + + + # Main script if __name__ == "__main__": app.run(host="0.0.0.0", port=42425, debug=True) diff --git a/script/templates/index.html b/script/templates/index.html index 8f3dc84..7ad7cb8 100644 --- a/script/templates/index.html +++ b/script/templates/index.html @@ -74,7 +74,7 @@
-
Bitte wähle die gewünschte Dauer für den WLAN-Zugang 😀
+
{{ name }}, bitte wähle die gewünschte Dauer für den WLAN-Zugang 😀
WLAN-Zugangscode
für
45min
erstellen
WLAN-Zugangscode
für
90min
erstellen
diff --git a/script/templates/voucher.html b/script/templates/voucher.html index daf2b9e..7115329 100644 --- a/script/templates/voucher.html +++ b/script/templates/voucher.html @@ -84,6 +84,7 @@ +
Der {{ minutes }}min Zugangscode: