vtex-io-auth-and-policies
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAuthorization & Policy Design
授权与策略设计
When this skill applies
本指南适用场景
Use this skill when a VTEX IO app needs explicit permissions to call external services, consume VTEX resources, or expose access-controlled behavior.
- Adding an external API integration
- Consuming VTEX resources that require declared permissions
- Reviewing whether a route or client needs policy changes
- Tightening app permissions around an existing integration
Do not use this skill for:
- service runtime tuning
- HTTP handler structure
- frontend UI authorization behavior
- broader trust-boundary or sensitive-data modeling
- choosing between ,
AUTH_TOKEN, andSTORE_TOKENADMIN_TOKEN
当VTEX IO应用需要显式权限来调用外部服务、使用VTEX资源或暴露访问受控的功能时,请使用本指南:
- 新增外部API集成
- 使用需要声明权限的VTEX资源
- 审查路由或客户端是否需要修改策略
- 收紧现有集成对应的应用权限
本指南不适用于以下场景:
- 服务运行时调优
- HTTP处理器结构
- 前端UI授权逻辑
- 更大范围的信任边界或敏感数据建模
- 、
AUTH_TOKEN和STORE_TOKEN的选型ADMIN_TOKEN
Decision rules
决策规则
- Treat policies as explicit declarations of what the app is allowed to access.
manifest.json - Use this skill to decide what the app is authorized to do, not which runtime token identity should make the call.
- Add only the policies required for the integrations and resources the app actually uses.
- Use License Manager policies when the app needs access to VTEX platform resources protected by LM resource keys.
- Use app policies such as when the app consumes resources or operations exposed by another VTEX IO app through role-based policies.
"vendor.app-name:policy-name" - Use when the app needs to call external HTTP services or URLs that are not covered by License Manager or app policies.
outbound-access - Prefer narrowly scoped outbound-access declarations over wildcard hosts or paths.
- When exposing your own routes or operations, define access on the server side through resource-based policies, route protections, or auth directives instead of assuming consumers will declare something in their own manifest.
- A VRN (VTEX Resource Name) is the internal identifier format VTEX uses for resources and identities. Role-based policies use expressed as VRNs, and resource-based policies use
resourcesexpressed as VRNs.principals - Use VRNs only where the platform expects them, especially in resource-based policies or when interpreting authorization errors. Do not generate VRNs in
service.jsonfor consumer-side policy declarations.manifest.json - In resource-based policies, multiple are evaluated as alternatives, and explicit
principalsrules overridedenyrules.allow - When exposing your own role-based policies, keep them minimal and operation-specific rather than broad catch-all permissions.
- Review policy requirements when adding a new client, external integration, or service route that depends on protected access.
- Keep route implementation and policy declaration aligned: if a route depends on a protected integration, make sure the permission boundary is visible and intentional.
Policy types at a glance:
- License Manager policy:
json
{
"policies": [
{ "name": "Sku.aspx" }
]
}- App policy:
json
{
"policies": [
{ "name": "vtex.messages:graphql-translate-messages" }
]
}- Outbound-access policy:
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/api/*"
}
}
]
}- Resource-based route policy with app principal VRN:
json
{
"routes": {
"privateStatus": {
"path": "/_v/private/status/:code",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": [
"vrn:apps:*:my-sponsor-account:*:app/vendor.partner-app@0.x"
]
}
]
}
}
}This route allows a specific IO app principal. Other apps remain denied by default because they do not match any allow rule.
- Resource-based route policy with VTEX ID principal VRN:
json
{
"routes": {
"status": {
"path": "/_v/status/:code",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": [
"vrn:vtex.vtex-id:-:bibi:-:user/vtexappkey-mcc77-HBXYAE"
]
},
{
"effect": "deny",
"actions": ["POST"],
"principals": [
"vrn:vtex.vtex-id:-:bibi:-:user/*@vtex.com"
]
}
]
}
}
}This is an advanced pattern for integrations that identify callers through a specific VTEX ID principal, including appkey-based contracts. Prefer app VRNs for IO-to-IO access when the caller is another VTEX IO app. VTEX IO auth tokens such as , , and play a different role: they authenticate requests to VTEX services and help preserve requester context, but they do not automatically replace route-level resource policies based on VRN principals.
AUTH_TOKENSTORE_TOKENADMIN_TOKEN- 将中的策略视为应用允许访问范围的显式声明。
manifest.json - 本指南用于决策应用的授权操作范围,而非选择发起调用的运行时Token身份。
- 仅添加应用实际使用的集成和资源所需的策略。
- 当应用需要访问受License Manager资源密钥保护的VTEX平台资源时,使用License Manager策略。
- 当应用使用其他VTEX IO应用通过基于角色的策略暴露的资源或操作时,使用应用策略,例如。
"vendor.app-name:policy-name" - 当应用需要调用License Manager或应用策略未覆盖的外部HTTP服务或URL时,使用策略。
outbound-access - 优先使用窄范围的outbound-access声明,而非通配符主机或路径。
- 当暴露自有路由或操作时,通过基于资源的策略、路由保护或授权指令在服务端定义访问规则,不要假设调用方会在自己的manifest中声明相关权限。
- VRN(VTEX Resource Name)是VTEX用于资源和身份的内部标识符格式。基于角色的策略使用VRN格式的,基于资源的策略使用VRN格式的
resources。principals - 仅在平台要求的位置使用VRN,尤其是的基于资源的策略中,或是解析授权错误时。不要在
service.json中为调用方侧的策略声明生成VRN。manifest.json - 在基于资源的策略中,多个为或的关系,显式
principals规则优先级高于deny规则。allow - 当暴露自有的基于角色的策略时,保持策略最小化、面向特定操作,而非宽泛的全量权限。
- 新增依赖受保护访问的客户端、外部集成或服务路由时,审查策略要求。
- 保持路由实现和策略声明一致:如果路由依赖受保护的集成,请确保权限边界是明确且有意设置的。
策略类型概览:
- License Manager策略:
json
{
"policies": [
{ "name": "Sku.aspx" }
]
}- 应用策略:
json
{
"policies": [
{ "name": "vtex.messages:graphql-translate-messages" }
]
}- Outbound-access策略:
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/api/*"
}
}
]
}- 基于资源、使用应用主体VRN的路由策略:
json
{
"routes": {
"privateStatus": {
"path": "/_v/private/status/:code",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": [
"vrn:apps:*:my-sponsor-account:*:app/vendor.partner-app@0.x"
]
}
]
}
}
}该路由允许特定IO应用主体访问,其他应用默认会被拒绝,因为它们不符合任何允许规则。
- 基于资源、使用VTEX ID主体VRN的路由策略:
json
{
"routes": {
"status": {
"path": "/_v/status/:code",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": [
"vrn:vtex.vtex-id:-:bibi:-:user/vtexappkey-mcc77-HBXYAE"
]
},
{
"effect": "deny",
"actions": ["POST"],
"principals": [
"vrn:vtex.vtex-id:-:bibi:-:user/*@vtex.com"
]
}
]
}
}
}这是一种高级模式,适用于通过特定VTEX ID主体(包括基于appkey的契约)识别调用方的集成。当调用方是其他VTEX IO应用时,优先使用应用VRN实现IO应用间的访问。VTEX IO授权Token(如、、)的作用不同:它们用于对发往VTEX服务的请求进行身份验证,帮助保留请求方上下文,但不能自动替代基于VRN主体的路由级资源策略。
AUTH_TOKENSTORE_TOKENADMIN_TOKENHard constraints
硬约束
Constraint: Every protected integration must have an explicit supporting policy
约束:所有受保护的集成必须有对应的显式策略支持
If a client or route depends on access controlled by License Manager policies, role-based app policies, or , the app MUST declare the corresponding permission explicitly in . Resources protected by resource-based policies define access on the server side and do not require consumer apps to declare additional policies just for that server-side enforcement.
outbound-accessmanifest.jsonWhy this matters
Without the required policy, the code may be correct but the platform will still block the access at runtime, leading to failures that are hard to debug from handler code alone.
Detection
If you see a new external host, VTEX resource, or protected capability being consumed, STOP and verify that the required consumer-side policy exists before merging the code. If the app is exposing a protected route or operation, STOP and confirm that the access rule is also enforced on the server side.
Correct
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/api/*"
}
}
]
}Wrong
json
{
"policies": []
}如果客户端或路由依赖受License Manager策略、基于角色的应用策略或控制的访问,应用必须在中显式声明对应的权限。受基于资源的策略保护的资源会在服务端定义访问规则,不需要调用方应用仅为了服务端的规则额外声明策略。
outbound-accessmanifest.json重要性说明
如果缺少所需的策略,即使代码逻辑正确,平台仍会在运行时拦截访问,导致仅从处理器代码很难排查的故障。
检测方式
如果发现代码中使用了新的外部主机、VTEX资源或受保护功能,请先验证调用方侧是否存在所需的策略,再合并代码。如果应用要暴露受保护的路由或操作,请先确认服务端也强制执行了对应的访问规则。
正确示例
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/api/*"
}
}
]
}错误示例
json
{
"policies": []
}Constraint: Outbound policies must follow least privilege
约束:出站策略必须遵循最小权限原则
Outbound-access policies MUST be scoped as narrowly as practical for the target host and path.
Why this matters
Broad outbound rules increase risk, make reviews harder, and allow integrations to expand silently beyond their intended surface.
Detection
If you see wildcard hosts or overly broad paths when the integration uses a much smaller surface, STOP and narrow the declaration.
Correct
json
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/orders/*"
}
}Wrong
json
{
"name": "outbound-access",
"attrs": {
"host": "*",
"path": "/*"
}
}Outbound-access策略的范围必须尽可能缩小到实际需要的目标主机和路径。
重要性说明
宽泛的出站规则会提升风险、加大审查难度,还会让集成的权限范围无声地超出预期边界。
检测方式
如果集成实际使用的范围很小,但声明中使用了通配符主机或过于宽泛的路径,请先缩小声明范围再继续。
正确示例
json
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/orders/*"
}
}错误示例
json
{
"name": "outbound-access",
"attrs": {
"host": "*",
"path": "/*"
}
}Constraint: Policy changes must be reviewed together with the behavior they enable
约束:策略变更必须和它支持的功能一起审查
When a policy is added or widened, the route or integration behavior that depends on it MUST be reviewed in the same change.
Why this matters
Permissions are meaningful only in context. Reviewing a policy change without the code that consumes it makes overreach and hidden side effects easier to miss.
Detection
If a PR changes permissions without showing the relevant route, client, or integration code, STOP and request the linked behavior before approving.
manifest.jsonCorrect
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/orders/*"
}
}
]
}Wrong
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/api/*"
}
}
]
}This broader policy alone does not explain why the app needs the expanded access.
当新增或扩大策略范围时,依赖该策略的路由或集成功能必须在同一次变更中一起审查。
重要性说明
权限只有结合上下文才有意义。脱离使用策略的代码单独审查策略变更,很容易遗漏权限过度和隐藏的副作用。
检测方式
如果PR修改了的权限,但没有提供对应的路由、客户端或集成代码,请先要求提供关联的功能代码再审批。
manifest.json正确示例
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/orders/*"
}
}
]
}错误示例
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/api/*"
}
}
]
}仅这个更宽泛的策略无法说明应用为什么需要扩大访问范围。
Preferred pattern
首选模式
Start from the client or route behavior, identify the minimal access needed, and declare only that permission in . When the app exposes protected routes or operations, define the resource-based access rule on the server side as part of the same review.
manifest.jsonExample pattern:
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/orders/*"
}
}
]
}Review permissions whenever integrations change, not only when policy errors appear in runtime.
从客户端或路由功能出发,识别所需的最小访问范围,仅在中声明该权限。当应用暴露受保护的路由或操作时,在同一次审查中完成服务端基于资源的访问规则定义。
manifest.json示例模式:
json
{
"policies": [
{
"name": "outbound-access",
"attrs": {
"host": "partner.example.com",
"path": "/orders/*"
}
}
]
}每次集成变更时都要审查权限,不要等到运行时出现策略错误才处理。
Common failure modes
常见故障模式
- Forgetting the outbound-access policy for a new external integration.
- Using an outbound-access policy when the real requirement is a License Manager resource key or an app policy exposed by another VTEX IO app.
- Using wildcard hosts or paths when a narrower declaration would work.
- Assuming consumer apps must declare manifest policies for resources that are actually enforced through resource-based policies on the server side.
- Adding permissions without reviewing the route or client behavior they enable.
- Treating policy failures as code bugs instead of permission bugs.
- Treating a that names a VRN resource or principal as a handler bug instead of an authorization or policy-mapping problem.
403
- 新增外部集成时忘记添加outbound-access策略。
- 实际需要的是License Manager资源密钥或其他VTEX IO应用暴露的应用策略,却使用了outbound-access策略。
- 可以使用更窄的声明时,却使用了通配符主机或路径。
- 误以为调用方应用需要在manifest中声明策略,但实际资源的访问规则是通过服务端的基于资源的策略强制执行的。
- 添加权限时没有审查它支持的路由或客户端功能。
- 将策略故障视为代码bug,而非权限配置问题。
- 将指向VRN资源或主体的403错误视为处理器bug,而非授权或策略映射问题。
Review checklist
审查清单
- Does every protected integration have an explicit policy?
- Is the policy type correct for the access pattern: License Manager, app policy, or outbound-access?
- Are outbound-access rules narrow enough for the real integration surface?
- If the app exposes protected routes or operations, is server-side access control defined explicitly as well?
- Is the policy change reviewed together with the route or client that needs it?
- Are wildcard permissions avoided unless strictly necessary?
- 所有受保护的集成都有对应的显式策略吗?
- 策略类型和访问模式匹配吗:License Manager、应用策略还是outbound-access?
- Outbound-access规则的范围是否缩小到了实际的集成使用范围?
- 如果应用暴露受保护的路由或操作,是否也显式定义了服务端访问控制?
- 策略变更是否和依赖它的路由或客户端一起审查?
- 除非绝对必要,是否避免了通配符权限?
Reference
参考资料
- Policies - Policy types and manifest declaration
- Accessing external resources within a VTEX IO app - Outbound-access policy guidance
- Policies from License Manager - License Manager resource keys and policy usage
- Controlling access to app resources - Role-based and resource-based access for your own app resources
- VTEX Resource Name (VRN) - How VTEX expresses resources and principals in policies
- Manifest - App contract and permission declaration
- 策略 - 策略类型与manifest声明
- 在VTEX IO应用中访问外部资源 - Outbound-access策略指导
- 来自License Manager的策略 - License Manager资源密钥与策略使用
- 控制应用资源的访问 - 自有应用资源的基于角色和基于资源的访问控制
- VTEX Resource Name (VRN) - VTEX如何在策略中表示资源和主体
- Manifest - 应用契约与权限声明