---
description: Security architecture, authentication, authorization patterns, and enhanced form component security
globs: app/Policies/*.php, app/View/Components/Forms/*.php, app/Http/Middleware/*.php, resources/views/**/*.blade.php
alwaysApply: true
---
# Coolify Security Architecture & Patterns
## Security Philosophy
Coolify implements **defense-in-depth security** with multiple layers of protection including authentication, authorization, encryption, network isolation, and secure deployment practices.
## Authentication Architecture
### Multi-Provider Authentication
- **[Laravel Fortify](mdc:config/fortify.php)** - Core authentication scaffolding (4.9KB, 149 lines)
- **[Laravel Sanctum](mdc:config/sanctum.php)** - API token authentication (2.4KB, 69 lines)
- **[Laravel Socialite](mdc:config/services.php)** - OAuth provider integration
### OAuth Integration
- **[OauthSetting.php](mdc:app/Models/OauthSetting.php)** - OAuth provider configurations
- **Supported Providers**:
- Google OAuth
- Microsoft Azure AD
- Clerk
- Authentik
- Discord
- GitHub (via GitHub Apps)
- GitLab
### Authentication Models
```php
// User authentication with team-based access
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
protected $fillable = [
'name', 'email', 'password'
];
protected $hidden = [
'password', 'remember_token'
];
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
public function teams(): BelongsToMany
{
return $this->belongsToMany(Team::class)
->withPivot('role')
->withTimestamps();
}
public function currentTeam(): BelongsTo
{
return $this->belongsTo(Team::class, 'current_team_id');
}
}
```
## Authorization & Access Control
### Enhanced Form Component Authorization System
Coolify now features a **centralized authorization system** built into all form components (`Input`, `Select`, `Textarea`, `Checkbox`, `Button`) that automatically handles permission-based UI control.
#### Component Authorization Parameters
```php
// Available on all form components
public ?string $canGate = null; // Gate name (e.g., 'update', 'view', 'delete')
public mixed $canResource = null; // Resource to check against (model instance)
public bool $autoDisable = true; // Auto-disable if no permission (default: true)
```
#### Smart Authorization Logic
```php
// Automatic authorization handling in component constructor
if ($this->canGate && $this->canResource && $this->autoDisable) {
$hasPermission = Gate::allows($this->canGate, $this->canResource);
if (! $hasPermission) {
$this->disabled = true;
// For Checkbox: also disables instantSave
}
}
```
#### Usage Examples
**✅ Recommended Pattern (Single Line):**
```html
Save Configuration
```
**❌ Old Pattern (Verbose, Deprecated):**
```html
@can('update', $application)
Save
@else
@endcan
```
#### Advanced Usage with Custom Control
**Custom Authorization Logic:**
```html
```
**Multiple Permission Checks:**
```html
```
#### Supported Gates and Resources
**Common Gates:**
- `view` - Read access to resource
- `update` - Modify resource configuration
- `deploy` - Deploy/restart resource
- `delete` - Remove resource
- `createAnyResource` - Create new resources
**Resource Types:**
- `Application` - Application instances
- `Service` - Docker Compose services
- `Server` - Server instances
- `Project` - Project containers
- `Environment` - Environment contexts
- `Database` - Database instances
#### Benefits
**🔥 Massive Code Reduction:**
- **90% less code** for authorization-protected forms
- **Single line** instead of 6-12 lines per form element
- **No more @can/@else blocks** cluttering templates
**🛡️ Consistent Security:**
- **Unified authorization logic** across all form components
- **Automatic disabling** for unauthorized users
- **Smart behavior** (like disabling instantSave on checkboxes)
**🎨 Better UX:**
- **Consistent disabled styling** across all components
- **Proper visual feedback** for restricted access
- **Clean, professional interface**
#### Implementation Details
**Component Enhancement:**
```php
// Enhanced in all form components
use Illuminate\Support\Facades\Gate;
public function __construct(
// ... existing parameters
public ?string $canGate = null,
public mixed $canResource = null,
public bool $autoDisable = true,
) {
// Handle authorization-based disabling
if ($this->canGate && $this->canResource && $this->autoDisable) {
$hasPermission = Gate::allows($this->canGate, $this->canResource);
if (! $hasPermission) {
$this->disabled = true;
// For Checkbox: $this->instantSave = false;
}
}
}
```
**Backward Compatibility:**
- All existing form components continue to work unchanged
- New authorization parameters are optional
- Legacy @can/@else patterns still function but are discouraged
### Custom Component Authorization Patterns
When dealing with **custom Alpine.js components** or complex UI elements that don't use the standard `x-forms.*` components, manual authorization protection is required since the automatic `canGate` system only applies to enhanced form components.
#### Common Custom Components Requiring Manual Protection
**⚠️ Custom Components That Need Manual Authorization:**
- Custom dropdowns/selects with Alpine.js
- Complex form widgets with JavaScript interactions
- Multi-step wizards or dynamic forms
- Third-party component integrations
- Custom date/time pickers
- File upload components with drag-and-drop
#### Manual Authorization Pattern
**✅ Proper Manual Authorization:**
```html
@can('update', $resource)
@else
@endcan
```
#### Implementation Checklist
When implementing authorization for custom components:
**🔍 1. Identify Custom Components:**
- Look for Alpine.js `x-data` declarations
- Find components not using `x-forms.*` prefix
- Check for JavaScript-heavy interactions
- Review complex form widgets
**🛡️ 2. Wrap with Authorization:**
- Use `@can('gate', $resource)` / `@else` / `@endcan` structure
- Provide full functionality in the `@can` block
- Create disabled/readonly version in the `@else` block
**🎨 3. Design Disabled State:**
- Apply `readonly disabled` attributes to inputs
- Add `opacity-50 cursor-not-allowed` classes for visual feedback
- Remove interactive JavaScript behaviors
- Show current value or appropriate placeholder
**🔒 4. Backend Protection:**
- Ensure corresponding Livewire methods check authorization
- Add `$this->authorize('gate', $resource)` in relevant methods
- Validate permissions before processing any changes
#### Real-World Examples
**Custom Date Range Picker:**
```html
@can('update', $application)