From 02700e8c8b4fc5831ee200cfc464eb8254530a84 Mon Sep 17 00:00:00 2001 From: Adam Moussa Date: Fri, 31 Jul 2026 11:24:57 -0400 Subject: [PATCH] fix(auth): require Google authentication in cloud mode Remove the public shared-key mechanism and fail closed on Google auth while adding submit-route throttling. --- functions/submit_order/handler.py | 30 ++++++++++++++++-------------- src/server/generate_form.py | 2 +- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/functions/submit_order/handler.py b/functions/submit_order/handler.py index d6c6276..2704122 100644 --- a/functions/submit_order/handler.py +++ b/functions/submit_order/handler.py @@ -65,10 +65,6 @@ def _get_discount_settings() -> tuple[Decimal, Decimal]: return _settings -def _get_admin_emails() -> set[str]: - return {email.lower() for email in get_settings().get("admin_emails", [])} - - def _google_auth_configured() -> bool: return bool(os.environ.get("GOOGLE_CLIENT_ID_PARAM", "")) @@ -151,10 +147,6 @@ def _verify_google_token(token: str) -> tuple[dict | None, str]: return None, "invalid" -def _authentication_service_unavailable() -> dict: - return response(503, {"error": "Authentication service temporarily unavailable"}) - - def _verify_admin(event) -> tuple[dict | None, dict | None]: """Verify Google auth and admin access. Returns (user_info, error_response).""" if not _google_auth_configured(): @@ -171,11 +163,14 @@ def _verify_admin(event) -> tuple[dict | None, dict | None]: user_info, status = _verify_google_token(token) if status == "unavailable": - return None, _authentication_service_unavailable() + return None, response( + 503, {"error": "Authentication service temporarily unavailable"} + ) if user_info is None: return None, response(403, {"error": "Invalid or unauthorized Google account"}) - if user_info["email"].lower() not in _get_admin_emails(): + admin_emails = {e.lower() for e in get_settings().get("admin_emails", [])} + if user_info["email"].lower() not in admin_emails: return None, response(403, {"error": "Admin access required"}) return user_info, None @@ -427,15 +422,21 @@ def handle_submit(event): client_id = _get_google_client_id() except Exception as exc: logger.error("SSM fetch failed for Google client ID: %s", exc) - return _authentication_service_unavailable() + return response( + 503, {"error": "Authentication service temporarily unavailable"} + ) if not client_id: logger.error("Google client ID is unavailable") - return _authentication_service_unavailable() + return response( + 503, {"error": "Authentication service temporarily unavailable"} + ) if not google_token: return response(403, {"error": "Google authentication is required"}) user_info, verify_status = _verify_google_token(google_token) if verify_status == "unavailable": - return _authentication_service_unavailable() + return response( + 503, {"error": "Authentication service temporarily unavailable"} + ) if user_info is None: return response(403, {"error": "Invalid or unauthorized Google account"}) name = user_info["name"] @@ -452,7 +453,8 @@ def handle_submit(event): week = current_week() status = get_form_status(week) - is_admin_user = email.lower() in _get_admin_emails() + admin_emails = {e.lower() for e in get_settings().get("admin_emails", [])} + is_admin_user = email.lower() in admin_emails if status == "closed" and not is_admin_user: return response(410, {"error": "Orders are closed for this week"}) if status == "not_found": diff --git a/src/server/generate_form.py b/src/server/generate_form.py index 26819d2..d74c283 100644 --- a/src/server/generate_form.py +++ b/src/server/generate_form.py @@ -159,7 +159,7 @@ def main(): ssm = boto3.client("ssm") resp = ssm.get_parameter(Name="/meal-order-manager/google-client-id") - google_client_id = resp["Parameter"]["Value"].strip() + google_client_id = resp["Parameter"]["Value"] except Exception as exc: parser.error( "Google auth is required in cloud mode, but the Google client ID "