#api/auth.py from flask import Blueprint, session, redirect, url_for, jsonify from authlib.integrations.flask_client import OAuth from contexts.RequestContext import RequestContext from api import limiter import env_provider import logging logger = logging.getLogger(__name__) auth_bp = Blueprint('auth', __name__, url_prefix='/api') oauth = OAuth() keycloak = oauth.register( 'keycloak', client_id=env_provider.CLIENT_ID, client_secret=env_provider.CLIENT_SECRET, server_metadata_url="https://login.hangman-lab.top/auth/realms/Hangman-Lab/.well-known/openid-configuration", client_kwargs={"scope": "openid email profile"}, ) @auth_bp.route('/login', methods=['GET']) @limiter.limit("20 per minute") def login(): redirect_uri = url_for("auth.authorize", _external=True) return keycloak.authorize_redirect(redirect_uri) @auth_bp.route('/authorize', methods=['GET']) @limiter.limit("20 per minute") def authorize(): try: token = keycloak.authorize_access_token() user_info = keycloak.parse_id_token(token) session['user'] = user_info return jsonify({"message": "login successful", "user": user_info}) except Exception as e: logger.error(f"Authorization failed: {str(e)}") errno = RequestContext.get_error_id() return jsonify({"error": f"Authorization failed - {errno}"}), 401 @auth_bp.route('/logout', methods=['GET']) def logout(): u = session.pop('user', None) if u: logger.info(f"Logged out user: {u}") logout_url = "https://login.hangman-lab.top/auth/realms/Hangman-Lab/protocol/openid-connect/logout" return redirect(logout_url) @auth_bp.route("/user", methods=["GET"]) @limiter.limit("80 per minute") def user(): u = session.get('user') if not u: return jsonify({"username": "guest", "role": "guest"}) return jsonify(u)