Skip to content

Security Attributes

lpachecob edited this page Mar 24, 2026 · 3 revisions

🔒 Security Attributes

BOUNDLY provides declarative security attributes to protect sensitive data, control access, and ensure data integrity at the attribute level.


📍 Location

Infrastructure\FrameworkCore\Attributes\Security\

🎭 #[Hidden]

Excludes a property from all API responses. Useful for sensitive data that should never be exposed to clients.

Target: Property

Use Case: Passwords, passwords confirmations, tokens, internal IDs, or any field that should never appear in JSON output.

Example:

use Infrastructure\FrameworkCore\Attributes\Schema\{Entity, Column, Id};
use Infrastructure\FrameworkCore\Attributes\Security\Hidden;

#[Entity(table: 'users', resource: 'users')]
class User extends AggregateRoot
{
    #[Id]
    private int $id;

    #[Column(type: 'string', length: 150)]
    private string $name;

    #[Column(type: 'string', length: 255)]
    private string $email;

    #[Hidden]
    #[Column(type: 'string')]
    private string $password;

    #[Hidden]
    #[Column(type: 'string', length: 255)]
    private string $internalNotes;
}

API Response (GET /api/users/1):

{
  "id": 1,
  "name": "John Doe",
  "email": "john@example.com"
}

Note: The password and internalNotes fields are completely excluded from the response.


🔐 #[Encrypted]

Encrypts the property value before storing in the database and decrypts it when retrieving. Uses AES-256-CBC encryption.

Target: Property

Parameter Type Default Description
algorithm string 'AES-256-CBC' Encryption algorithm

Use Case: Personally Identifiable Information (PII), API keys, secrets, sensitive configuration data.

Requirements:

  • APP_KEY must be set in your .env file
  • Encryption happens transparently on INSERT/UPDATE
  • Decryption happens transparently on SELECT

Example:

use Infrastructure\FrameworkCore\Attributes\Schema\{Entity, Column, Id};
use Infrastructure\FrameworkCore\Attributes\Security\Encrypted;

#[Entity(table: 'integrations', resource: 'integrations')]
class Integration extends AggregateRoot
{
    #[Id]
    private int $id;

    #[Column(type: 'string', length: 150)]
    private string $name;

    #[Encrypted]
    #[Column(type: 'text')]
    private string $apiKey;

    #[Encrypted(algorithm: 'AES-256-CBC')]
    #[Column(type: 'text')]
    private string $webhookSecret;
}

Database Storage:

-- Stored encrypted (not readable in plain text)
-- aW5zZXJ0LXZlcnktbG9uZy1hcGkta2V5LXZhbHVl

API Behavior:

// GET /api/integrations/1
{
  "id": 1,
  "name": "Stripe",
  "apiKey": "sk_live_abc123...",  // Automatically decrypted
  "webhookSecret": "whsec_xyz789..."  // Automatically decrypted
}

#️⃣ #[Hashed]

Automatically hashes the value before storage using bcrypt or Argon2. Ideal for passwords and sensitive strings that should never be retrievable.

Target: Property

Parameter Type Default Description
algorithm string 'bcrypt' Hashing algorithm (bcrypt, argon2i, argon2id)
options array [] Algorithm-specific options (e.g., ['rounds' => 12])

Use Case: Passwords, PINs, security questions answers, or any sensitive data that should be stored irreversibly.

Example:

use Infrastructure\FrameworkCore\Attributes\Schema\{Entity, Column, Id};
use Infrastructure\FrameworkCore\Attributes\Security\Hashed;

#[Entity(table: 'users', resource: 'users')]
class User extends AggregateRoot
{
    #[Id]
    private int $id;

    #[Column(type: 'string', length: 150)]
    private string $name;

    #[Hashed(algorithm: 'bcrypt', options: ['rounds' => 12])]
    #[Column(type: 'string')]
    private string $password;

    #[Hashed(algorithm: 'argon2id')]
    #[Column(type: 'string')]
    private string $pin;
}

Database Storage:

-- Stored as bcrypt hash (irreversible)
-- $2y$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/X4.H7pB7p4ZZ7Z7LK

Important Notes:

  1. Hashing is one-way - You cannot retrieve the original value
  2. Hashes on INSERT - Automatically hashes when creating records
  3. Hashes on UPDATE - Only if the value has changed
  4. Verification - Use Hash::check($plain, $hashed) to verify:
