Installation Add the bundle via Composer:
composer require drupol/cas-bundle
Enable the bundle in config/bundles.php:
return [
// ...
Drupol\CasBundle\DrupolCasBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console drupol:cas:install
Update config/packages/drupol_cas.yaml with your CAS server details:
drupol_cas:
client:
id: "your_client_id"
secret: "your_client_secret"
server:
url: "https://your-cas-server/cas"
validate_url: "https://your-cas-server/cas/serviceValidate"
proxy_receipt_url: "https://your-cas-server/cas/proxy"
logout:
url: "https://your-cas-server/cas/logout"
First Use Case: Secure a Route
Annotate a controller method or route with @Secure:
use Drupol\CasBundle\Annotation\Secure;
class MyController extends AbstractController
{
#[Secure]
public function secureAction(): Response
{
return $this->render('secure.html.twig');
}
}
Or via YAML:
# config/routes.yaml
secure_route:
path: /secure
controller: App\Controller\MyController::secureAction
requirements:
_cas: true
Login Flow
Redirect users to CAS via the login route:
return $this->redirectToRoute('drupol_cas_login');
The bundle handles the CAS callback automatically (default route: drupol_cas_callback).
Proxy Grants (Service Tickets)
For single-sign-on (SSO) across services, use the proxy grant:
drupol_cas:
proxy:
enabled: true
service_url: "https://your-app.example.com"
Access the proxy ticket in your code:
$proxyGrant = $this->get('security.token_storage')->getToken()->getProxyGrant();
Custom Attributes
Extract CAS attributes (e.g., eduPersonPrincipalName) in controllers:
$attributes = $this->get('security.token_storage')->getToken()->getUser()->getAttributes();
$username = $attributes['eduPersonPrincipalName'] ?? null;
config/packages/security.yaml:
firewalls:
main:
pattern: ^/
cas: ~
# Other providers (e.g., form_login) can be combined
config/packages/drupol_cas.yaml:
drupol_cas:
user:
property_mappings:
username: "eduPersonPrincipalName"
email: "mail"
CasAuthenticationSuccessEvent) for custom logic:
// src/EventListener/CasListener.php
public function onCasAuthSuccess(CasAuthenticationSuccessEvent $event)
{
$user = $event->getAuthenticationToken()->getUser();
// Custom logic (e.g., log, update DB)
}
Register the listener in services.yaml:
services:
App\EventListener\CasListener:
tags:
- { name: kernel.event_listener, event: cas.authentication.success, method: onCasAuthSuccess }
CSRF Token Mismatch
INVALID_TICKET if CSRF tokens don’t match.client.id and client.secret in config match the CAS server’s expectations. For stateless setups, disable CSRF checks:
drupol_cas:
client:
csrf: false
Proxy Callback Errors
service_url in config doesn’t match the exact callback URL.https://) and ensure it matches the proxyCallback route:
drupol_cas:
proxy:
service_url: "https://your-app.example.com/_cas/proxyCallback"
Attribute Parsing Failures
// src/Service/CustomAttributeParser.php
use Drupol\CasBundle\Parser\AttributeParserInterface;
class CustomAttributeParser implements AttributeParserInterface
{
public function parse(string $attributes): array
{
// Custom logic (e.g., handle multi-valued attributes)
return [...];
}
}
Register it in services.yaml:
services:
Drupol\CasBundle\Parser\AttributeParserInterface: '@App\Service\CustomAttributeParser'
Enable Verbose Logging
Add to config/packages/monolog.yaml:
handlers:
cas:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.cas.log"
level: debug
channels: ["cas"]
Then enable the channel in drupol_cas.yaml:
drupol_cas:
debug: true
Validate Tickets Manually
Test CAS tickets with curl:
curl -v "https://your-cas-server/cas/serviceValidate?service=https://your-app.example.com&ticket=ST-12345-ABCDE"
Custom User Provider Replace the default user provider:
services:
App\Security\User\CasUserProvider:
arguments:
- '@drupol_cas.user.provider'
tags:
- { name: 'security.user_provider' }
Override Templates Customize login/logout templates by copying from:
vendor/drupol/cas-bundle/Resources/views/
to templates/bundles/drupolcas/.
Add Custom Routes Extend the bundle’s routing loader:
// src/DependencyInjection/Compiler/CasRoutePass.php
public function process(ContainerBuilder $container)
{
$loader = $container->getDefinition('drupol_cas.routing.loader');
$loader->addMethodCall('addRoute', ['custom_route', '/custom-path']);
}
How can I help you explore Laravel packages today?