discoverygarden/crayfish-commons-syn
Installation:
composer require discoverygarden/crayfish-commons-syn
Ensure your project meets the PHP 7.2+ requirement.
Configure security.yaml:
Add the package to your config/packages/security.yaml (or equivalent):
security:
enable_authenticator_manager: true
providers:
users_in_memory:
memory: ~
firewalls:
main:
anonymous: false
provider: users_in_memory
custom_authenticators:
- islandora_crayfish_commons_syn.jwt.authenticator
First Use Case:
Test JWT authentication by sending a request with a valid Authorization: Bearer <token> header. Verify the response includes the expected authenticated user data.
Multi-Tenancy Integration:
islandora_crayfish_commons_syn.jwt.authenticator to include tenant ID in token claims (e.g., tenant_id).{
"sub": "user@example.com",
"tenant_id": "tenant_123",
"exp": 1234567890
}
Custom Auth Logic:
// services.yaml
islandora_crayfish_commons_syn.jwt.authenticator:
class: App\Security\CustomSynAuthenticator
arguments: ['@islandora_crayfish_commons_syn.jwt.authenticator']
// src/Security/CustomSynAuthenticator.php
class CustomSynAuthenticator extends AbstractAuthenticator {
public function supports(Request $request) {
// Add tenant-specific checks
return parent::supports($request);
}
}
Token Generation:
JWTManagerInterface to generate tokens with tenant context:
$token = $jwtManager->create([
'sub' => $user->getEmail(),
'tenant_id' => $tenant->getId(),
]);
API Integration:
main firewall. Example controller:
#[Route('/api/protected', methods: ['GET'])]
public function protectedRoute(UserInterface $user, TenantManager $tenantManager) {
$tenant = $tenantManager->findById($user->getTenantId());
return new JsonResponse(['tenant' => $tenant->getName()]);
}
Missing Provider Configuration:
provider under security.firewalls.main will cause silent authentication failures.provider: users_in_memory (or your custom provider) is set.Token Claims Mismatch:
tenant_id), the authenticator may reject it.Caching Issues:
php bin/console lexik_jwt:purge
Firewall Order:
main firewall after another firewall (e.g., dev) may bypass the JWT check.main is listed first in security.firewalls.Enable Debug Mode:
# config/packages/security.yaml
security:
debug: true
Logs authentication events to var/log/dev.log.
Token Validation: Use LexikJWT’s debug command to validate tokens:
php bin/console lexik_jwt:debug-token <your_token_here>
Event Listeners:
Subscribe to security.authentication.success to log tenant-specific events:
// src/EventListener/AuthListener.php
class AuthListener implements EventSubscriberInterface {
public static function getSubscribedEvents() {
return [
SecurityEvents::AUTHENTICATION_SUCCESS => 'onAuthenticationSuccess',
];
}
public function onAuthenticationSuccess(AuthenticationSuccessEvent $event) {
$user = $event->getUser();
$tenantId = $user->getTenantId();
// Log or process tenant-specific logic
}
}
Custom Token Claims:
Extend the authenticator to support additional claims (e.g., roles, permissions):
// src/Security/CustomAuthenticator.php
public function getCredentials(Request $request) {
$token = $this->jwtManager->getUserByToken($request->headers->get('Authorization'));
return [
'username' => $token['sub'],
'tenant_id' => $token['tenant_id'] ?? null,
'roles' => $token['roles'] ?? [],
];
}
Tenant-Aware User Providers: Override the user provider to fetch users based on tenant context:
// src/Security/TenantUserProvider.php
class TenantUserProvider implements UserProviderInterface {
public function loadUserByUsername($username) {
$tenantId = $this->requestStack->getCurrentRequest()->attributes->get('tenant_id');
// Fetch user with tenant context
}
}
Token Refresh:
Implement a custom refresh token endpoint using LexikJWT’s RefreshTokenManagerInterface:
#[Route('/api/token/refresh', methods: ['POST'])]
public function refreshToken(RefreshTokenManagerInterface $refreshTokenManager) {
$refreshToken = $this->request->request->get('refresh_token');
$newToken = $refreshTokenManager->refresh($refreshToken);
return new JsonResponse(['token' => $newToken]);
}
How can I help you explore Laravel packages today?