import os import json import time import uuid import hmac import base64 import hashlib from urllib.parse import quote from flask import Blueprint, session, redirect, url_for, flash portal_service_launch_bp = Blueprint("portal_service_launch", __name__) def _b64url_encode(data: bytes) -> str: return base64.urlsafe_b64encode(data).rstrip(b"=").decode("utf-8") def _sign_payload(payload: dict, secret: str) -> str: payload_json = json.dumps(payload, separators=(",", ":"), sort_keys=True).encode("utf-8") payload_b64 = _b64url_encode(payload_json) sig = hmac.new(secret.encode("utf-8"), payload_b64.encode("utf-8"), hashlib.sha256).digest() sig_b64 = _b64url_encode(sig) return f"{payload_b64}.{sig_b64}" @portal_service_launch_bp.route("/portal/services/follow-me-launch") def portal_follow_me_launch(): portal_client_id = session.get("portal_client_id") portal_email = session.get("portal_email") if not portal_client_id or not portal_email: flash("Please sign in to launch Follow-me.", "warning") return redirect(url_for("portal_login")) secret = os.getenv("FMV2_HANDOFF_SECRET", "").strip() base_url = os.getenv("FMV2_BASE_URL", "https://follow-me.outsidethebox.top").strip().rstrip("/") ttl_seconds = int(os.getenv("FMV2_HANDOFF_TTL_SECONDS", "300")) if not secret: flash("Follow-me launch is not configured. Missing FMV2_HANDOFF_SECRET.", "danger") return redirect(url_for("portal_services.portal_services_home")) now = int(time.time()) payload = { "iss": "otb-billing", "aud": "fmv2", "jti": str(uuid.uuid4()), "iat": now, "exp": now + ttl_seconds, "portal_client_id": int(portal_client_id), "portal_email": portal_email, "portal_contact_name": session.get("portal_contact_name", ""), "portal_company_name": session.get("portal_company_name", ""), "return_to": "/dashboard", } token = _sign_payload(payload, secret) target = f"{base_url}/auth/portal-handoff?token={quote(token)}" return redirect(target)