-
Notifications
You must be signed in to change notification settings - Fork 101
Description
Environment information
npx ampx info
System:
OS: macOS 14.5
CPU: (8) arm64 Apple M1 Pro
Memory: 206.73 MB / 16.00 GB
Shell: /bin/zsh
Binaries:
Node: 20.9.0 - /usr/local/bin/node
Yarn: 1.22.19 - /opt/homebrew/bin/yarn
npm: 10.2.4 - /opt/homebrew/bin/npm
pnpm: undefined - undefined
NPM Packages:
@aws-amplify/auth-construct: 1.8.1
@aws-amplify/backend: 1.16.1
@aws-amplify/backend-ai: Not Found
@aws-amplify/backend-auth: 1.7.1
@aws-amplify/backend-cli: 1.8.0
@aws-amplify/backend-data: 1.6.1
@aws-amplify/backend-deployer: 2.1.3
@aws-amplify/backend-function: 1.14.1
@aws-amplify/backend-output-schemas: 1.7.0
@aws-amplify/backend-output-storage: 1.3.1
@aws-amplify/backend-secret: 1.4.0
@aws-amplify/backend-storage: 1.4.1
@aws-amplify/cli-core: 2.2.1
@aws-amplify/client-config: 1.8.0
@aws-amplify/data-construct: 1.16.3
@aws-amplify/data-schema: 1.20.3
@aws-amplify/deployed-backend-client: 1.8.0
@aws-amplify/form-generator: 1.2.4
@aws-amplify/model-generator: 1.2.0
@aws-amplify/platform-core: 1.10.0
@aws-amplify/plugin-types: 1.11.0
@aws-amplify/sandbox: 2.1.2
@aws-amplify/schema-generator: 1.4.0
@aws-cdk/toolkit-lib: 1.1.1
aws-amplify: 6.15.3
aws-cdk-lib: 2.206.0
typescript: 5.8.3
AWS environment variables:
AWS_SDK_LOAD_CONFIG = 1
No CDK environment variables
Describe the bug
AWS Amplify Gen 2: Multi-Tenant RBAC Authorization Pattern
Database Schema
I have a multi-tenant SaaS application with this data structure:
Company Table
Company: a.model({
id: a.id().required(),
companyName: a.string(),
companyBackground: a.string(),
// ... other company fields
// Relationships
memberships: a.hasMany('CompanyMembership', 'companyId'),
})
CompanyMembership Table (Junction Table)
CompanyMembership: a.model({
id: a.id().required(),
userId: a.string().required(), // Cognito user ID
companyId: a.id().required(), // Reference to Company
role: a.enum(['owner', 'admin', 'editor', 'viewer']),
status: a.enum(['active', 'inactive', 'pending']),
// Relationships
company: a.belongsTo('Company', 'companyId'),
})
JWT Token Structure
My PreTokenGeneration Lambda creates these custom claims:
{
"sub": "user-cognito-id",
"user_companies": "owner authenticated", // Roles as string
"company_access": "company-id-user-belongs-to", // Single company ID
"cognito:groups": ["company-id-owner", "owner", "authenticated"]
}
Current Problem
Users can query client.models.Company.list()
and see ALL companies in the database, not just companies they belong to.
What I Want to Achieve
Multi-tenant RBAC where:
- Users can ONLY access companies they have active membership in
- Within each company, users have different permissions based on their role:
owner
: Full CRUD accessadmin
: Full CRUD accesseditor
: Read + Update onlyviewer
: Read only
Current Authorization Attempt
Company: a.model({
// ... fields
})
.authorization((allow) => [
allow.ownerDefinedIn('company_access'),
allow.groups(['owner', 'admin']).withClaimIn('user_companies').to(['read', 'create', 'update', 'delete']),
allow.groups(['editor']).withClaimIn('user_companies').to(['read', 'update']),
allow.groups(['viewer']).withClaimIn('user_companies').to(['read']),
])
Problem: The role-based rules grant access to ALL companies if user has the role, completely bypassing company scoping.
Questions
-
What's the correct authorization pattern for multi-tenant RBAC in Amplify Gen 2?
-
How should I structure my JWT claims to support both company scoping AND role-based permissions?
-
Should I use only custom resolvers instead of model-level authorization for this use case?
-
Is there a way to combine
ownerDefinedIn()
withgroups().withClaimIn()
to create AND logic instead of OR logic?
Looking for the recommended approach to implement secure multi-tenant authorization with AWS Amplify Gen 2.
Reproduction steps
NA