Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Php Saml Laravel Package

onelogin/php-saml

PHP toolkit for adding SAML 2.0 SSO to your app. Handles login/logout, assertion processing, metadata generation, and signature/encryption validation, with strict security options and PHP 7.3+ (4.x) or older PHP support via branches.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package:

    composer require onelogin/php-saml
    

    Use branch 4.X for PHP 7.3+ or 3.X for PHP 7.0-7.2.

  2. Configure SAML settings: Replace settings_example.php (from the package) with your own config/saml.php:

    return [
        'strict' => true,
        'debug' => env('SAML_DEBUG', false),
        'security' => [
            'nameIdEncrypted' => false,
            'authnRequestsSigned' => true,
            'wantAssertionsSigned' => true,
            'wantAssertionsEncrypted' => false,
            'signatureAlgorithm' => 'sha256',
            'digestAlgorithm' => 'sha256',
        ],
        'sp' => [
            'entityId' => 'https://your-app.test/saml/metadata',
            'assertionConsumerService' => [
                'url' => route('saml.acs'),
                'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
            ],
            'singleLogoutService' => [
                'url' => route('saml.sls'),
                'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
            ],
            'x509cert' => file_get_contents(base_path('storage/saml/sp.crt')),
            'privateKey' => file_get_contents(base_path('storage/saml/sp.key')),
        ],
        'idp' => [
            'entityId' => 'https://idp.example.com/saml/metadata',
            'singleSignOnService' => [
                'url' => 'https://idp.example.com/saml/sso',
                'binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
            ],
            'x509cert' => file_get_contents(base_path('storage/saml/idp.crt')),
        ],
    ];
    
  3. Create routes (routes/saml.php):

    Route::get('/saml/metadata', [SamlController::class, 'metadata'])->name('saml.metadata');
    Route::post('/saml/acs', [SamlController::class, 'acs'])->name('saml.acs');
    Route::post('/saml/sls', [SamlController::class, 'sls'])->name('saml.sls');
    Route::get('/saml/login', [SamlController::class, 'login'])->name('saml.login');
    
  4. First use case: SP-Initiated SSO In your controller:

    use OneLogin\Saml2\Auth;
    
    public function login()
    {
        $settings = config('saml');
        $auth = new Auth($settings);
        return redirect()->to($auth->login());
    }
    

Implementation Patterns

Core Workflows

  1. SP-Initiated SSO:

    • Trigger via Auth::login() → Redirects to IdP.
    • IdP returns to acs.php (or your custom route) with SAML Response.
    • Validate response in acs():
      $auth = new Auth($settings);
      $errors = $auth->validateAuthnResponse();
      if (empty($errors)) {
          $attributes = $auth->getAttributes();
          auth()->loginUsingId($attributes['email'][0]); // Custom logic
          return redirect()->intended('/dashboard');
      }
      return back()->withErrors($errors);
      
  2. IdP-Initiated SSO:

    • IdP redirects to your acs.php with RelayState.
    • Validate and process as above.
  3. Single Logout (SLO):

    • Trigger via Auth::logout() → Redirects to IdP.
    • IdP sends LogoutRequest to your sls.php:
      $auth = new Auth($settings);
      $logoutRequest = $auth->getLogoutRequest();
      return redirect()->to($logoutRequest['url']);
      
    • Handle LogoutResponse in sls():
      $auth = new Auth($settings);
      $errors = $auth->validateLogoutResponse();
      if (empty($errors)) {
          auth()->logout(); // Custom logic
      }
      

Integration Tips

  • Session Handling: Use Laravel’s session to store LastMessageID/LastAssertionID for replay attack prevention:

    session(['last_saml_message_id' => $auth->getLastMessageId()]);
    

    Check on validation:

    if (session('last_saml_message_id') === $auth->getLastMessageId()) {
        abort(403, 'Replay attack detected');
    }
    
  • Metadata: Publish SP metadata via metadata.php:

    $settings = config('saml');
    $metadata = new \OneLogin\Saml2\Metadata($settings);
    return response()->make($metadata->getMetadata(), 200, ['Content-Type' => 'text/xml']);
    
  • Attribute Mapping: Map IdP attributes to Laravel users dynamically:

    $email = $auth->getAttributes()['email'][0] ?? null;
    $user = User::firstOrCreate(['email' => $email]);
    
  • Error Handling: Centralize SAML errors in a middleware:

    public function handle($request, Closure $next)
    {
        try {
            return $next($request);
        } catch (\OneLogin_Saml2_Error $e) {
            return back()->withErrors(['saml' => $e->getMessage()]);
        }
    }
    

Gotchas and Tips

Pitfalls

  1. Certificate Management:

    • Issue: Certificates in vendor/onelogin/php-saml/certs/ are overwritten on composer update.
    • Fix: Store certs in storage/saml/ and reference them in config/saml.php:
      'sp' => [
          'x509cert' => file_get_contents(storage_path('saml/sp.crt')),
          'privateKey' => file_get_contents(storage_path('saml/sp.key')),
      ],
      
  2. Strict Mode:

    • Issue: Forgetting strict: true in production enables insecure defaults (e.g., SHA1).
    • Fix: Enforce in config/saml.php and validate signatures:
      'strict' => env('APP_ENV') === 'production',
      'security' => [
          'signatureAlgorithm' => 'sha256',
          'digestAlgorithm' => 'sha256',
      ],
      
  3. RelayState Validation:

    • Issue: Untrusted RelayState values enable open redirect attacks (CWE-601).
    • Fix: Whitelist allowed URLs:
      $allowedUrls = ['/dashboard', '/profile'];
      if (!in_array($auth->getRelayState(), $allowedUrls)) {
          abort(400, 'Invalid RelayState');
      }
      
  4. Session Fixation:

    • Issue: SAML responses may override Laravel’s session.
    • Fix: Regenerate session ID post-authentication:
      if ($auth->isAuthenticated()) {
          session_regenerate_id(true);
      }
      
  5. IdP Metadata Parsing:

    • Issue: Caching stale IdP metadata causes authentication failures.
    • Fix: Fetch metadata dynamically:
      $idpMetadata = file_get_contents('https://idp.example.com/saml/metadata');
      $settings['idp']['x509cert'] = $this->extractCertFromMetadata($idpMetadata);
      

Debugging Tips

  • Enable Debugging: Set 'debug' => true in config/saml.php to log SAML messages to storage/logs/saml.log.

  • Validate XML: Use OneLogin\Saml2\Utils::xmlErrorLog() to debug malformed SAML responses:

    \OneLogin\Saml2\Utils::xmlErrorLog($samlResponse);
    
  • Test Locally: Use SimpleSAMLphp as a test IdP with self-signed certs.

Extension Points

  1. Custom Assertion Processing: Extend OneLogin\Saml2\Auth to add logic:

    class CustomAuth extends \OneLogin\Saml2\Auth
    {
        public function getUser()
        {
            $attributes = $this->getAttributes();
            return User::where('email', $attributes['email'][0])->first();
        }
    }
    
  2. Hooks for Pre/Post-Validation: Use Laravel events to intercept SAML flows:

    event(new SamlValidating($auth));
    event(new SamlValidated($auth, $errors));
    

3

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime