vtex-io-rbac
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVTEX IO access control (RBAC)
VTEX IO 访问控制(RBAC)
When this skill applies
本技能适用场景
Use this skill when you need to control who can access your VTEX IO app's routes and resources:
- Deciding between role-based () and resource-based (
policies.jsonpolicies) access controlservice.json - Securing REST endpoints so only specific apps, users, or API keys can call them
- Setting up GraphQL authorization with the directive
@auth - Understanding VRN (VTEX Resource Name) syntax for declaring principals
- Debugging 403 Forbidden errors caused by missing or misconfigured policies
Do not use this skill for:
- General service architecture (use )
vtex-io-service-apps - PCI compliance and payment security (use )
payment-pci-security - Route prefix and CDN behavior (use )
vtex-io-service-paths-and-cdn
当您需要控制谁可以访问您的VTEX IO应用的路由和资源时,可使用本技能:
- 选择基于角色()还是基于资源(
policies.json策略)的访问控制方式service.json - 保护REST端点,仅允许特定应用、用户或API密钥调用
- 使用指令配置GraphQL授权
@auth - 理解用于声明主体的VRN(VTEX资源名称)语法
- 调试因策略缺失或配置错误导致的403 Forbidden错误
本技能不适用于:
- 通用服务架构(请使用)
vtex-io-service-apps - PCI合规与支付安全(请使用)
payment-pci-security - 路由前缀与CDN行为(请使用)
vtex-io-service-paths-and-cdn
Decision rules
决策规则
Role-based vs resource-based policies
基于角色 vs 基于资源的策略
Role-based ( | Resource-based ( | |
|---|---|---|
| Who can call? | Only other IO apps (by themselves or on behalf of other apps) | Apps, users, and integrations (API keys) |
| API types | GraphQL and REST | REST only |
| How callers get access | Must declare required policies in their | No policy declaration needed; just call with auth token |
| Where configured | | |
| Use when | Exposing GraphQL endpoints; exposing REST endpoints for app-to-app only | Controlling access for users, API keys, or specific apps to REST endpoints |
基于角色( | 基于资源( | |
|---|---|---|
| 允许调用者 | 仅其他IO应用(自行调用或代表其他应用调用) | 应用、用户和集成(API密钥) |
| 支持API类型 | GraphQL和REST | 仅REST |
| 调用者获取权限方式 | 必须在其 | 无需声明策略;只需携带认证令牌调用 |
| 配置位置 | 应用根目录下的 | |
| 适用场景 | 暴露GraphQL端点;仅为应用间调用暴露REST端点 | 控制用户、API密钥或特定应用对REST端点的访问权限 |
Choosing the right approach
选择合适的方案
- GraphQL endpoints → Use role-based policies () and/or the
policies.jsondirective in the schema for user-level authorization.@auth - REST endpoint called only by other IO apps → Use role-based policies (). Consuming apps must declare the policy in their
policies.json.manifest.json - REST endpoint called by users or API keys → Use resource-based policies in . Set the route as
service.jsonand define principals."public": false - Public REST endpoint (no auth) → Set in
"public": true. No policies needed, but be aware this means anyone can call it.service.json
- GraphQL端点 → 使用基于角色的策略()和/或 Schema中的**
policies.json指令**实现用户级授权。@auth - 仅被其他IO应用调用的REST端点 → 使用基于角色的策略()。消费应用必须在其
policies.json中声明该策略。manifest.json - 被用户或API密钥调用的REST端点 → 使用中的基于资源的策略。将路由设置为
service.json并定义主体。"public": false - 公开REST端点(无需认证) → 在中设置
service.json。无需配置策略,但请注意这意味着任何人都可以调用该端点。"public": true
VRN syntax
VRN语法
VRNs (VTEX Resource Names) identify resources and principals:
text
vrn:{service}:{region}:{account}:{workspace}:{path}- Apps:
vrn:apps:*:*:*:app/{vendor}.{app-name}@{version} - Users:
vrn:vtex.vtex-id:*:*:*:user/{email} - API keys:
vrn:vtex.vtex-id:*:*:*:user/vtexappkey-{account}-{hash} - Wildcards: matches any value in a segment.
*matches all apps.app/*matches all Gmail users.user/*@gmail.com
VRN(VTEX资源名称)用于标识资源和主体:
text
vrn:{service}:{region}:{account}:{workspace}:{path}- 应用:
vrn:apps:*:*:*:app/{vendor}.{app-name}@{version} - 用户:
vrn:vtex.vtex-id:*:*:*:user/{email} - API密钥:
vrn:vtex.vtex-id:*:*:*:user/vtexappkey-{account}-{hash} - 通配符:匹配任意分段值。
*匹配所有应用。app/*匹配所有Gmail用户。user/*@gmail.com
Hard constraints
硬性约束
Constraint: Use resource-based policies when users or API keys need access
约束:当用户或API密钥需要访问时,必须使用基于资源的策略
Role-based policies only work for app-to-app communication. If users (admin or storefront) or integrations (API keys) need to call your endpoint, you must use resource-based policies in with the route set to .
service.json"public": falseWhy this matters — Setting up a role-based policy for a route that users or API keys call results in 403 Forbidden for those callers, because role-based policies don't evaluate user/integration tokens.
Detection — A private route that should be callable by admin users or external integrations, but only has configuration and no array in .
policies.jsonpoliciesservice.jsonCorrect — Resource-based policy in for user/integration access.
service.jsonjson
{
"routes": {
"orders": {
"path": "/_v/private/my-app/orders",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["GET", "POST"],
"principals": [
"vrn:vtex.vtex-id:*:*:*:user/*@mycompany.com",
"vrn:apps:*:*:*:app/partner.integration-app@*"
]
}
]
}
}
}Wrong — Only for a route that users need.
policies.jsonjson
// policies.json — this only covers app-to-app, not users
[
{
"name": "access-orders",
"statements": [
{
"effect": "allow",
"actions": ["GET"],
"resources": ["vrn:my-app:*:*:*:/_v/private/my-app/orders"]
}
]
}
]
// Users calling this route still get 403基于角色的策略仅适用于应用间通信。如果用户(管理员或店铺前台)或集成(API密钥)需要调用您的端点,您必须在中使用基于资源的策略,并将路由设置为。
service.json"public": false重要性 — 为用户或API密钥调用的路由配置基于角色的策略会导致这些调用者收到403 Forbidden错误,因为基于角色的策略不会验证用户/集成令牌。
检测方式 — 一个私有路由本应允许管理员用户或外部集成调用,但仅配置了,而中没有数组。
policies.jsonservice.jsonpolicies正确示例 — 使用中的基于资源策略实现用户/集成访问。
service.jsonjson
{
"routes": {
"orders": {
"path": "/_v/private/my-app/orders",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["GET", "POST"],
"principals": [
"vrn:vtex.vtex-id:*:*:*:user/*@mycompany.com",
"vrn:apps:*:*:*:app/partner.integration-app@*"
]
}
]
}
}
}错误示例 — 仅为用户需要访问的路由配置。
policies.jsonjson
// policies.json — 仅覆盖应用间访问,不支持用户访问
[
{
"name": "access-orders",
"statements": [
{
"effect": "allow",
"actions": ["GET"],
"resources": ["vrn:my-app:*:*:*:/_v/private/my-app/orders"]
}
]
}
]
// 用户调用该路由仍会收到403错误Constraint: Deny policies take precedence over allow policies
约束:拒绝策略优先级高于允许策略
When resource-based policies have overlapping principals between an and a rule, the deny always wins. Be careful with wildcards in allow rules that intersect with specific deny rules.
allowdenyWhy this matters — A broad for combined with a specific for correctly blocks . But the reverse—a broad with a specific —blocks everything including what you wanted to allow.
allowapp/*denyapp/vendor.bad-app@*bad-appdenyallowDetection — Multiple policy entries for the same route with conflicting effects and overlapping principals.
Correct — Allow broadly, deny specifically.
json
{
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/*"]
},
{
"effect": "deny",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/untrusted.app@*"]
}
]
}Wrong — Deny broadly, try to allow specifically (the allow is overridden).
json
{
"policies": [
{
"effect": "deny",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/*"]
},
{
"effect": "allow",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/trusted.app@*"]
}
]
}当基于资源的策略中,允许和拒绝规则的主体存在重叠时,拒绝规则始终优先。需注意允许规则中的通配符与特定拒绝规则的交集。
重要性 — 为设置宽泛的允许规则,同时为设置特定的拒绝规则,可正确阻止。但反过来——宽泛的拒绝规则加特定的允许规则——会阻止所有请求,包括您想要允许的请求。
app/*app/vendor.bad-app@*bad-app检测方式 — 同一路由存在多个策略条目,且效果和主体存在冲突。
正确示例 — 先宽泛允许,再特定拒绝。
json
{
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/*"]
},
{
"effect": "deny",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/untrusted.app@*"]
}
]
}错误示例 — 先宽泛拒绝,再尝试特定允许(允许规则会被覆盖)。
json
{
"policies": [
{
"effect": "deny",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/*"]
},
{
"effect": "allow",
"actions": ["POST"],
"principals": ["vrn:apps:*:*:*:app/trusted.app@*"]
}
]
}Preferred pattern
推荐模式
Role-based policy (policies.json
)
policies.json基于角色的策略(policies.json
)
policies.jsonjson
[
{
"name": "resolve-graphql",
"description": "Allows apps to resolve GraphQL requests",
"statements": [
{
"effect": "allow",
"actions": ["POST"],
"resources": [
"vrn:vtex.store-graphql:{{region}}:{{account}}:{{workspace}}:/_v/graphql"
]
}
]
}
]The consuming app declares the policy in its :
manifest.jsonjson
{
"policies": [
{
"name": "resolve-graphql"
}
]
}json
[
{
"name": "resolve-graphql",
"description": "Allows apps to resolve GraphQL requests",
"statements": [
{
"effect": "allow",
"actions": ["POST"],
"resources": [
"vrn:vtex.store-graphql:{{region}}:{{account}}:{{workspace}}:/_v/graphql"
]
}
]
}
]消费应用需在其中声明该策略:
manifest.jsonjson
{
"policies": [
{
"name": "resolve-graphql"
}
]
}Resource-based policy for mixed access
支持混合访问的基于资源策略
json
{
"routes": {
"webhook": {
"path": "/_v/private/my-app/webhook",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": [
"vrn:apps:*:*:*:app/vtex.orders-broadcast@*",
"vrn:vtex.vtex-id:*:*:*:user/vtexappkey-myaccount-*"
]
}
]
}
}
}json
{
"routes": {
"webhook": {
"path": "/_v/private/my-app/webhook",
"public": false,
"policies": [
{
"effect": "allow",
"actions": ["POST"],
"principals": [
"vrn:apps:*:*:*:app/vtex.orders-broadcast@*",
"vrn:vtex.vtex-id:*:*:*:user/vtexappkey-myaccount-*"
]
}
]
}
}
}GraphQL @auth
directive
@authGraphQL @auth
指令
@authFor GraphQL endpoints, use the directive for user-level authorization:
@authgraphql
type Query {
orders: [Order] @auth(productCode: "10", resourceCode: "list-orders")
adminSettings: Settings
@auth(productCode: "10", resourceCode: "admin-settings")
}
type Mutation {
updateSettings(input: SettingsInput!): Settings
@auth(productCode: "10", resourceCode: "admin-settings")
}The directive checks the caller's License Manager role for the specified and .
@authproductCoderesourceCode对于GraphQL端点,使用指令实现用户级授权:
@authgraphql
type Query {
orders: [Order] @auth(productCode: "10", resourceCode: "list-orders")
adminSettings: Settings
@auth(productCode: "10", resourceCode: "admin-settings")
}
type Mutation {
updateSettings(input: SettingsInput!): Settings
@auth(productCode: "10", resourceCode: "admin-settings")
}@authproductCoderesourceCodeCommon failure modes
常见失败模式
- 403 for users on role-based routes — Route only has ; users and API keys get 403 because role-based policies don't apply to them.
policies.json - Overly broad — Route set to public when it should be private. Anyone can call it without auth.
public: true - Missing policy in consumer manifest — App tries to call a role-based protected route but didn't declare the policy in its . Results in 403.
manifest.json - VRN typo — Misspelled vendor, app name, or principal format in VRN. Silently fails to match, resulting in 403.
- Wildcard in deny — Broad deny with blocks all apps including trusted ones. Deny takes precedence.
app/* - No on GraphQL mutations — Mutations that modify data accessible without role checks.
@auth
- 基于角色的路由对用户返回403 — 路由仅配置了;用户和API密钥会收到403错误,因为基于角色的策略不适用于他们。
policies.json - 过度宽泛的设置 — 本应设为私有路由却被设为公开。任何人无需认证即可调用。
public: true - 消费应用清单中缺失策略 — 应用尝试调用受基于角色策略保护的路由,但未在其中声明该策略。导致403错误。
manifest.json - VRN拼写错误 — VRN中的供应商、应用名称或主体格式拼写错误。匹配失败会静默发生,导致403错误。
- 拒绝规则中使用通配符 — 为设置宽泛的拒绝规则会阻止所有应用,包括可信应用。拒绝规则优先级更高。
app/* - GraphQL变更未添加— 可修改数据的变更未设置角色检查。
@auth
Review checklist
审核清单
- Is the access control type (role-based vs resource-based) correct for the callers (apps vs users/integrations)?
- Are private routes set to with appropriate policies?
"public": false - Are VRNs correctly formatted for the principal type (apps, users, API keys)?
- Do consuming apps declare required role-based policies in their ?
manifest.json - Are deny rules used carefully (they override allow rules for intersecting principals)?
- Do GraphQL mutations have directives with correct
@authandproductCode?resourceCode - Are wildcard principals scoped as narrowly as possible?
- 访问控制类型(基于角色 vs 基于资源)是否与调用者类型(应用 vs 用户/集成)匹配?
- 私有路由是否设置为并配置了合适的策略?
"public": false - 针对主体类型(应用、用户、API密钥)的VRN格式是否正确?
- 消费应用是否在其中声明了所需的基于角色策略?
manifest.json - 是否谨慎使用拒绝规则(它们会覆盖重叠主体的允许规则)?
- GraphQL变更是否添加了带有正确和
productCode的resourceCode指令?@auth - 通配符主体的范围是否尽可能缩小?
Related skills
相关技能
- vtex-io-service-apps — Service class, clients, and route configuration
- vtex-io-app-contract — Manifest, builders, and policy declarations
- vtex-io-graphql-api — GraphQL schema and directive details
@auth - vtex-io-service-paths-and-cdn — Route prefix patterns
- vtex-io-service-apps — 服务类、客户端和路由配置
- vtex-io-app-contract — 清单、构建器和策略声明
- vtex-io-graphql-api — GraphQL Schema和指令细节
@auth - vtex-io-service-paths-and-cdn — 路由前缀模式
Reference
参考资料
- Controlling Access to App Resources — Role-based and resource-based policies, VRN syntax, principal types
- App Authentication Using Auth Tokens — Auth token types for app-to-app and user-to-app communication
- GraphQL Authorization in IO Apps — @auth directive usage
- VTEX IO VRN — VTEX Resource Name format and examples
- Controlling Access to App Resources — 基于角色和基于资源的策略、VRN语法、主体类型
- App Authentication Using Auth Tokens — 应用间和用户-应用通信的认证令牌类型
- GraphQL Authorization in IO Apps — @auth指令用法
- VTEX IO VRN — VTEX资源名称格式与示例