workos/workos-php
Official WorkOS PHP SDK for integrating SSO, Directory Sync, Admin Portal, Magic Links, and more. Configure with your WorkOS API key and client ID to access the WorkOS API from PHP applications via a convenient, maintained client.
The WorkOS PHP SDK (v5+) aligns well with Laravel’s dependency injection (DI) container, service layer pattern, and event-driven architecture. Key strengths:
$workos->sso(), $workos->userManagement()) map cleanly to Laravel’s facade/manager pattern (e.g., Auth::guard()).DateTimeImmutable, enums) integrate seamlessly with Laravel’s Eloquent and API resource abstractions.Http::macro()) and middleware stack (e.g., retries, logging).WORKOS_API_KEY, WORKOS_CLIENT_ID) aligns with Laravel’s .env conventions.Potential friction points:
WorkOS::setApiKey()) conflict with Laravel’s explicit DI. These should be deprecated in favor of container binding.SessionManager) requires manual cookie handling, which may need Laravel’s session middleware or encrypted cookies integration.| Component | Feasibility | Notes |
|---|---|---|
| Authentication (SSO) | High | Works with Laravel’s session drivers and auth guards. |
| User Management | High | Can extend Laravel’s User model or use API resources for responses. |
| Directory Sync | Medium | Requires queue workers for async jobs (Laravel’s bus:work). |
| Admin Portal | High | Can embed WorkOS’s iframe or proxy routes via Laravel’s middleware. |
| Webhooks | High | Laravel’s route model binding + signed middleware for validation. |
| Multi-Factor Auth (MFA) | High | Integrates with Laravel’s auth pipelines (e.g., MustVerifyEmail). |
Critical dependencies:
Http client already uses Guzzle, so no additional overhead.| Risk Area | Severity | Mitigation |
|---|---|---|
| Breaking changes (v4→v5) | High | Test migration with Laravel’s phpunit + mock WorkOS client. |
| Session cookie handling | Medium | Use Laravel’s encrypted cookies or session drivers for security. |
| Rate limiting | Low | Leverage Laravel’s throttle middleware for API calls. |
| Webhook signature validation | Medium | Implement Laravel’s signed middleware or a custom validator. |
| Beta features | Low | Pin to stable versions (^5.0) and monitor WorkOS’s changelog. |
Key questions for the team:
SessionManager or build a custom WorkosGuard?signed middleware or a custom WorkosWebhookMiddleware?Log facade or use a custom monolog handler?| Laravel Component | WorkOS SDK Integration | Example |
|---|---|---|
| Service Container | Bind WorkOS client as a singleton or context-bound instance. |
```php |
| // app/Providers/AppServiceProvider.php | ||
| $this->app->singleton(WorkOS::class, fn() => new WorkOS( |
apiKey: config('services.workos.key'),
clientId: config('services.workos.client_id')
));
| **Facades** | Create a `Workos` facade for fluent access (optional). | ```php
// app/Facades/Workos.php
public static function sso() { return app(WorkOS::class)->sso(); }
``` |
| **HTTP Client** | Use Laravel’s `Http::macro()` to wrap WorkOS calls (e.g., for retries). | ```php
Http::macro('workos', fn($callback) => Http::withOptions([
'headers' => ['Authorization' => 'Bearer ' . config('services.workos.key')],
])->post('https://api.workos.com/v1/...', $callback));
``` |
| **Middleware** | Validate WorkOS webhook signatures via middleware. | ```php
// app/Http/Middleware/ValidateWorkosWebhook.php
public function handle($request, Closure $next) {
if (!$request->hasHeader('workos-signature')) {
abort(403);
}
// Verify signature...
return $next($request);
}
``` |
| **Queues** | Offload async WorkOS jobs (e.g., directory sync) to Laravel queues. | ```php
// app/Jobs/SyncDirectory.php
public function handle() {
$workos->directorySync()->sync();
}
``` |
| **Events** | Dispatch Laravel events for WorkOS webhooks (e.g., `UserCreated`). | ```php
// Listen to WorkOS webhooks
event(new WorkosWebhookReceived($payload));
``` |
---
### **Migration Path**
1. **Phase 1: Dependency Setup**
- Add to `composer.json`:
```json
"require": {
"workos/workos-php": "^5.0",
"php": "^8.2"
}
```
- Configure `.env`:
```env
WORKOS_API_KEY=sk_test_...
WORKOS_CLIENT_ID=client_...
```
2. **Phase 2: Client Initialization**
- **Option A (Container Binding)**:
```php
// config/services.php
'workos' => [
'key' => env('WORKOS_API_KEY'),
'client_id' => env('WORKOS_CLIENT_ID'),
];
```
```php
// app/Providers/AppServiceProvider.php
$this->app->bind(WorkOS::class, fn() => new WorkOS(
apiKey: config('services.workos.key'),
clientId: config('services.workos.client_id')
));
```
- **Option B (Facade)**:
```php
// app/Facades/Workos.php
public static function userManagement() {
return app(WorkOS::class)->userManagement();
}
```
3. **Phase 3: Feature Migration**
- **SSO**:
```php
// Replace static calls
$url = Workos::sso()->getAuthorizationUrl(...);
```
```php
// New pattern
$url = app(WorkOS::class)->sso()->getAuthorizationUrl(...);
```
- **User Management**:
```php
// Old (v4)
$user = (new UserManagement())->createUser(...);
```
```php
// New (v5)
$user = app(WorkOS::class)->userManagement()->createUsers(...);
```
- **Webhooks**:
```php
// Route
Route::post('/workos/webhook', [WorkosWebhookController::class, 'handle']);
```
```php
// Controller
public function handle(Request $request) {
$payload = $request->json()->all();
// Validate signature (see Middleware above)
event(new WorkosWebhookReceived($payload));
}
```
4. **Phase 4: Testing**
- **Unit Tests**: Mock `WorkOS` client using Laravel’s `Mockery`.
```php
$mockWorkos = Mockery::mock(WorkOS::class);
$mockWorkos->shouldReceive('sso')->andReturnSelf();
$mockWorkos->shouldReceive('getAuthorizationUrl')->andReturn('https://test.com/auth');
$this->app->instance(WorkOS::class, $mockWorkos);
```
- **End-to-End**: Test SSO flows, webhook payloads, and directory sync in staging.
5. **Phase 5: Deployment**
- **Feature Flags**: Use Laravel’s `config('features.workos')` to toggle WorkOS features.
-
How can I help you explore Laravel packages today?