aerialship/saml-sp-bundle
Symfony2 bundle providing a SAML 2.0 Service Provider: authenticate against one or more IdPs with SSO (AuthnRequest), Single Logout, federation metadata, discovery service, and HTTP-POST/Redirect bindings. Legacy; newer version exists.
Installation
composer require aerialship/saml-sp-bundle
Add the bundle to app/AppKernel.php (Symfony 2.x):
new Aerialship\SamlSpBundle\AerialshipSamlSpBundle(),
Configuration
Update app/config/config.yml with your IdP metadata (XML or URL) and SP settings:
aerialship_saml_sp:
sp:
entity_id: "https://your-app.com/saml"
assertion_consumer_service:
url: "https://your-app.com/login/saml/check"
single_sign_on_service:
url: "https://your-app.com/login/saml"
name_id_format: "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
idp:
metadata: "https://idp.example.com/metadata" # or local XML file path
single_sign_on_service:
url: "https://idp.example.com/sso"
single_logout_service:
url: "https://idp.example.com/logout"
First Use Case: Login Flow
# app/config/routing.yml
saml_login:
path: /login/saml
defaults: { _controller: AerialshipSamlSpBundle:Default:initiate }
saml_check:
path: /login/saml/check
defaults: { _controller: AerialshipSamlSpBundle:Default:check }
Authentication Flow
/login/saml.User object. Override Aerialship\SamlSpBundle\Security\Authentication\Provider\SamlProvider to customize user mapping:
public function retrieveUser($credentials)
{
$attributes = $credentials['attributes'];
$email = $attributes['email'][0] ?? null;
return $this->userManager->findUserBy(['email' => $email]);
}
User Provisioning
SamlUserProvider to map SAML attributes to your user entity. Example:
// src/Acme/UserBundle/Resources/config/services.yml
services:
acme.user.saml_provider:
class: Acme\UserBundle\Security\User\SamlUserProvider
arguments: ['@doctrine.orm.entity_manager', 'Acme\UserBundle\Entity\User']
Logout Handling
saml_logout:
path: /logout/saml
defaults: { _controller: AerialshipSamlSpBundle:Default:logout }
Aerialship\SamlSpBundle\Event\LogoutEvent.security.yml:
firewalls:
main:
saml: true
form_login: ~
logout: ~
attribute_map config to rename/transform attributes:
aerialship_saml_sp:
attribute_map:
email: "mail"
first_name: "givenName"
last_name: "sn"
$metadata = new \Aerialship\SamlSpBundle\Metadata\IdPMetaData();
$metadata->loadFromUrl('https://idp.example.com/metadata');
Metadata Validation
curl -v https://idp.example.com/metadata
$metadata = new \Aerialship\SamlSpBundle\Metadata\IdPMetaData();
$metadata->loadFromUrl('...');
var_dump($metadata->getErrors());
Clock Skew
config.yml:
aerialship_saml_sp:
security:
clock_skew: 60 # Allow 60-second skew
Attribute Handling
['email' => ['user@example.com', 'backup@example.com']]). Normalize in your SamlProvider:
$email = reset($attributes['email'] ?? []);
HTTPS Requirements
trusted_proxies in Symfony to handle load balancers:
framework:
trusted_proxies: ["10.0.0.0/8", "192.168.0.0/16"]
Enable Verbose Logging
Add to config.yml:
aerialship_saml_sp:
debug: true
Logs appear in app/logs/dev.log.
Dump SAML Messages
Use the SamlDebugController (if enabled) to inspect raw SAML requests/responses:
_saml_debug:
path: /_saml/debug
defaults: { _controller: AerialshipSamlSpBundle:Debug:dump }
Test with SimpleSAMLphp Use SimpleSAMLphp as a test IdP for development.
Custom Authentication Providers
Extend SamlProvider to add logic (e.g., role mapping):
class CustomSamlProvider extends \Aerialship\SamlSpBundle\Security\Authentication\Provider\SamlProvider
{
public function authenticate(TokenInterface $token)
{
$user = parent::authenticate($token);
$user->addRole('ROLE_SAML_USER');
return new UsernamePasswordToken($user->getUsername(), null, 'main', $user->getRoles());
}
}
Event Listeners
Subscribe to SAML events (e.g., SamlResponseEvent) to modify behavior:
// src/Acme/UserBundle/EventListener/SamlListener.php
class SamlListener
{
public function onSamlResponse(SamlResponseEvent $event)
{
if ($event->getResponse()->getStatus() === 'Success') {
$event->setUserData(['custom' => 'value']);
}
}
}
Register in services.yml:
services:
acme.saml_listener:
class: Acme\UserBundle\EventListener\SamlListener
tags:
- { name: kernel.event_listener, event: saml.response, method: onSamlResponse }
Metadata Generation Generate SP metadata dynamically:
$metadata = new \Aerialship\SamlSpBundle\Metadata\SpMetaData();
$metadata->setEntityId('https://your-app.com/saml');
$metadata->setAssertionConsumerService('https://your-app.com/login/saml/check');
file_put_contents('metadata/sp-metadata.xml', $metadata->generate());
NameID Format
Ensure name_id_format in config.yml matches what the IdP expects (e.g., urn:oasis:names:tc:SAML:2.0:nameid-format:persistent).
Signature Validation Disable signature validation only for testing (not production):
aerialship_saml_sp:
security:
validate_signatures: false
Legacy Symfony Versions
This bundle is deprecated for Symfony 3.0+. Migrate to lightSAML/SpBundle if using newer Symfony versions.
```markdown
### Upgrade Note
- If using Symfony 2.7+, consider migrating to the [new `lightSAML/SpBundle`](https://github.com/lightSAML/SpBundle) for active maintenance.
How can I help you explore Laravel packages today?