Design: Fix Deconsolidated Login Page URL Issue

1 comments0 reviews

When users visit alpha.atoz.amazon.dev, they end up on atoz.integ.amazon.com after login. The root cause: the deconsolidated login page uses hardcoded absolute URLs (e.g., https://atoz-login.integ.amazon.com/login?loginType=AA) that break the X-ATOZ-SOURCE header mechanism needed for the domain migration.

LPT (Ruby)                    → CloudFormation Param          → StaticCopyCustomResource → S3 bundle
aa_authentication_controller_url()  → AaAuthenticationControllerUrl    → replaces {{...}} in built JS    → served to browser

In the React code, the placeholders look like:

// LoginForm.tsx — the main AA login form
const aaAuthenticationControllerUrl =
    (source === "ac") ? "{{AaAuthenticationControllerUrl}}" : "{{AaEsspUrl}}";
formRef.current!.action = aaAuthenticationControllerUrl;

// DeconsolidatedLoginScreenV2.tsx — the DA tile
href={"{{DaAuthenticationControllerUrl}}"}

// Other tiles
href={"{{PbAuthenticationControllerUrl}}"}
href={"{{SruAuthenticationControllerUrl}}"}

After deploy, these become actual URLs like https://atoz-login.integ.amazon.com/login?loginType=AA.


#Approach

Replace the {{*AuthenticationControllerUrl}} template values with relative paths (/login?loginType=XX) directly in the React components. Since the deconsolidated login page is already served from the Auth Controller's CloudFront distribution (same origin as /login), relative URLs naturally stay on whatever domain the user is currently on.

#Changes Required

AtoZIdentityAppWebsite/src/components/LoginForm.tsx:

// BEFORE:
const aaAuthenticationControllerUrl: string =
    (source === ParameterNames.REQUEST_SOURCE_AUTHENTICATION_CONTROLLER) ?
        "{{AaAuthenticationControllerUrl}}" : "{{AaEsspUrl}}";

// AFTER:
const aaAuthenticationControllerUrl: string =
    (source === ParameterNames.REQUEST_SOURCE_AUTHENTICATION_CONTROLLER) ?
        "/login?loginType=AA" : "{{AaEsspUrl}}";

AtoZIdentityAppWebsite/src/components/DeconsolidatedLoginScreenV2.tsx:

// BEFORE:
const newHref = (source === ParameterNames.REQUEST_SOURCE_AUTHENTICATION_CONTROLLER) ?
    "{{DaAuthenticationControllerUrl}}" : "{{DaEsspUrl}}";

// AFTER:
const newHref = (source === ParameterNames.REQUEST_SOURCE_AUTHENTICATION_CONTROLLER) ?
    "/login?loginType=DA" : "{{DaEsspUrl}}";

// BEFORE:
href={"{{PbAuthenticationControllerUrl}}"}
// AFTER:
href={"/login?loginType=PB"}

// BEFORE:
href={"{{SruAuthenticationControllerUrl}}"}
// AFTER:
href={"/login?loginType=SRU"}

Other components (CSGO region pages, Jobseeker, etc.) — same pattern: replace {{*AuthenticationControllerUrl}} with /login?loginType=XX.

#Pros

  • Simplest change — only React code, no LPT/CloudFormation changes needed
  • Works for all stages including future domains — relative URLs are domain-agnostic
  • No deploy ordering dependency — doesn't need LPT+CFN redeploy
  • Eliminates the entire class of bug — no more hardcoded domains to go stale
  • Works for personal dev stacks too (e.g., wzhongwe.atoz-apps-alpha.integ.amazon.com)

#Cons

  • ESSP URLs remain absolute — the {{AaEsspUrl}} (non-AC) path still uses absolute URLs, but those go to the portal domain which is a different CloudFront distribution, so relative wouldn't work for them
  • Requires understanding the source parameter logic — the source === "ac" branch is the only one that should use relative URLs (when the page is served from the AC distribution)
  • Won't fix the ESSP flow — if a user somehow lands on the deconsolidated page without ?source=ac, the ESSP URLs are still absolute (but this is a different flow and not broken by this bug)

#Risk Assessment

  • Low risk — relative URLs on the same origin is standard web behavior
  • The ?source=ac parameter guarantees the page is served from the AC distribution, so /login resolves correctly

#Approach

Change all *_authentication_controller_url methods in website_template.rb to emit new-domain URLs for pre-prod stages.

#Changes Required

AtoZIdentityAppLPT/lib/amazon/lpt/website_template.rb:

# BEFORE:
def aa_authentication_controller_url(options)
  if options.logical_stage.name.downcase == "beta"
    url = "https://atoz-login.integ.amazon.com/login?loginType=AA"
  elsif options.logical_stage.name.downcase == "gamma"
    url = "https://atoz-login-gamma.corp.amazon.com/login?loginType=AA"
  elsif options.logical_stage.name.downcase == "prod-na"
    url = "https://atoz-login.amazon.work/login?loginType=AA"
  end
  url
end

# AFTER:
def aa_authentication_controller_url(options)
  if options.logical_stage.name.downcase == "beta"
    url = "https://login.beta.atoz.amazon.dev/login?loginType=AA"
  elsif options.logical_stage.name.downcase == "gamma"
    url = "https://login.gamma.atoz.amazon.dev/login?loginType=AA"
  elsif options.logical_stage.name.downcase == "prod-na"
    url = "https://atoz-login.amazon.work/login?loginType=AA"
  end
  url
end

Repeat for ALL helper methods:

  • da_authentication_controller_url
  • dspa_authentication_controller_url
  • dsp_authentication_controller_url
  • csgo_authentication_controller_url_na
  • csgo_authentication_controller_url_eu
  • csgo_authentication_controller_url_fe
  • sru_authentication_controller_url
  • pb_authentication_controller_url
  • jobseeker_authentication_controller_url

#Pros

  • Doesn't modify React app code — keeps the existing template variable approach
  • Explicit and auditable — each stage's URL is clearly visible in one file

#Cons

  • Only fixes new-domain users — users who arrive via the legacy domain (atoz-login.integ.amazon.com) would get redirected to the new domain mid-flow, potentially breaking cookies
  • Requires LPT + CloudFormation deploy — change in LPT triggers a pipeline redeploy of the S3 bundle via CloudFormation
  • Hardcodes new domains — same category of problem (domain changes require LPT updates)
  • Many methods to update — 9+ helper methods, easy to miss one
  • Personal dev stacks break — personal stacks like wzhongwe.atoz-apps-alpha.integ.amazon.com don't have a corresponding login.wzhongwe.atoz.amazon.dev domain
  • Doesn't work for beta stage — beta LPT currently serves BOTH alpha and beta traffic (the same S3 bundle is deployed for both), so you can't have one URL that works for both login.alpha.atoz.amazon.dev and login.beta.atoz.amazon.dev from the same bundle

#Risk Assessment

  • Medium risk — the beta/alpha shared bundle problem makes this approach non-trivial
  • Would need a way to distinguish alpha vs beta at deploy time (currently beta stage in LPT covers both)

#Approach

Replace the template placeholders with dynamic URL construction using the browser's current origin.

#Changes Required

AtoZIdentityAppWebsite/src/components/LoginForm.tsx:

// BEFORE:
const aaAuthenticationControllerUrl: string =
    (source === ParameterNames.REQUEST_SOURCE_AUTHENTICATION_CONTROLLER) ?
        "{{AaAuthenticationControllerUrl}}" : "{{AaEsspUrl}}";

// AFTER:
const aaAuthenticationControllerUrl: string =
    (source === ParameterNames.REQUEST_SOURCE_AUTHENTICATION_CONTROLLER) ?
        `${window.location.origin}/login?loginType=AA` : "{{AaEsspUrl}}";

Same pattern for all other *AuthenticationControllerUrl usages.

#Pros

  • Domain-agnostic like Option A
  • Works for personal dev stacks — picks up whatever origin the page is on
  • Explicit about what's happening (constructs full absolute URL)

#Cons

  • Functionally identical to Option A but more verbose — window.location.origin + "/login?loginType=AA" is the same as just /login?loginType=AA for same-origin navigation
  • More code to write — template literal instead of simple string
  • SSR considerations — if this code ever runs server-side, window.location doesn't exist (not currently an issue since this is a static S3 app)
  • No real advantage over Option A — since the page is always same-origin with /login, relative is simpler

#Risk Assessment

  • Low risk — same as Option A, just more verbose

Option A is the clear winner:

  1. Fewest changes, lowest risk
  2. Eliminates the hardcoded-domain class of bugs entirely
  3. Works for all current and future domains
  4. Only modifies the React app (same VS, same pipeline, fast deploy)
  5. No LPT/CloudFormation deploy required — just a website bundle update

The key insight: when source === "ac", the page is ALWAYS served from the AC distribution. So /login is guaranteed to resolve to the correct Auth Controller endpoint on the same domain the user is already on.


  1. Identify all {{*AuthenticationControllerUrl}} usages in AtoZIdentityAppWebsite/src/
  2. Replace with relative paths only in the source === "ac" branches
  3. Keep ESSP URLs unchanged — those go to the portal distribution (different origin)
  4. Update tests — any test mocking these URLs needs updating
  5. Optionally clean up LPT/CFN — remove unused *AuthenticationControllerUrl parameters (separate follow-up CR to avoid risk)
  6. Deploy to alpha and verify the full login flow on alpha.atoz.amazon.dev

#Files to Modify

FileChange
AtoZIdentityAppWebsite/src/components/LoginForm.tsxReplace "{{AaAuthenticationControllerUrl}}" with "/login?loginType=AA"
AtoZIdentityAppWebsite/src/components/DeconsolidatedLoginScreenV2.tsxReplace DA, PB, SRU controller URLs with relative paths
Any CSGO region componentsReplace {{CsgoAuthenticationControllerUrl*}} with /login?loginType=CSGO&region_hint=XX
Any Jobseeker componentsReplace {{JobseekerAuthenticationControllerUrl}} with /login?loginType=JOBSEEKER
AtoZIdentityAppWebsite/src/components/__tests__/*Update test expectations
AtoZIdentityAppWebsite/configuration/webpack.config.jsCan remove the AC URL template entries (optional cleanup)

After deploying to alpha:

  1. Visit https://alpha.atoz.amazon.dev
  2. Get redirected to https://login.alpha.atoz.amazon.dev/login
  3. AC redirects to https://login.alpha.atoz.amazon.dev/?source=ac
  4. Click "Associate" / enter login / submit
  5. Verify: form submits to https://login.alpha.atoz.amazon.dev/login?loginType=AA (relative → same origin)
  6. Complete Federate auth
  7. Verify: land on https://alpha.atoz.amazon.dev/ (not atoz.integ.amazon.com)

Also verify DA, PB, SRU, CSGO tiles navigate to relative /login?loginType=XX paths.

1 comment

+1 more