Skip to content

ERA-13429 Collapse EarthRanger Web's flow selection to two-way - #1689

Merged
StephenWithPH merged 6 commits into
developfrom
ERA-13429
Oct 1, 2026
Merged

StephenWithPH merged 6 commits into
developfrom
ERA-13429

Conversation

@StephenWithPH

@StephenWithPH StephenWithPH commented Aug 5, 2026 •

Copy link
Copy Markdown
Contributor

What this does

Collapses EarthRanger Web's three-way flow selection to two-way. EarthRanger has moved away from Auth0 Organizations, so no site sets idp_org_id and the org-scoped branch is dead code and routing reduces to common-DB Auth0 vs. legacy ROPC.

Flow selection still keys on feature_flags.require_idp from /api/v1.0/status. Replacing that with RFC 9728 discovery is deliberately not here — it is ERA-13805, stacked on this branch, and it carries a different release gate. Splitting them means this half does not have to wait on the server and ingress work that one needs.

Changes

Area Change
Login/index.js One Auth0 branch. The "Sign in with email" button and the EarthRanger Identity info box now render on every Auth0 site, not only org-less ones. The managed-user button loses its org-scoped exclusion too, and its redirect sends the site connection without an organization. access_denied always shows the generic alert; the org-membership one is gone.
Auth0TokenManager/index.js The post-PKCE account-linking gate applies to every Auth0 site; it previously skipped org-scoped ones.
hooks/useAuthRecovery.js MFA step-up no longer sends organization. The hook no longer reads Redux at all.
ducks/system-config Stops storing idp_org_id. The status response still carries the field, null on every site since ERA-13666, so Web drops it on ingest rather than passing it through.
utils/auth0.js, locales buildAuth0AuthorizationParams drops its idp_org_id param and keeps only the connection the managed-user path needs. The loginButtonIdp and accessDeniedNotAuthorized strings go from all six locale files, with I18N_FILES_VERSION bumped to 1.77.

User-visible impact — not transparent, by design

On a formerly org-scoped site, users see the migration info box and the "Sign in with email" label instead of "Sign in". More significantly, their first Auth0 return now passes through the account-linking gate, so an account that has not been converted is handed to the server account linker rather than straight through. That is the intended Phase 3 end state. Where the site supports managed users, a formerly org-scoped site now offers the managed-user button too.

The legacy ROPC path (require_idp = false) is untouched.

ERA-13666 is done

ERA-13666 cleared idp_org_id on the last site that set it, so no site is org-scoped and this PR no longer waits on anything. develop already sends no organization anywhere; this PR removes the code that could.

Auth0 now enforces the same end state: since 2026-09-29 the Web SPA is at organization_usage = "deny" in auth0-platform-management, so a login carrying an organization would be rejected outright. That also makes Auth0's org-membership error unreachable, which is why its alert goes too.

Testing

Full suite green: 5537 tests / 409 suites. Written test-first, one behaviour per commit; each commit passes on its own.

Three test files deliberately keep idp_org_id: 'org_abc' in their fixtures — in system-config, Auth0TokenManager and Login. The status response still carries that field, so "Web ignores a server-supplied organization ID" is a live behaviour worth pinning, not a leftover.

Commits

Each is a red test → implementation → refactor cycle.

  1. Collapse the login page's org branch to a single Auth0 path
  2. Apply the account-linking gate to every Auth0 site
  3. Drop the organization param from MFA step-up
  4. Stop storing idp_org_id in system config
  5. Remove what the org-branch collapse orphaned
  6. Describe Auth0 sign-in without the organization path (AGENTS.md)

Copilot AI left a comment

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.

Pull request overview

This PR simplifies EarthRanger Web’s authentication flow selection by removing the now-dead Auth0-Organizations (org-scoped) branch and standardizing behavior across all Auth0 (require_idp=true) sites. It ensures Auth0 login and post-callback handling no longer depend on idp_org_id, while keeping legacy ROPC (require_idp=false) untouched.

Changes:

  • Remove idp_org_id-driven branching: Auth0 login always uses { audience } authorization params, and MFA step-up no longer sends an organization.
  • Apply the post-PKCE account-linking gate consistently on all Auth0 sites.
  • Stop storing idp_org_id in system config state and remove the now-unused Auth0 param builder + locale string.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/utils/auth0.js Removes buildAuth0AuthorizationParams; keeps only callback param detection.
src/utils/auth0.test.js Drops tests for the removed authorization param builder.
src/utils/auth.test.js Updates system-config-loaded fixture to no longer include idp_org_id.
src/Login/index.js Collapses Auth0 UI/behavior to a single path; always uses audience-only params and always shows the info box when require_idp.
src/Login/index.test.js Updates expectations for button label, absence of organization param, and info box rendering on all Auth0 sites.
src/hooks/useAuthRecovery.js Removes Redux dependency and ensures MFA step-up uses audience-only params (plus acr_values/max_age).
src/hooks/useAuthRecovery.test.js Updates assertions to match the new step-up authorization params.
src/ducks/system-config/index.js Stops persisting idp_org_id into Redux system config state.
src/ducks/system-config/index.test.js Pins “ignore server-supplied idp_org_id” behavior by ensuring it isn’t stored.
src/Auth0TokenManager/index.js Removes org-scoped bypass; runs account-linking gate for all require_idp sites.
src/Auth0TokenManager/index.test.js Updates gating tests to reflect “gate always runs” behavior.
src/Auth0TokenManager/accountLinkingGate.integration.test.js Updates integration fixture to no longer depend on idp_org_id.
public/locales/en-US/login.json Removes loginButtonIdp string (no longer referenced).
public/locales/es/login.json Removes loginButtonIdp string (no longer referenced).
public/locales/fr/login.json Removes loginButtonIdp string (no longer referenced).
public/locales/ne-NP/login.json Removes loginButtonIdp string (no longer referenced).
public/locales/pt/login.json Removes loginButtonIdp string (no longer referenced).
public/locales/sw/login.json Removes loginButtonIdp string (no longer referenced).

