Skip to content

bug: Session not cleared upon different logons https://track.akamai.c…#13359

Draft
mkaminsk-akamai wants to merge 3 commits intolinode:developfrom
mkaminsk-akamai:bug/compare-session-and-token
Draft

bug: Session not cleared upon different logons https://track.akamai.c…#13359
mkaminsk-akamai wants to merge 3 commits intolinode:developfrom
mkaminsk-akamai:bug/compare-session-and-token

Conversation

@mkaminsk-akamai
Copy link
Contributor

@mkaminsk-akamai mkaminsk-akamai commented Feb 3, 2026

…om/jira/browse/LILO-1461

Description 📝

Fixes a session/token mismatch edge case where the UI session (Flask cookie) and a token in localStorage can represent different users, leaving the app in a bad state. Verify that the auth token in localStorage belongs to the same user as the server-side Login session before proceeding with initial app requests; if they don’t match, clear localstorage and Login's 'session' cookie and redirect to logout to avoid incorrect token and session state. On app load time, the hook attempts to validate the stored token and Login's 'session' cookie against the login server (/oauth/verify). If the verify response reports a mismatch, the client clears stored auth and redirects to logout. Admin tokens skip the verify call. If verification fails due to network errors, the app falls back to making initial data requests.
This issue was reported on Slack: https://linode.slack.com/archives/CNC90RQMC/p1769601801504539.

Changes 🔄

List any change(s) relevant to the reviewer.

Added/modified files:
Updated: useInitialRequests.ts — add token/session verification, keep upload-pending behavior to avoid redirect during active image uploads, expose isLoading.
Added: useInitialRequests.test.ts — unit tests covering match/mismatch, network failure, and admin token behavior.
Updated: oauth.ts — small export re-export added (getLoginURL) required by the hook changes.

useInitialRequests now:

  • avoids redirect-to-login if there is a pendingUpload (same behavior retained),
  • performs a POST to ${getLoginURL()}/oauth/verify?client_id=${getClientId()} for non-admin tokens,
  • calls clearStorageAndRedirectToLogout() if verification returns match: false,
  • falls back to initial data load on fetch errors.
    verifyTokenMatchAndInit (internal function) encapsulates the above behaviour.

Scope 🚢

Upon production release, changes in this PR will be visible to:

  • All customers
  • Some customers (e.g. in Beta or Limited Availability)
  • No customers / Not applicable

Target release date 🗓️

Please specify a release date (and environment, if applicable) to guarantee timely review of this PR. If exact date is not known, please approximate and update it as needed.

TBD

Preview 📷

Screenshot 2026-02-13 at 3 25 39 PM

How to test 🧪

Prerequisites

No need to alter test environment configuration.

Reproduction steps

Demonstrate the issue:

Use current develop branch for Cloud Manager and sign in to Cloud Manager using Login link as UNRESTRICTED user A (complete normal login). The unrestricted user type is required as only for the unrestricted users the user's name is displayed in profile in Cloud Manager on right-top part of the screen.

Keep the same browser. Either: Wait until the server session cookie expires (12h), OR Manually alter value or expire the session cookie created for Login domain (ie. login.lindev.local) in the browser devtools.

Screenshot 2026-02-13 at 3 24 11 PM

In the same browser, navigate to Login page (ie. locally https://login.lindev.local/login) and sign in as user B (restricted or unrestricted).

After logon as user B you should be redirected to Cloud Manager page. You should see INCORRECTLY user's A user name displayed in profile in Cloud Manager on right-top part of the screen instead of user's B user name.

After applying fix

Sign in to Cloud Manager using Login as UNRESTRICTED user A (complete normal login). The unrestricted user type is required as only for the unrestricted users the user's name is displayed in profile in Cloud Manager on right-top part of the screen.

Keep the same browser. Either: Wait until the server session cookie expires (12h), OR Manually alter value or expire the session cookie created for Login domain (ie. login.lindev.local) in the browser devtools.

Screenshot 2026-02-13 at 3 24 11 PM

In the same browser, navigate to Login page (ie. locally https://login.lindev.local/login) and sign in as user B (restricted or unrestricted). This sets the server session cookie to user B. Do NOT clear or alter localStorage items for Cloud Manager.
At this point localStorage still contains the auth token from user A, while the session cookie represents user B.

After logon as user B you should be redirected to Cloud Manager page which should send POST request to ${getLoginURL()}/oauth/verify?client_id=... with the token extracted from localStorage and 'session' cookie from Login. You should see this request and it's response in devtools network tab.
If the Login endpoint /oauth/verify returns { match: false }, the Cloud Manager clears localStorage and triggers the logout flow which clears also Login's 'session' cookie.

Screenshot 2026-02-13 at 3 25 39 PM

If you log in now again (ie. locally https://login.lindev.local/login) using user B credentials you will be logged in as user B in Login and have user's B 'session' cookie and new token associated with user B. You should also see user's B user name displayed in profile in Cloud Manager on right-top part of the screen.

In other cases if there is no possibility to retrieve response from /oauth/verify endpoint (ie. CORS) or there is a pending image upload the Cloud Manager behavior is the same as previously.

Verification steps

(How to verify changes)

  • ...
  • ...
Author Checklists

As an Author, to speed up the review process, I considered 🤔

👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support


  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All tests and CI checks are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

@jdamore-linode
Copy link
Contributor

jdamore-linode commented Feb 3, 2026

Hey @mkaminsk-akamai I see this is a draft and I hope I'm not stepping on your toes, but I just pushed a quick addition to our E2E tests to ensure they can run with this change. Feel free to reach out if you have any questions or if we can help out with testing/test development for this change.

@mkaminsk-akamai mkaminsk-akamai force-pushed the bug/compare-session-and-token branch from f868c75 to 3c80f10 Compare February 12, 2026 15:23
@linode-gh-bot
Copy link
Collaborator

Cloud Manager UI test results

🔺 1 failing test on test run #4 ↗︎

❌ Failing✅ Passing↪️ Skipped🕐 Duration
1 Failing865 Passing11 Skipped42m 11s

Details

Failing Tests
SpecTest
clone-linode.spec.tsCloud Manager Cypress Tests→clone linode » can clone a Linode from Linode details page

Troubleshooting

Use this command to re-run the failing tests:

pnpm cy:run -s "cypress/e2e/core/linodes/clone-linode.spec.ts"

@mkaminsk-akamai mkaminsk-akamai force-pushed the bug/compare-session-and-token branch 5 times, most recently from 30e45d5 to 55caa8f Compare February 16, 2026 07:21
@mkaminsk-akamai mkaminsk-akamai force-pushed the bug/compare-session-and-token branch from 55caa8f to 34cdf00 Compare February 16, 2026 07:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Review

Development

Successfully merging this pull request may close these issues.

3 participants