-
Notifications
You must be signed in to change notification settings - Fork 0
Security Attributes
BOUNDLY provides declarative security attributes to protect sensitive data, control access, and ensure data integrity at the attribute level.
Infrastructure\FrameworkCore\Attributes\Security\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.
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_KEYmust be set in your.envfile - 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)
-- aW5zZXJ0LXZlcnktbG9uZy1hcGkta2V5LXZhbHVlAPI Behavior:
// GET /api/integrations/1
{
"id": 1,
"name": "Stripe",
"apiKey": "sk_live_abc123...", // Automatically decrypted
"webhookSecret": "whsec_xyz789..." // Automatically decrypted
}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.H7pB7p4ZZ7Z7LKImportant Notes:
- Hashing is one-way - You cannot retrieve the original value
- Hashes on INSERT - Automatically hashes when creating records
- Hashes on UPDATE - Only if the value has changed
-
Verification - Use
Hash::check($plain, $hashed)to verify:
if (Hash::check($request->password, $user->password)) {
// Password is correct
}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;
}┌─────────────────────────────────────────────────────────────────┐
│ 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 │
└─────────────────────────────────────────────────────────────────┘
| 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 |
-
Always use
#[Hidden]on passwords - Never expose hash in API -
Use
#[Encrypted]for PII - Names, addresses, phone numbers -
Use
#[Hashed]for credentials - Passwords that verify, never display - Rotate encryption keys carefully - Encrypted data will become unreadable
-
Never commit
APP_KEY- Use environment variables
Next Step: Behavioral-Traits 🛡️