Explains which VTEX IO token (authToken, storeUserAuthToken, adminUserAuthToken) to use based on request context—storefront, admin, or app-level integration—and how to avoid hardcoded credentials.
Best for: VTEX developers integrating with VTEX IO endpoints from backend code.
---
name: vtex-io-auth-tokens-and-context
description: "Apply when choosing which VTEX IO authentication token should back a request from a backend app. Covers `ctx.authToken`, `ctx.storeUserAuthToken`, `ctx.adminUserAuthToken`, `authMethod`, and how requester context should determine the identity used by VTEX clients. Use for deciding which identity talks to VTEX endpoints in storefront-backed requests, Admin actions, or app-level integrations that should avoid hardcoded VTEX credentials."
---
# Auth Tokens & Request Context
## When this skill applies
Use this skill when the main decision is which VTEX IO identity should authenticate a backend request to VTEX services.
- Choosing between `ctx.authToken`, `ctx.storeUserAuthToken`, and `ctx.adminUserAuthToken`
- Deciding whether a VTEX client call should use `AUTH_TOKEN`, `STORE_TOKEN`, or `ADMIN_TOKEN`
- Reviewing storefront and Admin integrations that should respect the current user identity
- Replacing hardcoded `appKey` and `appToken` usage inside a VTEX IO app
Do not use this skill for:
- deciding which policies belong in `manifest.json`
- modeling route-level authorization or resource-based policies
- choosing between `ExternalClient`, `JanusClient`, and other client abstractions
- browser-side login or session UX flows
- validating route input or deciding what data may cross the app boundary
## Decision rules
- Use this skill to decide which identity talks to VTEX endpoints, not what that identity is authorized to do.
- Use `AUTH_TOKEN` with `ctx.authToken` only for app-level operations that are not tied to a current shopper or Admin user.
- Use `STORE_TOKEN` with `ctx.storeUserAuthToken` whenever the action comes from storefront browsing or a shopper-triggered flow and the integration should respect shopper permissions.
- Use `ADMIN_TOKEN` with `ctx.adminUserAuthToken` whenever the action comes from an Admin interface and the integration should respect the logged-in Admin user's License Manager permissions.
- Prefer user tokens whenever they are available. The official guidance is to avoid app-token authentication when a store or Admin user token can represent the requester more accurately.
- If the corresponding user token is not present, fall back to `AUTH_TOKEN` only when the operation is truly app-scoped and does not depend on a current shopper or Admin identity.
- When using VTEX IO clients that accept `authMethod`, pass the token choice explicitly when the default app identity is not the right one for the request.
- When wrapping custom VTEX clients, propagate the matching auth token from `IOContext` at the client boundary instead of hardcoding credentials in handlers.
- Keep token choice aligned with the user journey: storefront flows should not silently escalate to app-level permissions, and Admin flows should not bypass the current Admin role context.
- `ADMIN_TOKEN` with `ctx.adminUserAuthToken` must remain server-side only and must never be exposed or proxied to browser clients.
- Treat token choice and policy design as separate concerns: this skill decides which identity is making the call, while auth-and-policies decides what that identity is allowed to do.
- Do not use `appKey` and `appToken` inside a VTEX IO app unless there is a documented exception outside the normal VTEX IO auth-token model.
- Never log raw tokens or return them in responses. Tokens are request secrets, and downstream callers should receive only business data.
Token selection at a glance:
| Token | Context field | Use when | Avoid when |
|---|---|---|---|
| `AUTH_TOKEN` | `ctx.authToken` | app-level jobs, service-to-service work, or operations not linked to a current user | a shopper or Admin user is already driving the action |
| `STORE_TOKEN` | `ctx.storeUserAuthToken` | storefront and shopper-triggered operations | backend jobs or Admin-only operations |
| `ADMIN_TOKEN` | `ctx.adminUserAuthToken` | Admin requests that must respect the current user's LM role | storefront flows or background app tasks |
## Hard constraints
### Constraint: User-driven requests must prefer user tokens over the app token
If a request is initiated by a current shopper or Admin user, the VTEX integration MUST use the corresponding user token instead of defaulting to the app token.
**Why this matters**
Using the app token for user-driven work widens permissions unnecessarily and disconnects the request from the real user context that should govern access.
**Detection**
If the code runs in a storefront or Admin request path and still uses `ctx.authToken` or implicit app-token behavior, STOP and verify whether `ctx.storeUserAuthToken` or `ctx.adminUserAuthToken` should be used instead.
**Correct**
```typescript
export class OmsClient extends JanusClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super(ctx, {
...options,
headers: {
...options?.headers,
VtexIdclientAutCookie: ctx.storeUserAuthToken,
},
})
}
}
```
**Wrong**
```typescript
export class OmsClient extends JanusClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super(ctx, {
...options,
headers: {
...options?.headers,
VtexIdclientAutCookie: ctx.authToken,
},
})
}
}
```
### Constraint: App tokens must be reserved for app-level operations that are not tied to a user
Use `ctx.authToken` only when the request is genuinely app-scoped and no current shopper or Admin identity should govern the action.
**Why this matters**
The app token carries the permissions declared in the app manifest. Using it for user-triggered actions can bypass the narrower shopper or Admin permission model that the platform expects.
**Detection**
If a request originates from an Admin page, storefront interaction, or another user-facing workflow, STOP before using `ctx.authToken` and confirm that the action is truly app-level rather than user-scoped.
**Correct**
```typescript
export class RatesAndBenefitsClient extends JanusClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super(ctx, {
...options,
headers: {
...options?.headers,
VtexIdclientAutCookie: ctx.authToken,
},
})
}
}
```
**Wrong**
```typescript
export class AdminOrdersClient extends JanusClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super(ctx, {
...options,
headers: {
...options?.headers,
VtexIdclientAutCookie: ctx.authToken,
},
})
}
}
```
This is wrong when the client is used from an Admin flow that should respect the logged-in user's role.
### Constraint: VTEX IO apps must not hardcode VTEX API credentials when auth tokens are available
A VTEX IO app MUST use tokens from `IOContext` or `authMethod` instead of embedding `appKey`, `appToken`, or static VTEX credentials in source code or routine runtime configuration.
**Why this matters**
Hardcoded VTEX credentials are harder to rotate, easier to leak, and bypass the request-context model that VTEX IO clients already support.
**Detection**
If you see `X-VTEX-API-AppKey`, `X-VTEX-API-AppToken`, raw VTEX API credentials, or environment variables carrying permanent VTEX credentials inside a normal IO app integration, STOP and replace them with the correct auth-token flow unless there is a documented exception.
**Correct**
```typescript
await ctx.clients.catalog.getSkuById(id, {
authMethod: 'ADMIN_TOKEN',
})
```
**Wrong**
```typescript
await fetch(`https://${ctx.vtex.account}.myvtex.com/api/catalog/pvt/stockkeepingunit/${id}`, {
headers: {
'X-VTEX-API-AppKey': process.env.VTEX_APP_KEY!,
'X-VTEX-API-AppToken': process.env.VTEX_APP_TOKEN!,
},
})
```
## Preferred pattern
Start from the requester context, choose the token identity that matches that requester, and keep the token propagation inside the client layer.
Minimal selection guide:
```text
storefront request -> STORE_TOKEN / ctx.storeUserAuthToken
admin request -> ADMIN_TOKEN / ctx.adminUserAuthToken
background app work -> AUTH_TOKEN / ctx.authToken
```
Pass the token explicitly when the client supports `authMethod`:
```typescript
await ctx.clients.orders.listOrders({
authMethod: 'ADMIN_TOKEN',
})
```
```typescript
await ctx.clients.orders.listOrders({
authMethod: 'STORE_TOKEN',
})
```
Or inject the matching token in a custom VTEX client:
```typescript
import type { IOContext, InstanceOptions } from '@vtex/api'
import { JanusClient } from '@vtex/api'
export class OmsClient extends JanusClient {
constructor(ctx: IOContext, options?: InstanceOptions) {
super(ctx, {
...options,
headers: {
...options?.headers,
VtexIdclientAutCookie: ctx.adminUserAuthToken,
},
})
}
}
```
Keep the decision close to the request boundary, then let downstream handlers and services depend on the correctly configured client rather than choosing tokens ad hoc in many places.
## Common failure modes
- Defaulting every VTEX request to `ctx.authToken`, even when a shopper or Admin user initiated the action.
- Using `ctx.authToken` in Admin pages and accidentally bypassing the current Admin user's License Manager role context.
- Using `ctx.authToken` in storefront flows that should be limited by shopper permissions.
- Hardcoding `appKey` and `appToken` in an IO app instead of using auth tokens from `IOContext`.
- Choosing the right token in one client method but forgetting to apply the same identity consistently across related calls.
- Mixing token choice with policy modeling and treating them as the same decision.
- Logging `ctx.authToken`, `ctx.storeUserAuthToken`, or `ctx.adminUserAuthToken` in plain text, or forwarding raw tokens to downstream services that do not need them.
## Review checklist
- [ ] Does each VTEX integration use the correct requester identity: shopper, Admin user, or app?
- [ ] Are `ctx.storeUserAuthToken` and `ctx.adminUserAuthToken` preferred when a user is actually driving the action?
- [ ] Is `ctx.authToken` used only for app-level operations that are not tied to a current user?
- [ ] Are hardcoded VTEX credentials absent from normal IO app integrations?
- [ ] Is token propagation centralized in the client layer or explicit `authMethod` usage rather than scattered across handlers?
## Related skills
- [`vtex-io-auth-and-policies`](../vtex-io-auth-and-policies/SKILL.md) - Use when the main choice is which permissions and policies the chosen identity should carry
## Reference
- [App authentication using auth tokens](https://developers.vtex.com/docs/guides/app-authentication-using-auth-tokens) - Official token model for `AUTH_TOKEN`, `STORE_TOKEN`, and `ADMIN_TOKEN`
- [Using VTEX IO clients](https://developers.vtex.com/docs/guides/calling-commerce-apis-3-using-vtex-io-clients) - Client usage patterns that complement token selection
- [Policies](https://developers.vtex.com/docs/guides/vtex-io-documentation-policies) - How app-token permissions relate to manifest-declared policies
Creator's repository · vtex/skills