Skip to content

security: gate Beatify admin behind Home Assistant login (#998)#1007

Open
mholzi wants to merge 2 commits into
mainfrom
security/998-admin-ha-login
Open

security: gate Beatify admin behind Home Assistant login (#998)#1007
mholzi wants to merge 2 commits into
mainfrom
security/998-admin-ha-login

Conversation

@mholzi
Copy link
Copy Markdown
Owner

@mholzi mholzi commented May 19, 2026

Admin/host control was reachable by anyone who could reach Home
Assistant. /beatify/admin even embedded the live admin token into the
page for any visitor. This makes every host action require a logged-in
HA user; players still join /beatify/play with no auth.

Server:

  • requires_auth=True on start-game, start-gameplay, end-game,
    rematch-game, force-reset, preview-lights, tts-test, lights, capabilities
  • AdminView no longer embeds the admin token (_inject_admin_token removed)
  • BeatifyAdminView gated by HA auth; retired the per-game admin_token check
  • WS admin_connect and is_admin joins validate an HA access token

Frontend:

  • new ha-auth.js: HA OAuth2 client (login redirect, refresh, authed fetch)
  • admin console requires HA login on load; player page only when the
    host role is claimed
  • admin/player/wizard/lights/tts calls carry the HA token

Pre-release for testing — the OAuth flow needs verification on a live
HA instance.

Co-Authored-By: Claude Opus 4.7 (1M context) [email protected]

Claude Code and others added 2 commits May 18, 2026 23:18
Admin/host control was reachable by anyone who could reach Home
Assistant. /beatify/admin even embedded the live admin token into the
page for any visitor. This makes every host action require a logged-in
HA user; players still join /beatify/play with no auth.

Server:
- requires_auth=True on start-game, start-gameplay, end-game,
  rematch-game, force-reset, preview-lights, tts-test, lights, capabilities
- AdminView no longer embeds the admin token (_inject_admin_token removed)
- BeatifyAdminView gated by HA auth; retired the per-game admin_token check
- WS admin_connect and is_admin joins validate an HA access token

Frontend:
- new ha-auth.js: HA OAuth2 client (login redirect, refresh, authed fetch)
- admin console requires HA login on load; player page only when the
  host role is claimed
- admin/player/wizard/lights/tts calls carry the HA token

Pre-release for testing — the OAuth flow needs verification on a live
HA instance.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…#998)

rc3 failed to load — server/stats_views.py still imported
_verify_admin_token from server/base.py, which was removed when the
per-game admin-token mechanism was retired. ImportError aborted the
whole integration setup.

StatsView (/beatify/api/stats) now uses requires_auth=True instead of
the old "admin token when a game is active" check (#386). No Beatify
page fetches this endpoint, so gating it breaks nothing.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements a significant security improvement by migrating from a per-game admin token system to native Home Assistant authentication. The changes include the introduction of a new OAuth2 client helper (ha-auth.js) to handle Home Assistant login flows, updating admin REST endpoints and WebSocket handlers to require valid Home Assistant access tokens, and removing the legacy admin token injection mechanism. I have reviewed the implementation and provided feedback on improving error logging in the authentication helper and simplifying the URL-encoded body construction in the frontend auth client.

Comment on lines +78 to +79
except Exception: # noqa: BLE001 — any decode/validation error means "no"
return False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While catching a broad Exception is a sound defensive strategy in this security context to ensure the function fails closed, swallowing the exception without logging can make debugging very difficult if an unexpected error occurs during token validation (e.g., due to a change in Home Assistant core). It would be beneficial to log the exception to aid in troubleshooting potential issues.

Suggested change
except Exception: # noqa: BLE001 — any decode/validation error means "no"
return False
except Exception as e: # noqa: BLE001 — any decode/validation error means "no"
_LOGGER.warning("HA token validation failed unexpectedly: %s", e)
return False

Comment on lines +109 to +113
var body = Object.keys(params)
.map(function (k) {
return encodeURIComponent(k) + '=' + encodeURIComponent(params[k]);
})
.join('&');
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The manual construction of the x-www-form-urlencoded body can be simplified by using the standard URLSearchParams API. This makes the code more concise and less prone to encoding errors.

    var body = new URLSearchParams(params).toString();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant