Skip to content

[SEC] Field-Level Auth + Resource Ownership + RBAC #12

@oomokaro1

Description

@oomokaro1

[SEC] Field-Level Authorization + Resource Ownership Guard

Priority: High

Difficulty: Hard
Estimated Effort: 3-4 days
Relevant Packages: OrbitStream_backend/, orbitstream_docs/
Labels: security, enhancement, priority:high

Requirements

1. Public vs Authenticated Response Filtering

  • Create a PublicSessionDto that strips sensitive fields: only returns id, url, amount, asset, status, expiresAt
  • The public GET /v1/checkout/sessions/:id returns PublicSessionDto
  • The authenticated merchant endpoint returns the full CheckoutSession object
  • Use class-transformer @Exclude() and @Expose() decorators, or manual field selection

2. ResourceOwnershipGuard

Create a reusable guard that verifies the authenticated merchant owns the resource:

// src/auth/resource-ownership.guard.ts
@Injectable()
export class ResourceOwnershipGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const merchantId = request.merchantId; // from JWT or API key
    const resourceId = request.params.id;

    // Look up resource and verify ownership
    // Return true if owned, throw ForbiddenException if not
  }
}

Apply to:

  • DELETE /merchants/me/api-keys/:id — verify key belongs to merchant
  • POST /v1/checkout/sessions/:id/cancel — verify session belongs to merchant
  • All future merchant-scoped endpoints

3. Role-Based Access Control

  • Add a role column to the merchants table: admin | merchant | viewer (default: merchant)
  • Create a RolesGuard that checks @Roles('admin') decorator
  • admin can access all merchants' data (platform operators)
  • merchant can access only their own data (default)
  • viewer can read but not write (for team members)
  • Create a @Roles() decorator

4. Audit Logging

  • Log all authorization failures: who tried to access what, from which IP
  • Create an audit_logs table: id, merchant_id, action, resource_type, resource_id, ip_address, user_agent, created_at
  • Log: failed auth attempts, successful logins, resource access denials, sensitive operations (API key generation, webhook changes)

5. Input Sanitization

  • Validate walletAddress format: must start with G, be exactly 56 characters, base32-encoded
  • Validate email format with RFC 5322 compliant regex
  • Validate webhookUrl format: must be HTTPS in production
  • Validate amount is positive and within reasonable bounds (0 < amount < 1,000,000)

6. Testing

  • Unit test: ResourceOwnershipGuard allows owner, denies non-owner
  • Unit test: RolesGuard allows admin, denies viewer on write endpoints
  • Unit test: PublicSessionDto excludes sensitive fields
  • Integration test: merchant A cannot cancel merchant B's session
  • Integration test: viewer role cannot generate API keys
  • Integration test: admin can access any merchant's data

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions