For AI agents: the complete documentation index is at llms.txt. Markdown versions are available by appending .md or sending Accept: text/markdown.
Reflex Logo
Docs Logo
Changelog

/

Reflex Enterprise

reflex-enterprise Changelog

v0.9.4 (2026-08-14)

Breaking Changes

  • EventHandlerAPIPlugin now requires an app-issued bearer token on every request — the bare caller-supplied client_token (a UUID naming a session) is no longer accepted. This closes the session-takeover vector where a caller could name (or guess) another session's token: sessions are now server-generated and bound to a bearer the app issues, obtained from the anonymous token endpoint or the OAuth flow. State reads redact the session's server-side client_token/session_id from the returned router var so the session token never reaches the client. (#198)
  • EventHandlerAPIPlugin no longer exposes auth/framework event handlers (any OIDCAuthState provider, the page guard, route dispatchers, AuthUserState, and other reflex/reflex_enterprise states). Callers drive the app's own handlers and authenticate through the token endpoint or the OAuth flow rather than by queueing the login events directly. (#198)
  • OIDC cookie names now carry a _partitioned suffix so they do not collide with the unpartitioned cookies written by earlier versions. Sessions established before this upgrade are not recognized under the new names, so users sign in once more after it is deployed. (#206)

Features

  • New: reflex_enterprise.MCPPlugin — serve a Reflex app to AI agents over the Model Context Protocol. Adding the plugin mounts an MCP server that publishes the app's public event handlers as search_events / queue_event tools, a reflex:// resource family for reading the app (reflex://state, reflex://event[/{event_name}], reflex://state/events/{state_name}, and reflex://state/vars/{state_name}[/{var_name}] for the caller's live session state, computed vars recomputed), and auto-generated instructions covering the app's location, auth model, tool workflow and pages, so a client knows how to drive it on connect. configure= (a callable or a "module.function" path) hands you the underlying FastMCP server before it is mounted to register your own tools, resources and prompts — also reachable at runtime via reflex_enterprise.get_mcp_server(); expose_events=False publishes reads only, without the app's action surface; pending_updates= chooses "drop" (default) or "queue" (buffered for a get_pending_updates tool) for deltas from chained events and background tasks, which have no websocket to land on. Upload handlers cannot run inline, so queue_event returns out-of-band upload directions (URL, headers, form fields and a curl example) carrying a short-lived, single-use ticket bound to the one handler it was minted for. Requires the optional mcp extra (pip install reflex-enterprise[mcp]). (#198)
  • MCP OAuth: with an AuthPlugin configured, MCPPlugin makes the app a spec-compliant OAuth 2.1 Authorization Server + Resource Server for its MCP endpoint, federating the human login to the existing OIDC flow through a brandable consent page. Clients discover the flow (RFC 9728 / RFC 8414), register dynamically (RFC 7591), and receive the app's own opaque, resource-bound tokens — upstream identity-provider tokens never leave the server. Each token is bound to a dedicated session, so the full enforcement stack (per-event gate, callable auth= checks, delta filtering, AuthUserState.current()) applies to agent traffic unchanged. app_scopes={name: description} renders each scope as an individually grantable checkbox on the consent screen and the minted token carries only what was granted, readable in auth= callbacks via ctx.token_scopes. Tokens and consent live in Redis when the app is configured for it, otherwise in-process. On by default alongside an AuthPlugin; opt out with MCPPlugin(auth=False). In production the issuer must be served over https — a plain-http issuer (outside loopback dev hosts) is rejected at wiring time with a ConfigError, since the authorization server hands out bearer credentials on that origin. See the production/TLS section in docs/mcp.md. (#198)
  • The rxe.mcp.resource decorator tags a state method as a top-level MCP resource — a var-like, parameterized, read-only view of the caller's session state, served at state-resource://<state>/<method>[/{param}] with the method's parameters as URI-template variables. It is never an event handler, so it stays out of search_events / queue_event, and its auth= (True/False/a check(ctx) callable, the same contract as rxe.var) gates the read whenever an AuthPlugin provides identity. (#198)
  • Anonymous API sessions: MCPPlugin and EventHandlerAPIPlugin serve POST /_reflex/auth/token, returning an app-issued bearer bound to a fresh, server-generated session — the client never picks or sees the underlying client token. The endpoint is rate limited per client IP (token_rate_limit) so one origin cannot mint unbounded sessions. With an AuthPlugin an agent may stay anonymous (no user identity, so only auth=False surfaces are reachable) or complete the OAuth flow for an authenticated session. On by default; turn it off with anonymous_sessions=False on every API plugin you register, since the shared endpoint is served if either enables it. (#198)
  • Auth contexts (event/var/page) now carry ctx.surface ("browser" / "event_api" / "mcp") and ctx.token_scopes (the app-issued token's scopes, or None for a browser request), so auth= checks can restrict what a delegated agent may do independent of the underlying user's identity. (#198)
  • Per-token API rate limiting: every MCP/REST call is counted against the presenting session token (call_rate_limit / call_rate_window), with per-handler overrides via rxe.event(rate_limit=..., rate_limit_window=...) (rate_limit=0 exempts a handler). (#198)
  • Cross-origin iframe login: OIDC cookies are now set with SameSite=None and the Partitioned attribute (including on Python versions whose http.cookies cannot emit Partitioned itself), so an app can complete the login flow while embedded in an iframe whose outer page is on a different origin. Logging out from the inner frame now clears the session proactively instead of waiting for a postMessage from the popup -- that message was only ever caught by a listener bound to the login button, so it never arrived on a page that rendered no login button. (#206)
  • An app that does not configure the AuthPlugin no longer loads the auth system from its OIDC providers. The provider helpers that reach for plugin-owned things -- AuthUserState, the deauthentication app-state sweep, the audit emissions -- are wrapped in @requires_plugin(AuthPlugin) and do nothing when the plugin is absent, so the provider still clears its own cookies but never grafts AuthUserState onto a state tree the frontend compiled without it. Previously that state was loaded anyway and every update computed for it reached the client as a dispatch error on the frontend and backend consoles.
  • The guard is reusable by any plugin integration that must stay inert in apps that did not enable the plugin: reflex_enterprise.plugins.guards exposes requires_plugin(SomePlugin, default=...) as a decorator for sync and async helpers, plus has_plugin / configured_plugin for the underlying question. (#210)

Bug Fixes

  • Popup auth flows honor redirect_to_url again: it is saved before the flow is initiated, so the query parameter set on the iframed page survives, and the saved URL is what the success handler redirects to. (#206)
  • Fix a cross-site iframe losing a valid session to a cross-tab logout that never happened. An iframe's partitioned localStorage cannot see the token hash the login popup wrote at top level, so its empty report was read as proof that another tab had logged out -- and won that race whenever it arrived before the server-queued hash write. The reported hash is now a change ping rather than a verdict: any disagreement queues one cookie sync and the callback adopts whatever the cookie jar holds. Token material means record the session's hash, re-assert it into this partition's localStorage and refresh if due; an empty jar is a real logout and resets as before. (#207)
  • MessageListener no longer accumulates message listeners. Its effect cleanup removed a different function than the one it registered, so a listener leaked on every re-render and each popup message was then handled once per leaked listener. (#208)

v0.9.3 (2026-08-05)

Features

  • Auth: AuthPlugin(audit=...) — an observe-only audit hook called for every auth lifecycle action (login, logout, token refresh, session expiry) and every access decision (event gate, page guard). See the audit docs. (#200)
  • Auth: replay gate-blocked events after login — an action blocked by the event gate for an anonymous visitor (the click or form submit that triggered the login redirect) is preserved and replayed once the user authenticates and lands back on the same page, instead of being silently lost (#190)

Bug Fixes

  • OIDC: split authorization-callback failure outcomes — handle identity-provider error responses, restart the flow once when the sign-in session was lost, and reserve the "possible CSRF attack" warning for a genuine state mismatch; the callback is now also idempotent across websocket reconnects instead of re-firing against an already-exchanged code (#203)
  • OIDC: stop reporting expired ID tokens as backend errors — routine expiry during re-validation now logs at INFO without a traceback and no longer sets has_error; signature and other validation failures still log at ERROR (#202)

Miscellaneous

  • OIDC: add token-presence context (access_token/id_token/refresh_token booleans, never values) to forced-logout warnings so the cause is visible in production logs (#195)
  • OIDC: attribute forced logouts from the token-refresh paths in logs and downgrade the userinfo reset warning to debug for anonymous visitors, cutting log noise (#203)
  • Fix unawaited-coroutine RuntimeWarnings in the auth test suite (#192)

v0.9.2.post1 (2026-07-06)

Bug Fixes

  • Do not update AuthUserState when AuthPlugin is not registered (#196)
  • Serialize HTTPCookie.sync requests to avoid data race (#196)

v0.9.2 (2026-07-06)

Features

  • Add Highcharts chart component (#182)
  • Add reflex_app pytest plugin for downstream testability (#179)

Bug Fixes

  • Auth: redeliver protected vars on public pages (#186)

Performance

  • Auth: skip protected-var redelivery on same-user navigation (#187)

Miscellaneous

  • Add logging to silent auth failure/logout paths (#188)

v0.9.1 (2026-07-01)

Features

  • Add reflex_enterprise.AuthPlugin providing integrated secure-by-default auth primitives for protecting pages, fields, vars, and event handlers. See the full docs for usage.

v0.9.0 (2026-06-09)

Breaking Changes

  • Restrict reflex export and reflex run --env prod to paid tiers (#177)

v0.8.3 (2026-06-01)

Bug Fixes

  • Handle map layer event_handlers prop properly (#175)
  • OIDC: use self.__class__ instead of type(self) for handler lookups (#176)
  • Redo redirect_to_login when userinfo is unavailable (#174)

v0.8.2 (2026-05-19)

Features

  • InteractiveLeafletLayer and enhanced event handling for map components (#170)
  • postMessage-based token sync for iframed OIDC popup flows (#172)

Bug Fixes

  • OIDC: try refresh token before resetting auth on validation failure (#173)

Miscellaneous

  • Harden GitHub Actions workflows (#171)

v0.8.1 (2026-05-11)

Bug Fixes

  • Always set cls._has_registered_endpoints = True (#169)

v0.8.0 (2026-05-08)

Bug Fixes

  • HTTPCookie: remove BaseState patches and fix subclass var dependencies (#164)

Miscellaneous

  • Remove runtime version checks throughout the package (#168)

v0.7.3 (2026-05-01)

Features

  • Add valid issuers and related cleanup (#163)

Bug Fixes

  • Avoid race condition between updating the localStorage value and redirect (#167)
  • Fix backend path handling for HTTP cookies (#166)

v0.7.2 (2026-04-27)

Bug Fixes

  • messageListener.js: reference public_path in the wrapped component (#162)

v0.7.1.post2 (2026-04-27)

Miscellaneous

  • Remove the GitHub Packages upload step and attach the wheel to the GitHub Release instead

v0.7.1 (2026-04-24)

Features

  • Add event handlers as HTTP endpoints and expose them via the OpenAPI spec (#156)

Miscellaneous

  • Add license URL (#161)

v0.7.0.post1 (2026-04-21)

Bug Fixes

  • Fix importable path for Mantine (#160)

v0.7.0 (2026-04-20)

Bug Fixes

  • Reflex 0.9 compatibility: use importable_path for assets in 0.9.0+ (#159)
  • Additional Reflex 0.9 compatibility fixes (#157, #158)

v0.6.5 (2026-03-27)

Miscellaneous

  • Replace AWS CodeArtifact with GitHub Packages for the enterprise wheel (#154)
  • Remove rx.Base for 0.9 compatibility (#155)

v0.6.4 (2026-03-18)

Features

  • Expose display name (#152)

Miscellaneous

  • Improve token type validation (#153)

v0.6.3 (2026-03-16)

Miscellaneous

  • Raise with an error message (#151)

v0.6.2 (2026-03-10)

Bug Fixes

  • Redirect after logout consistently (#150)

v0.6.1 (2026-03-09)

Features

  • Add APIs for Reflex Enterprise to override UI (#149)

v0.6.0 (2026-03-03)

Performance

  • OIDC: reduce and centralize out-of-band events (#148)

v0.5.5 (2026-02-21)

Bug Fixes

  • Ignore refresh access token errors (#142)

Miscellaneous

  • OIDC: handle local storage updates internally (#147)

v0.5.4 (2026-02-19)

Bug Fixes

  • OIDC: reset auth for invalid tokens in userinfo (#146)

v0.5.3 (2026-02-19)

Features

  • OIDC: allow a pluggable _http_client implementation (#145)

v0.5.2.post1 (2026-02-18)

Bug Fixes

  • Also save redirect_to_url in sessionStorage (#144)

v0.5.2 (2026-02-18)

Miscellaneous

  • Store PKCE identifiers in sessionStorage (#143)

v0.5.1 (2026-02-17)

Bug Fixes

  • Redirect to login with an invalid token (#141)

v0.5.0 (2026-02-13)

Features

  • Implement refresh token in OIDCAuthState (#139)

Miscellaneous

  • Overhaul OIDC implementation for flexibility (#135)
  • Upgrade dependency pins (#140)

v0.4.3 (2026-01-22)

Bug Fixes

  • Fix issuer claim request to support multiple values (#137)

Miscellaneous

  • Exclude OIDC routes from /sitemap.xml (#134)

v0.4.2 (2026-01-07)

Features

  • Add HTTPCookie partitioned attribute (#129)
  • Allow cross-origin cookie sync when same_site="none" (#128)

Miscellaneous

  • Use Starlette cookie_parser instead of SimpleCookie (#133)
  • Do not validate cookie domain (#130)
  • Pre-commit fixes (#131)

v0.4.1 (2025-12-19)

Features

  • Allow passing arbitrary headers to HTTPCookie.sync (#127)

v0.4.0 (2025-12-17)

Features

  • Implement HTTP Cookie support (#119)
  • Add presets and other props for Mantine date components (#120)
  • Return the row count in Datasource and SSRMDatasource (#123)
  • Row grouping options include the RowGroupingModule (#122)
  • Apply default sort order by primary_key (#121)

Bug Fixes

  • args_names must be a tuple (#124)

Miscellaneous

  • Bump ag-grid to 34.3.1 (#125)
  • Add upload step to build job (#126)
Built with Reflex