Skip to content

fix: forward auth token only via account-scoped cookie#3381

Merged
lemagnetic merged 3 commits into
devfrom
fix/my-account-auth-validation
Jun 16, 2026
Merged

fix: forward auth token only via account-scoped cookie#3381
lemagnetic merged 3 commits into
devfrom
fix/my-account-auth-validation

Conversation

@lemagnetic

@lemagnetic lemagnetic commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

What's the purpose of this pull request?

Logged-in shoppers were unable to access the FastStore My Account area: any navigation to /pvt/account/* resulted in an immediate redirect to /pvt/account/403?from=..., where the page entered an infinite refresh-token loop.

The root cause was on the API side. Every @auth-protected GraphQL query relies on vtexid.validate, and the request that backs that call was forwarding the auth token in two ways at once: once through the standard account-scoped cookie and again under a duplicated, top-level header. The duplicated header was being rejected by the platform with 401, even though the user's session was perfectly valid.

How it works?

This PR removes the duplication. The auth token is now forwarded exclusively through the account-scoped cookie (VtexIdclientAutCookie_{account}) — exactly like every other authenticated path in the codebase already does (see getAuthCookie, getJWTAutCookie, getIsRepresentative).

How to test it?

Pre-conditions: a logged-in shopper on a store that has FastStore My Account enabled (experimental.enableFaststoreMyAccount = true).

  • Navigate to /pvt/account/profile — should render the profile page directly, without redirecting to /pvt/account/403.

  • Run the package tests:

    pnpm --filter @faststore/api test

Starters Deploy Preview

Before

Gravacao.de.Tela.2026-05-05.as.19.26.38.mov

References

Summary by CodeRabbit

  • Bug Fixes

    • VTEX authentication token validation now derives the token from the merged/updated cookie set, with improved handling of duplicate auth cookie entries.
    • Updated VTEX request headers to use consistent cookie-based header construction (including forwarded host and content type) instead of the previous auth-cookie helper.
  • Tests

    • Added integration coverage for VTEX cookie normalization, including collapsing duplicate cookie keys and resolving the latest auth token value.
    • Added fallback behavior checks when storage-provided cookie updates are unavailable.

@lemagnetic lemagnetic requested a review from a team as a code owner June 5, 2026 18:54
@lemagnetic lemagnetic requested review from hellofanny and lucasfp13 and removed request for a team June 5, 2026 18:54
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: da15c848-116a-4f26-a3ce-a5efcc4aec87

📥 Commits

Reviewing files that changed from the base of the PR and between 6173834 and 55137ef.

📒 Files selected for processing (3)
  • packages/api/src/platforms/vtex/clients/commerce/index.ts
  • packages/api/src/platforms/vtex/utils/cookies.ts
  • packages/api/test/integration/vtex.cookies.test.ts
💤 Files with no reviewable changes (2)
  • packages/api/test/integration/vtex.cookies.test.ts
  • packages/api/src/platforms/vtex/utils/cookies.ts

Walkthrough

This PR refactors VTEX authentication cookie handling by removing header-based auth extraction and shifting to explicit cookie-forwarding. The credential validation now derives tokens from merged cookie sets, ensuring request body tokens align with storage updates, while authentication flows exclusively through the cookie header.

Changes

VTEX Auth Cookie Forwarding

Layer / File(s) Summary
Cookie utilities removal
packages/api/src/platforms/vtex/utils/cookies.ts
Removes getWithAutCookie function entirely, eliminating separate VtexIdclientAutCookie header extraction and consolidating authentication to the merged cookie header only.
Commerce client cookie-based token derivation
packages/api/src/platforms/vtex/clients/commerce/index.ts
Imports getAuthCookie and getUpdatedCookie, removes withAutCookie helper initialization, replaces multi-endpoint header construction from withAutCookie to withCookie with explicit headers, and extracts credential/validate token from merged cookies via getAuthCookie(getUpdatedCookie(ctx) ?? '', account) for the request body.
Auth cookie and token resolution tests
packages/api/test/integration/vtex.cookies.test.ts
Adds integration test suites for cookie normalization (duplicate key handling keeps last values while preserving first-seen order) and auth-token resolution ensuring storage-updated tokens are prioritized with fallback to original request tokens.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • vtex/faststore#3294: Identical refactoring—derives credential validation tokens from merged cookies and consolidates auth forwarding to the cookie header with matching test coverage.

Suggested labels

hotfix

Suggested reviewers

  • eduardoformiga
  • lucasfp13

🍪 Auth cookies now flow direct,
Through headers merged, no more select,
Storage updates find their way—
One true token leads the day! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: forward auth token only via account-scoped cookie' accurately describes the main change: removing token duplication and forwarding exclusively via account-scoped cookies to fix the 401 auth loop issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/my-account-auth-validation

Comment @coderabbitai help to get the list of available commands and usage tips.

@codesandbox-ci

codesandbox-ci Bot commented Jun 5, 2026

Copy link
Copy Markdown

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@coderabbitai coderabbitai Bot 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.

🧹 Nitpick comments (1)
packages/api/test/integration/vtex.cookies.test.ts (1)

104-165: 💤 Low value

Consider moving unit tests to a unit test location.

These tests verify individual utility functions in isolation (no network calls, no API integration). Per coding guidelines, @faststore/api should separate unit tests (*.test.ts) from integration tests (*.int.test.ts). This file is named *.test.ts but lives in test/integration/.

Either move to a unit test directory or rename to *.int.test.ts if the intent is to run with integration test suites.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/api/test/integration/vtex.cookies.test.ts` around lines 104 - 165,
Tests in test/integration cover a pure utility (getWithAutCookie) and should be
classified consistently: either move this file to the unit-test suite or mark it
as an integration test. Fix by either (A) relocating the file to the unit tests
folder and updating any import-relative paths so getWithAutCookie imports still
resolve, or (B) renaming the test file from *.test.ts to *.int.test.ts so the
integration runner picks it up; ensure the test name continues to reference
getWithAutCookie and that CI/test config (if any) does not require additional
changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/api/test/integration/vtex.cookies.test.ts`:
- Around line 104-165: Tests in test/integration cover a pure utility
(getWithAutCookie) and should be classified consistently: either move this file
to the unit-test suite or mark it as an integration test. Fix by either (A)
relocating the file to the unit tests folder and updating any import-relative
paths so getWithAutCookie imports still resolve, or (B) renaming the test file
from *.test.ts to *.int.test.ts so the integration runner picks it up; ensure
the test name continues to reference getWithAutCookie and that CI/test config
(if any) does not require additional changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4fef2328-3d26-4fb4-a1ab-e290d6e9c2c4

📥 Commits

Reviewing files that changed from the base of the PR and between 25a03d5 and 6173834.

📒 Files selected for processing (3)
  • packages/api/src/platforms/vtex/clients/commerce/index.ts
  • packages/api/src/platforms/vtex/utils/cookies.ts
  • packages/api/test/integration/vtex.cookies.test.ts

@renatomaurovtex renatomaurovtex 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.

Reviewed the auth-forwarding change. The root cause (duplicated token: account-scoped cookie + top-level VtexIdclientAutCookie header, with the platform 401-ing on the duplicate) is well explained, and the fix matches the established cookie-only pattern (getAuthCookie, getJWTAutCookie, getIsRepresentative). Tests are solid and the regression case for the unscoped header is a nice touch. A few things to confirm before merge.


🔴 [security] Auth path change — needs a human sign-off

This touches the authentication path (vtexid.validate backing the @auth directive). Per our review limits I won't solo-approve an auth change; flagging for a maintainer to confirm the platform contract (cookie-only forwarding for credential/validate) and to green-light the merge.


🟠 [bug] Blast radius is wider than the PR body — withAutCookie feeds ~10 other endpoints

getWithAutCookie previously attached VtexIdclientAutCookie to every caller, not just vtexid.validate. After this change none of these get it anymore:

  • profile.addressesprofile-system/pvt/profiles/{userId}/addresses
  • oms.userOrderoms/user/orders/{orderId}
  • oms.getCommercialAuthorizationsByOrderId / processOrderAuthorization
  • units.*units/v1/...
  • licenseManager.*license-manager/...

The PR description only validates the My Account /pvt/account/* flow. Did you verify these resolvers (especially license-manager and commercial-authorizations) still authenticate via the account-scoped cookie alone? Reassuringly, oms.listUserOrders already uses withCookie (no VtexIdclientAutCookie header) against the same OMS API, so the precedent looks right — but a quick confirmation (or a test step covering one B2B/orders path) would de-risk the wider change.


💬 [nit] _account param is now dead weight

withAutCookie(forwardedHost, _account?) keeps the param only for call-site compatibility. Fine to leave it, but since all 11 call sites are in this same file you could drop the second arg entirely and remove the account passthrough — slightly cleaner. Non-blocking, your call.


Verdict: Approved with comments

Blocking (🔴/🟠):

  • 🔴 Auth-path change — requires a maintainer sign-off (can't be auto-approved).
  • 🟠 Confirm the now-unscoped endpoints (license-manager, units, commercial-authorizations, profile, oms.userOrder) still authenticate via the account-scoped cookie. listUserOrders precedent suggests yes; a test step or note would close it out.

Non-blocking (🟡/💬):

  • 💬 Drop the unused _account param if you want the small cleanup.

Checks to confirm before merge: pnpm lint · build · pnpm --filter @faststore/api test

@hellofanny hellofanny 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.

  • pvt/account/profile ✅
Image
  • pvt/account/orders ✅
    Those seems to be working as expected.

But I not sure if pvt/account/security should also be working here. It returns 403. Do you know if It was pre-existing issue (I think probably was..)? Or licenseManager endpoint (ServerSecurity query calls userDetails → licenseManager.getUserRoles, which uses withAutCookie) may require the explicit VtexIdclientAutCookie header.

@eduardoformiga eduardoformiga left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please, take a look at this

* Headers for authenticated VtexID requests. The auth token is carried by
* the forwarded `cookie` header — not duplicated as a separate header.
*/
export const getWithAutCookie = (ctx: ContextForCookies) => {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this function no longer makes sense.
since getWithAutCookie didn't return the AutCookie (VtexIdclientAutCookie) anymore.

We can use instead, directly the:

 const headers: HeadersInit = withCookie({
    'content-type': 'application/json',
    'X-FORWARDED-HOST': forwardedHost,
  })

@pkg-pr-new

pkg-pr-new Bot commented Jun 15, 2026

Copy link
Copy Markdown

Open in StackBlitz

@faststore/api

npm i https://pkg.pr.new/vtex/faststore/@faststore/api@55137ef

@faststore/cli

npm i https://pkg.pr.new/vtex/faststore/@faststore/cli@55137ef

@faststore/components

npm i https://pkg.pr.new/vtex/faststore/@faststore/components@55137ef

@faststore/core

npm i https://pkg.pr.new/vtex/faststore/@faststore/core@55137ef

@faststore/diagnostics

npm i https://pkg.pr.new/vtex/faststore/@faststore/diagnostics@55137ef

@faststore/lighthouse

npm i https://pkg.pr.new/vtex/faststore/@faststore/lighthouse@55137ef

@faststore/sdk

npm i https://pkg.pr.new/vtex/faststore/@faststore/sdk@55137ef

@faststore/ui

npm i https://pkg.pr.new/vtex/faststore/@faststore/ui@55137ef

commit: 55137ef

@sonar-workflows

Copy link
Copy Markdown

@lemagnetic lemagnetic merged commit 37d6fcf into dev Jun 16, 2026
12 of 13 checks passed
@lemagnetic lemagnetic deleted the fix/my-account-auth-validation branch June 16, 2026 20:50
lemagnetic added a commit that referenced this pull request Jun 16, 2026
## What's the purpose of this pull request?

fix(api): use account-scoped cookie in orderEntry headers

The orderEntry methods (file upload via OES, #3334) still referenced the
withAutCookie helper that #3381 removed, since that PR was not rebased
on
the latest dev and did not see the newly merged orderEntry block. This
left an undefined withAutCookie reference, breaking the build and tests
on dev.

Replace the 5 withAutCookie(forwardedHost, account) calls with the
withCookie({ 'content-type', 'X-FORWARDED-HOST' }) pattern adopted by
#3381 

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved authentication/header handling for order entry endpoints to
ensure requests consistently include the correct `Content-Type` and
forwarded host information.
* Ensures file upload continues to use `multipart/form-data` with the
proper boundary while retaining the updated base header behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@eduardoformiga eduardoformiga mentioned this pull request Jun 17, 2026
2 tasks
eduardoformiga added a commit that referenced this pull request Jun 17, 2026
## Summary

Graduate the `4.3.0-dev.8` prerelease cycle to the stable `4.3.0`
release on `latest`.

Merging this PR triggers CD on `main`, which runs `lerna version
--conventional-graduate` and publishes all `@faststore/*` packages to
the `latest` dist-tag.

### Features
- Password Protection (v4) (#3276)
- File upload via Order Entry Service (OES) (#3334)
- Add sitemap to CMS Landing Page content-type (#3386)

### Bug Fixes
- **core:** use authenticator route for setpassword (#3380)
- migrate partytown `@builder.io` → `@qwik.dev@0.14.0` (#3394)
- **api:** use account-scoped cookie in orderEntry headers (#3395)
- forward auth token only via account-scoped cookie (#3381)
- **core:** propagate upstream error status instead of always 500
(#3379)

## Pre-flight (faststore-release skill)
- Working tree clean; `release.yml` has `fetch-depth: 0`
- All 8 packages have `repository.url`
- No breaking changes since `v4.2.0`
- `dev → main` merges cleanly (no CHANGELOG/codegen conflicts)
- No unmerged hotfixes on `main` (accidental `4.2.1` was fully reverted
in #3375)

## Test plan
- [ ] CI green on this PR
- [ ] After merge, confirm CD publishes all 8 packages at `4.3.0` under
`latest`

Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Matheus P. Silva <cout.matheusps@gmail.com>
Co-authored-by: vtexgithubbot <vtexgithubbot@github.com>
Co-authored-by: Lucas Feijó <lucas.portela@vtex.com>
Co-authored-by: Luiz Falcão <39093175+llfalcao@users.noreply.github.com>
Co-authored-by: Artur Santiago <artur.santiago@cubos.io>
Co-authored-by: Larícia Mota <laricia.mota@vtex.com.br>
Co-authored-by: Sahan Jayawardana <sahan@clouda.io>
Co-authored-by: Mateus Pontes <mateuspo10@gmail.com>
Co-authored-by: Matheus Martins <mathews_2010@outlook.com>
Co-authored-by: renatomaurovtex <167437775+renatomaurovtex@users.noreply.github.com>
Co-authored-by: Leandro Rodrigues <leandro.rodrigues@vtex.com>
Co-authored-by: Fanny Chien <fanny.chien@vtex.com>
Co-authored-by: Arthur Andrade <arthurfelandrade@gmail.com>
Co-authored-by: Leandro Rodrigues <leandro.swf@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Thiago Pereira <thiago.pereira@vtex.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Giuliana Rigaud <62848434+giurigaud@users.noreply.github.com>
Co-authored-by: renato <renato.neto@cubos.io>
Co-authored-by: Bruna Santos <brunassdev@gmail.com>
Co-authored-by: BrunaCubos <104789782+BrunaCubos@users.noreply.github.com>
Co-authored-by: Ícaro Oliveira <icarovinici@gmail.com>
Co-authored-by: Bruna Santos <bruna.santos@cubos.io>
Co-authored-by: Everton Ataide <everton.ataide@vtex.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Otavio Moreira Meirelles <otavio.meirelles@vtex.com>
Co-authored-by: Marco Cardoso <marcopaulo@outlook.com>
Co-authored-by: Gabriel Paladino <gabpaladino@users.noreply.github.com>
Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
Co-authored-by: dk-portal[bot] <134092483+dk-portal[bot]@users.noreply.github.com>
Co-authored-by: Rodrigo Tavares <rodrigo.tavares@vtex.com>
Co-authored-by: vitorflg <vitor.gomes@vtex.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Válber Laux <valber.laux@vtex.com>
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