if (Hash::check($request->password, $user->password)) {
    // Password is correct
}

🎯 Combining Security Attributes

You can combine multiple security attributes for maximum protection:

use Infrastructure\FrameworkCore\Attributes\Schema\{Entity, Column, Id};
use Infrastructure\FrameworkCore\Attributes\Security\{Hidden, Encrypted, Hashed};

#[Entity(table: 'users', resource: 'users')]
class User extends AggregateRoot
{
    #[Id]
    private int $id;

    #[Column(type: 'string', length: 150)]
    private string $name;

    // Never returned in API responses
    #[Hidden]
    // Encrypted at rest in database
    #[Encrypted]
    // Hashed before storage (one-way)
    #[Hashed(algorithm: 'bcrypt', options: ['rounds' => 12])]
    #[Column(type: 'string')]
    private string $password;

    // Visible in API but encrypted in database
    #[Encrypted]
    #[Column(type: 'string', length: 20)]
    private string $phone;

    // Encrypted and hidden
    #[Hidden]
    #[Encrypted]
    #[Column(type: 'text')]
    private string $socialSecurityNumber;
}

🔄 Security Attribute Flow

┌─────────────────────────────────────────────────────────────────┐
│                        REQUEST RECEIVED                         │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                      BOUNDLY VALIDATION                         │
│  - #[Validation] attributes validate input                      │
│  - Reject invalid data before processing                        │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                        INSERT/UPDATE                            │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │
│  │ #[Hashed]   │→ │ Hash value  │→ │ Store in DB (irreversible)│ │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘ │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────────┐ │
│  │ #[Encrypted]│→ │ Encrypt AES │→ │ Store in DB (encrypted)   │ │
│  └─────────────┘  └─────────────┘  └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                           SELECT                                 │
│  - #[Encrypted] values are automatically decrypted              │
│  - #[Hashed] values remain hashed (cannot decrypt)             │
│  - #[Hidden] values are stripped from response                  │
└─────────────────────────────────────────────────────────────────┘
                                │
                                ▼
┌─────────────────────────────────────────────────────────────────┐
│                      API RESPONSE                               │
│  - Clean, safe data returned to client                         │
│  - No passwords, encrypted values, or hidden fields             │
└─────────────────────────────────────────────────────────────────┘

📋 Security Attributes Quick Reference

Attribute Target Purpose Reversible
#[Hidden] Property Exclude from API responses N/A
#[Encrypted] Property Encrypt at rest in database Yes (with key)
#[Hashed] Property Hash irreversibly No

⚠️ Best Practices

  1. Always use #[Hidden] on passwords - Never expose hash in API
  2. Use #[Encrypted] for PII - Names, addresses, phone numbers
  3. Use #[Hashed] for credentials - Passwords that verify, never display
  4. Rotate encryption keys carefully - Encrypted data will become unreadable
  5. Never commit APP_KEY - Use environment variables

🛡️ Enterprise Security Features

BOUNDLY v0.8.0 includes comprehensive security middleware and services:

Security Middlewares

Middleware Purpose
SecurityHeadersMiddleware X-Frame-Options, HSTS, CSP, X-XSS-Protection
CorsMiddleware Cross-Origin Resource Sharing
RequestSizeLimitMiddleware Protects against large payload attacks
RateLimitMiddleware Per-IP/user rate limiting
BruteForceProtectionMiddleware Login attempt throttling
InputSanitizationMiddleware XSS, SQLi, injection prevention
ApiKeyMiddleware API Key authentication

Security Services

Service Purpose
SecurityLogger Comprehensive audit logging with 16+ event types
BruteForceProtectionService Tracks failed attempts, manages lockouts
InputSanitizer Detects and sanitizes malicious input
OwnershipValidator BOLA/IDOR protection
SecureFileUploader Secure file upload handling

Behavioral Security Attributes

Attribute Purpose
#[ApiKey] Declare API Key authentication requirements
#[ThrottleLogin] Configure login throttling per endpoint
#[Ownership] Define object-level authorization rules

Security Events (logged by SecurityLogger)

  • auth.login.success / auth.login.failed
  • auth.logout, auth.token.expired, auth.token.invalid
  • security.rate_limit.exceeded
  • security.unauthorized, security.forbidden
  • security.brute_force.detected, security.brute_force.blocked
  • security.suspicious_input
  • security.apikey.created, security.apikey.revoked

Next Step: Behavioral-Traits 🛡️

Clone this wiki locally