bluetea/crowd-authentication-bundle
Installation Add the bundle via Composer:
composer require bluetea/crowd-authentication-bundle dev-master
Enable the bundle in config/bundles.php (Symfony 4+) or AppKernel.php (Symfony 2/3):
Bluetea\CrowdAuthenticationBundle\BlueteaCrowdAuthenticationBundle::class => ['all' => true],
Configuration
Add Crowd API credentials to config/packages/bluetea_crowd_authentication.yaml (Symfony 4+):
bluetea_crowd_authentication:
base_url: "https://your-crowd-instance/rest/usermanagement/latest"
application: "your_application_key"
password: "your_application_password"
For Symfony 2/3, use config.yml:
bluetea_crowd_authentication:
base_url: "https://your-crowd-instance/rest/usermanagement/latest"
application: "your_application_key"
password: "your_application_password"
Security Configuration
Configure security.yaml (Symfony 4+) or security.yml (Symfony 2/3):
security:
encoders:
Bluetea\CrowdAuthenticationBundle\Crowd\User: plaintext # Crowd uses plaintext passwords via API
providers:
crowd:
id: bluetea_crowd_authentication.security.user.crowd_user_provider
firewalls:
main:
crowd_login:
check_path: /login_check
login_path: /login
First Use Case
Redirect users to Crowd for authentication by adding the crowd_login firewall. Test with:
php bin/console debug:security
Verify the crowd_user_provider is registered.
Authentication Flow
UserInterface via CrowdUserProvider.routing.yml:
_demo_security_check:
path: /login_check
methods: [POST]
User Provider Integration
Extend CrowdUser to include custom fields:
// src/Entity/CrowdUser.php
namespace App\Entity;
use Bluetea\CrowdAuthenticationBundle\Crowd\User as BaseCrowdUser;
class CrowdUser extends BaseCrowdUser {
public function getFullName() {
return $this->getFirstName() . ' ' . $this->getLastName();
}
}
Override the provider in security.yaml:
providers:
crowd:
id: app.security.user.crowd_user_provider # Custom service ID
Role Mapping
Map Crowd groups to Symfony roles in config/packages/security.yaml:
security:
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_CROWD_ADMIN_GROUP]
Override CrowdUserProvider to translate Crowd groups to roles:
// src/Security/CrowdUserProvider.php
public function loadUserByUsername($username) {
$crowdUser = parent::loadUserByUsername($username);
$crowdUser->setRoles($this->mapCrowdGroupsToRoles($crowdUser->getGroups()));
return $crowdUser;
}
API Integration Fetch additional user data from Crowd’s REST API:
// src/Service/CrowdApiClient.php
use Bluetea\CrowdAuthenticationBundle\Client\CrowdClient;
class CrowdApiClient {
private $crowdClient;
public function __construct(CrowdClient $crowdClient) {
$this->crowdClient = $crowdClient;
}
public function getUserDetails($username) {
return $this->crowdClient->getUser($username);
}
}
Register as a service and inject where needed.
config/packages/bluetea_crowd_authentication.yaml and leverage autowiring.CacheInterface).CrowdClient to handle API errors gracefully:
try {
$this->crowdClient->authenticate($username, $password);
} catch (\Exception $e) {
throw new AuthenticationException('Crowd authentication failed: ' . $e->getMessage());
}
CrowdClient in PHPUnit:
$mockClient = $this->createMock(CrowdClient::class);
$mockClient->method('authenticate')->willReturn(true);
$this->container->set('bluetea_crowd_authentication.client.crowd', $mockClient);
Plaintext Passwords
User entity’s setPassword() method handles this (or ignore it if using Crowd as the sole auth source).CrowdUser to skip password checks:
public function getPassword() { return null; } // Disable password verification
public function getSalt() { return null; }
API Rate Limiting
CrowdClient:
use Symfony\Component\HttpClient\RetryableHttpClient;
use Symfony\Contracts\HttpClient\RetryableHttpInterface;
$client = new RetryableHttpClient(
HttpClient::create(),
[
'max_retries' => 3,
'delay' => 100,
]
);
Group Synchronization
// src/Security/CrowdUserProvider.php
private $groupCache = [];
public function loadUserByUsername($username) {
if (!isset($this->groupCache[$username])) {
$this->groupCache[$username] = $this->crowdClient->getGroupsForUser($username);
}
// ...
}
Deprecated Symfony 2/3
symfony/flex recipes or manually patch the bundle.CSRF Protection
// src/Security/CrowdCsrfListener.php
public function handle(Request $request, Response $response, $exception = null) {
if ($request->isMethod('POST') && $request->getPathInfo() === '/login_check') {
$this->csrfTokenManager->getToken('authenticate')->validate($request);
}
}
Enable API Logging
Configure CrowdClient to log requests:
# config/services.yaml
Bluetea\CrowdAuthenticationBundle\Client\CrowdClient:
arguments:
$logger: '@logger'
Check logs for failed API calls:
bin/console debug:config bluetea_crowd_authentication
Test API Connectivity Verify Crowd’s API is reachable:
curl -u "application_key:password" "https://your-crowd-instance/rest/usermanagement/latest/user?username=testuser"
Custom User Data
Extend CrowdUser to include Crowd-specific fields (e.g., active, email):
class CrowdUser extends BaseCrowdUser {
private $email;
private $active;
public function setEmail($email) { $this->email = $email; }
public function getEmail() { return $this->email; }
// ...
}
Override CrowdUserProvider::loadUserByUsername() to populate fields:
$userData = $this->crowdClient->getUser($username);
$user->setEmail($userData['email'] ?? null);
Multi-Tenant Support
Dynamically set base_url or application key per tenant:
# config/packages/bluetea_c
How can I help you explore Laravel packages today?