@github-actions

github-actions Bot commented Aug 5, 2026 •

Copy link
Copy Markdown

🚀 PR Environment Deployed

App Sync Health Image
pr-web-era-13429 ✅ Synced ✅ Healthy 5f66650799c9dda07b2e47b3a17f9ad26c36f3f1

Access: https://era-13429.dev.pamdas.org

View in ArgoCD

@github-actions

Copy link
Copy Markdown

⚠️ This PR environment has been inactive for 14 days.
Environment will be torn down in 3 days.

To keep the environment alive:

  • Remove the stale-environment label, OR
  • Add the keep-alive label for permanent exemption

@github-actions

Copy link
Copy Markdown

🗑️ Environment torn down due to inactivity

StephenWithPH and others added 4 commits October 1, 2026 12:41
EarthRanger has moved away from Auth0 Organizations, so no site sets
idp_org_id and the org-scoped render branch is dead. The login page now
shows one Auth0 path -- "Sign in with email" plus the migration info box --
and sends only the audience, ignoring an idp_org_id the status response
still reports until ERA-13666 clears it.

The managed-user button loses its org-scoped exclusion for the same reason,
and its redirect carries the site connection without an organization.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The gate previously ran only on the common-DB path, skipping org-scoped
sites. With the org branch gone, every Auth0 return goes through it, so
users on formerly org-scoped sites with an unconverted account are handed
to the server link page rather than straight through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Step-up now re-runs PKCE against the common DB like any other login, so the
hook no longer reads systemConfig at all. buildAuth0AuthorizationParams is
left with no callers and goes next.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nothing reads it now that routing is two-way. The status response keeps
sending the field until ERA-13666 clears it, so the payload drops it rather
than passing it through.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@StephenWithPH
StephenWithPH force-pushed the ERA-13429 branch 2 times, most recently from f04cf54 to a514555 Compare October 1, 2026 20:17
StephenWithPH and others added 2 commits October 1, 2026 13:37
buildAuth0AuthorizationParams lost its last organization caller when
step-up stopped sending one, so it drops the idp_org_id param and keeps only
the connection the managed-user path needs. The loginButtonIdp label died
with the org render branch. No behavior change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Every Auth0 site now signs in through EarthRanger Identity, so the
organization's-identity-provider route AGENTS.md still described is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

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.

Copilot review overview

🟢 Approval recommended

The reviewed changes have no unresolved blocking issues.

Review effort: Lite
Findings: None

@StephenWithPH
StephenWithPH marked this pull request as ready for review October 1, 2026 21:02

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@StephenWithPH
StephenWithPH requested a review from luixlive October 1, 2026 21:02
@chrisj-er
chrisj-er self-requested a review October 1, 2026 21:34

@luixlive luixlive left a comment

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.

Changes look good to me ✅

Claude found some minor issue, probably worth validating them. None of them seems like a blocker to me.

  1. MFA step-up drops the managed-user connection — src/hooks/useAuthRecovery.js:25
    When a managed user hits an MFA step-up, the re-login redirect doesn't send the site connection. They sign in against the default directory instead, which is what Login/index.js:62 warns about. This bug was already there before the PR, but the PR rewrites this exact params object, so this is the place to decide whether step-up should carry the connection.

  2. No regression test for the access_denied change — src/Login/index.test.js:952
    The org-membership alert test was deleted rather than turned around. The only access_denied test left would also pass on the old code. Add a case with error_description=user+is+not+part+of+the+org that expects the generic "Access denied" alert.

  3. Dead guard and needless effect dependency — src/Auth0TokenManager/index.js:130
    The guard if (!requireIdp || !isAuthenticated || existingToken) return; is the last statement in the function, so it does nothing. The existingToken selector (line 28) and its effect dependency (line 135) exist only for this guard, and they re-run the effect every time the token changes. Remove all three. The PR already edits that dependency list.

  4. buildAuth0AuthorizationParams is left half-used — src/utils/auth0.js:8
    It now has a single caller, the managed-user login, where siteSlug is always already trimmed and non-empty, so its trimming and empty check never matter. The other three Auth0 calls build { audience } inline. Either inline it and delete the helper and its 4 tests, or use it in all four places.

  5. Rewritten JSX comment breaks the comment rules — src/Login/index.js:209
    It's a three-line {/* */} block that mostly describes what the code does. Cut it, or reduce it to one line giving the reason.

@StephenWithPH
StephenWithPH merged commit 6c9f225 into develop Oct 1, 2026
9 checks passed
@StephenWithPH
StephenWithPH deleted the ERA-13429 branch October 1, 2026 21:44
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.

4 participants