ecphp/cas-bundle
ecphp/cas-bundle integrates CAS (Central Authentication Service) single sign-on into Symfony applications. It bundles configuration for CAS authentication, user handling, and related services so Symfony apps can add CAS login quickly. Part of the ECphp project, with full docs available.
Installation
composer require ecphp/cas-bundle
Add to config/bundles.php:
return [
// ...
Ecphp\CasBundle\EcphpCasBundle::class => ['all' => true],
];
Configuration
Update config/packages/ecphp_cas.yaml:
ecphp_cas:
client:
cas_server_url: 'https://your-cas-server/cas'
authentication_url: '/cas/login'
validation_url: '/cas/serviceValidate'
logout_url: '/cas/logout'
user:
class: App\Entity\User
property: username
First Use Case Secure a route with CAS authentication:
# config/packages/security.yaml
security:
firewalls:
main:
pattern: ^/
cas:
entry_point: cas_authentication_entry_point
provider: cas_user_provider
config/packages/ecphp_cas.yaml (core settings)src/Security/CasUserProvider.php (custom user mapping)src/Security/CasAuthenticationEntryPoint.php (custom entry point)// In a controller or event subscriber
use Ecphp\CasBundle\Security\CasUserProvider;
// Fetch authenticated user
$user = $this->get('security.token_storage')->getToken()->getUser();
if ($user instanceof CasUserInterface) {
$casUser = $this->get(CasUserProvider::class)->loadUserByUsername($user->getUsername());
// Custom logic with CAS attributes
}
Access CAS-provided attributes:
$attributes = $user->getAttributes();
$email = $attributes->get('email') ?? null;
Extend CasUserProvider to map CAS responses to your user model:
use Ecphp\CasBundle\Security\CasUserProvider as BaseCasUserProvider;
class CustomCasUserProvider extends BaseCasUserProvider
{
public function loadUserByUsername($username)
{
$casUser = parent::loadUserByUsername($username);
$user = $this->userRepository->findOneBy(['username' => $username]);
if (!$user) {
$user = $this->userRepository->createNew();
$user->setUsername($username);
$user->setEmail($casUser->getAttributes()->get('email'));
$this->userRepository->save($user);
}
return $user;
}
}
# config/packages/security.yaml
security:
firewalls:
main:
pattern: ^/
cas:
logout:
invalidate_session: true
post_logout_redirect: /logout-success
cas_authenticator in your firewall configuration.UserCheckerInterface for post-authentication checks:
public function checkPostAuth(UserInterface $user)
{
if (!$user->hasAttribute('isActive')) {
throw new DisabledException('Account is disabled.');
}
}
// In a voter
public function vote(TokenInterface $token, $object, array $attributes)
{
$user = $token->getUser();
$requiredRole = $attributes[0];
if ($user->getAttributes()->has('roles')) {
$userRoles = $user->getAttributes()->get('roles');
return in_array($requiredRole, $userRoles, true);
}
return false;
}
Enable debug mode in config/packages/ecphp_cas.yaml:
ecphp_cas:
debug: true
CORS Issues with CAS Server
# config/packages/ecphp_cas.yaml
ecphp_cas:
client:
allowed_origins: ['https://your-frontend.com']
Attribute Parsing Failures
CasUser::getAttributes() to handle custom formats:
public function getAttributes()
{
if ($this->attributes === null) {
$this->attributes = new AttributesCollection(
json_decode($this->rawAttributes, true)
);
}
return $this->attributes;
}
Session Fixation
# config/packages/security.yaml
security:
firewalls:
main:
cas:
regenerate_session: true
Proxy Server Issues
trusted_proxies is configured:
# config/packages/framework.yaml
framework:
trusted_proxies:
- 192.168.0.0/16
Enable Verbose Logging
# config/packages/ecphp_cas.yaml
ecphp_cas:
debug: true
logging:
level: debug
Inspect CAS Responses
serviceValidate POST request.Test with a Mock CAS Server
URL Paths Must Match Exactly
authentication_url, validation_url, and logout_url match your CAS server’s endpoints exactly (including trailing slashes).HTTPS Requirements
# config/packages/framework.yaml
framework:
router:
http_port: 80
https_port: 443
redirect_http_to_https: true
User Provider Overrides
CasUserProvider, ensure your custom provider is registered as a service:
# config/services.yaml
services:
App\Security\CustomCasUserProvider:
tags: ['security.user_provider']
Custom Attribute Handlers
Ecphp\CasBundle\Security\AttributeHandlerInterface to transform raw attributes:
class CustomAttributeHandler implements AttributeHandlerInterface
{
public function handle(array $attributes, UserInterface $user)
{
$attributes['normalized_email'] = strtolower($attributes['email'] ?? '');
return $attributes;
}
}
Register in config/packages/ecphp_cas.yaml:
ecphp_cas:
attribute_handlers:
- App\Security\CustomAttributeHandler
Event Listeners
use Ecphp\CasBundle\Event\CasEvents;
use Symfony\Component\EventDispatcher\GenericEvent;
$dispatcher->addListener(CasEvents::AUTHENTICATION_SUCCESS, function (GenericEvent $event) {
$user = $event->getSubject();
// Custom logic on successful auth
});
Custom Entry Point
use Ecphp\CasBundle\Security\CasAuthenticationEntryPoint;
class CustomCasEntryPoint extends CasAuthenticationEntryPoint
{
public function start(Request $request = null, ?string $message = null)
{
return new RedirectResponse('/custom-cas-login');
}
}
Register in config/packages/security.yaml:
security:
firewalls:
main:
cas:
entry_point: custom_cas_entry_point
How can I help you explore Laravel packages today?