Feature/global redash login logout - #75
Merged
Merged
Conversation
Separate admin user for global redash. env.py imports redash_global.models so migrations pick up the table, keeping the main app decoupled from redash_global.
Registered via app.cli.add_command in create_global_app, so `FLASK_APP=redash_global.app:create_global_app flask create_global_admin` works.
Gate the Redash Global admin SPA behind a login page so only authenticated global admins can reach it. - Add a /login page and POST handler that verifies GlobalAdminUser credentials and starts a flask_login session; wrap the SPA index in @login_required so unauthenticated visitors are redirected there. - Configure a dedicated GLOBAL_SECRET_KEY for signing the session cookie, and fail fast at startup if it's unset — this keeps global sessions cryptographically independent from the main Redash app so a leaked key in one app can't forge sessions in the other. - Use a separate session cookie name (global_admin_session) so the two apps' cookies don't collide when served from the same host. - Enable CSRF protection on the global app and include a csrf_token in the login form to protect the credential POST. - Register a Jinja ChoiceLoader that prefers Redash Global's own templates but falls back to Redash's, so login.html can extend the shared signed_out.html layout and reuse existing styling. - Add tests covering the redirect-when-unauthenticated, valid-login, and invalid-login flows. The shared test process forces us to mute the user_logged_in signal, since the main app's handler expects an org_id that GlobalAdminUser doesn't have.
Let an authenticated global admin end their session and return to the login page. - Add a POST-only /logout handler wrapped in @login_required that calls logout_user() to clear the flask_login session and redirects back to /login. - Keep it POST-only rather than GET so CSRF protection applies to it: a GET logout could be triggered by a prefetched link or embedded <img>, letting a third-party page silently sign the admin out. - Add a test that logs in, POSTs /logout, and confirms / gates back to /login — proving the session was actually cleared, not just that the endpoint returns a redirect.
Wires the bare "Work in progress" global app into Redash's existing application chrome and fixes logout end to end. - Render ApplicationLayout + Router with a placeholder home route, reusing the main app's chrome instead of reinventing it. - Register GlobalDesktopNavbar as "ApplicationDesktopNavbar"; the default navbar needs an org-scoped currentUser that Redash Global doesn't have. - Add main.less + ant.less to the global_app webpack entry, without them the navbar's Ant Design Menu had no styles and the layout was unpositioned. - Pass baseHref + staticPath to global.html so the Router can resolve routes and favicons load. - Change /logout from POST to GET to match main Redash and the navbar's <a href>, which was returning Method Not Allowed.
Accessing a protected page while logged out redirected to the login page but flashed "Please log in to access this page." as an error. For an admin app the redirect alone is enough signal, and the message read as an error the user had done something wrong rather than a routine auth gate.
thiagogds
approved these changes
Jul 15, 2026
helenalebreton
approved these changes
Jul 15, 2026
berinhard
reviewed
Jul 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes https://github.com/metr-systems/backlog/issues/4784
Closes https://github.com/metr-systems/backlog/issues/4761
Closes https://github.com/metr-systems/backlog/issues/4760
AI Disclaimer: Yes claude opus , to plan and assist
Summary
Global Redash already existed. This PR adds authentication and admin management to it:
create_global_adminandupdate_global_admin_password( the readme for how to run these commands ).Code Strategy
GlobalAdminUsermodel that is not org scoped.GLOBAL_SECRET_KEY(app won't start without it) and also a separate cookie name.main.less/ant.lessto the existing global_app webpack entry so the navbar renders styled, and setbaseHref/staticPathon its HTML template for routing and favicons.Security
Baseline protections are in place: separate sessions, a dedicated secret key, CSRF on the login POST, and login rate limiting (a dedicated Limiter pointed at the same Redis as main Redash, defaulting to 10/hour, configurable via
GLOBAL_THROTTLE_LOGIN_PATTERN).A follow-up PR will do more security hardening: bringing Redash Global up to main Redash's level and probably beyond. check issue
QA
How did you test it? Keep your future self in mind to help debug things later.