Skip to content

feat: add strictImpersonationPermissions setting for checkUserPermission - #200

Open
wender wants to merge 1 commit into
masterfrom
feature/B2BTEAM-3566_impersonation-permissions-toggle
Open

feat: add strictImpersonationPermissions setting for checkUserPermission#200
wender wants to merge 1 commit into
masterfrom
feature/B2BTEAM-3566_impersonation-permissions-toggle

Conversation

@wender

@wender wender commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

What problem is this solving?

In version 3.5.1, checkUserPermission started scoping permissions to the impersonated profile unconditionally. That prevents the acting user's permissions from reaching the storefront during impersonation, but it also removes permissions that the default B2B Suite configuration relies on:

  • can-checkout is granted to store-admin, sales-admin, sales-manager, sales-representative, customer-admin and customer-approver, but not to customer-buyer.
  • Aggregation is therefore what allows a sales representative impersonating an Organization Buyer to complete a purchase, a capability described for sales roles in docs/README.md.
  • With strict scoping always on, that checkout stops working.

Both behaviors are legitimate depending on the store: some need the storefront to render exactly what the impersonated user can do, others depend on the acting user's rights during impersonation (for example approval flows).

This also affects both impersonation flows, not only vtex.telemarketing. The B2B Organizations app switches the profile namespace through storefront-permissions.storeUserId, which vtex.profile-session takes as an input, so authentication.storeUserEmail and profile.email diverge in both flows.

What changed

The behavior is now controlled by a new app setting:

strictImpersonationPermissions Result during impersonation
true Only the impersonated profile's permissions and role (the 3.5.1 behavior).
false (default) Deduplicated union of the acting user's and the impersonated profile's permissions; role prefers the acting user's, falling back to the impersonated profile's (the 3.5.0 behavior).

Sessions outside impersonation are unchanged in both modes.

This restores the 3.5.0 default on purpose. Apps auto-update within a major, so keeping strict scoping on by default would continue to remove can-checkout in stores that did not opt into the change. Stores that want strict scoping enable the setting. Flipping the default to strict is a candidate for the next major, with a migration note.

Notes for reviewers:

  • The aggregated branch reproduces the pre-3.5.1 semantics exactly, including the role fallback order.
  • App settings are read only for impersonation sessions, through the existing 5-minute LRU cache (getCachedAppSettings), so regular sessions are not affected. A settings read failure logs a warning and falls back to the default (aggregated) mode.
  • UserPermissions { role, permissions } is unchanged, so there is no GraphQL schema change.
  • Documents the query's behavior during impersonation in docs/README.md, which was previously unspecified.

How should this be manually tested?

With the setting disabled (default):

  1. As a sales-representative, impersonate a customer-buyer through the B2B Organizations app.
  2. Confirm checkUserPermission returns the union of both sets, that can-checkout is present, and that checkout completes.

With strictImpersonationPermissions enabled in the app settings:

  1. Repeat the impersonation and confirm checkUserPermission returns only the buyer's role and permissions, with no permission coming from the sales representative.
  2. Repeat the check for a vtex.telemarketing session impersonating a customer.
  3. In both modes, confirm that a regular (non-impersonated) login is unaffected.

Screenshots or example usage:

N/A (backend resolver and app setting)

Ref: B2BTEAM-3566

3.5.1 made checkUserPermission scope permissions to the impersonated
profile unconditionally. That closes the permission leak reported for
Call Center sessions, but it also removes permissions that the default
B2B Suite configuration depends on: can-checkout is not granted to the
customer-buyer role, so a sales representative impersonating an
Organization Buyer could no longer complete checkout - a capability this
app's own docs describe for sales roles. The same need was raised for
approvers who must retain approval power while impersonating.

Both impersonation flows are affected, not only telemarketing: the
Organizations app switches the profile namespace through
storefront-permissions.storeUserId, which vtex.profile-session consumes,
so authentication.storeUserEmail and profile.email diverge in both.

Put the behavior behind a new app setting instead of picking one side:

- strictImpersonationPermissions=true returns only the impersonated
  profile's permissions (the 3.5.1 behavior).
- strictImpersonationPermissions=false (default) aggregates the acting
  user's and impersonated profile's permissions, restoring the 3.5.0
  behavior so existing stores keep working without any action.

Settings are only read for impersonation sessions, through the existing
5 minute LRU cache, so regular sessions are unaffected. Also document the
query's contract during impersonation, which was previously unspecified.

Ref: B2BTEAM-3566
@vtex-io-ci-cd

vtex-io-ci-cd Bot commented Aug 5, 2026

Copy link
Copy Markdown

Hi! I'm VTEX IO CI/CD Bot and I'll be helping you to publish your app! 🤖

Please select which version do you want to release:

  • Patch (backwards-compatible bug fixes)

  • Minor (backwards-compatible functionality)

  • Major (incompatible API changes)

And then you just need to merge your PR when you are ready! There is no need to create a release commit/tag.

  • No thanks, I would rather do it manually 😞

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.

2 participants