mirror of
https://github.com/Sea-Haven-Industries/meal-order-manager.git
synced 2026-10-07 16:18:54 +00:00
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.
This commit is contained in:
parent
311eab35c0
commit
02700e8c8b
2 changed files with 17 additions and 15 deletions
|
|
@ -65,10 +65,6 @@ def _get_discount_settings() -> tuple[Decimal, Decimal]:
|
||||||
return _settings
|
return _settings
|
||||||
|
|
||||||
|
|
||||||
def _get_admin_emails() -> set[str]:
|
|
||||||
return {email.lower() for email in get_settings().get("admin_emails", [])}
|
|
||||||
|
|
||||||
|
|
||||||
def _google_auth_configured() -> bool:
|
def _google_auth_configured() -> bool:
|
||||||
return bool(os.environ.get("GOOGLE_CLIENT_ID_PARAM", ""))
|
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"
|
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]:
|
def _verify_admin(event) -> tuple[dict | None, dict | None]:
|
||||||
"""Verify Google auth and admin access. Returns (user_info, error_response)."""
|
"""Verify Google auth and admin access. Returns (user_info, error_response)."""
|
||||||
if not _google_auth_configured():
|
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)
|
user_info, status = _verify_google_token(token)
|
||||||
if status == "unavailable":
|
if status == "unavailable":
|
||||||
return None, _authentication_service_unavailable()
|
return None, response(
|
||||||
|
503, {"error": "Authentication service temporarily unavailable"}
|
||||||
|
)
|
||||||
if user_info is None:
|
if user_info is None:
|
||||||
return None, response(403, {"error": "Invalid or unauthorized Google account"})
|
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 None, response(403, {"error": "Admin access required"})
|
||||||
|
|
||||||
return user_info, None
|
return user_info, None
|
||||||
|
|
@ -427,15 +422,21 @@ def handle_submit(event):
|
||||||
client_id = _get_google_client_id()
|
client_id = _get_google_client_id()
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
logger.error("SSM fetch failed for Google client ID: %s", 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:
|
if not client_id:
|
||||||
logger.error("Google client ID is unavailable")
|
logger.error("Google client ID is unavailable")
|
||||||
return _authentication_service_unavailable()
|
return response(
|
||||||
|
503, {"error": "Authentication service temporarily unavailable"}
|
||||||
|
)
|
||||||
if not google_token:
|
if not google_token:
|
||||||
return response(403, {"error": "Google authentication is required"})
|
return response(403, {"error": "Google authentication is required"})
|
||||||
user_info, verify_status = _verify_google_token(google_token)
|
user_info, verify_status = _verify_google_token(google_token)
|
||||||
if verify_status == "unavailable":
|
if verify_status == "unavailable":
|
||||||
return _authentication_service_unavailable()
|
return response(
|
||||||
|
503, {"error": "Authentication service temporarily unavailable"}
|
||||||
|
)
|
||||||
if user_info is None:
|
if user_info is None:
|
||||||
return response(403, {"error": "Invalid or unauthorized Google account"})
|
return response(403, {"error": "Invalid or unauthorized Google account"})
|
||||||
name = user_info["name"]
|
name = user_info["name"]
|
||||||
|
|
@ -452,7 +453,8 @@ def handle_submit(event):
|
||||||
|
|
||||||
week = current_week()
|
week = current_week()
|
||||||
status = get_form_status(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:
|
if status == "closed" and not is_admin_user:
|
||||||
return response(410, {"error": "Orders are closed for this week"})
|
return response(410, {"error": "Orders are closed for this week"})
|
||||||
if status == "not_found":
|
if status == "not_found":
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ def main():
|
||||||
|
|
||||||
ssm = boto3.client("ssm")
|
ssm = boto3.client("ssm")
|
||||||
resp = ssm.get_parameter(Name="/meal-order-manager/google-client-id")
|
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:
|
except Exception as exc:
|
||||||
parser.error(
|
parser.error(
|
||||||
"Google auth is required in cloud mode, but the Google client ID "
|
"Google auth is required in cloud mode, but the Google client ID "
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue