PHPackages                             beartropy/saml2 - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Authentication &amp; Authorization](/categories/authentication)
4. /
5. beartropy/saml2

ActiveLibrary[Authentication &amp; Authorization](/categories/authentication)

beartropy/saml2
===============

Multi-IDP SAML2 SP integration for Laravel using onelogin/php-saml

0.3.8(1w ago)1247MITPHPPHP ^8.2

Since Jan 16Pushed 1mo agoCompare

[ Source](https://github.com/beartropy/saml2)[ Packagist](https://packagist.org/packages/beartropy/saml2)[ RSS](/packages/beartropy-saml2/feed)WikiDiscussions main Synced today

READMEChangelog (5)Dependencies (28)Versions (22)Used By (0)

🛡️ Beartropy SAML2
==================

[](#️-beartropy-saml2)

**Multi-IDP SAML2 Service Provider integration for Laravel using [onelogin/php-saml](https://github.com/onelogin/php-saml)**

Integrate your Laravel app with multiple Identity Providers (Azure AD, Okta, ADFS, etc.)

 [![Latest Stable Version](https://camo.githubusercontent.com/24ecb206aac2d2f9c61f4c76c44d6b43ecada640970eb32e421bdd49f4cb50af/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6265617274726f70792f73616d6c322e7376673f7374796c653d666c61742d73717561726526636f6c6f723d696e6469676f)](https://packagist.org/packages/beartropy/saml2) [![Total Downloads](https://camo.githubusercontent.com/23a089e0b9c96da724e42da6a63dfb2e0e508933f83bd52c860444cb43b72849/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6265617274726f70792f73616d6c322e7376673f7374796c653d666c61742d73717561726526636f6c6f723d626c7565)](https://packagist.org/packages/beartropy/saml2) [![License](https://camo.githubusercontent.com/9ef8ddc431c07cb005a46c0600d17825b5800a062d5b0926dd179573fe59b80b/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6265617274726f70792f73616d6c323f7374796c653d666c61742d73717561726526636f6c6f723d736c617465)](https://packagist.org/packages/beartropy/saml2)

Features
--------

[](#features)

- 🔐 Configure your Laravel app as a SAML 2.0 Service Provider
- 🏢 Support for multiple Identity Providers (Azure AD, Okta, ADFS, etc.)
- 🖥️ **Web UI** for first-deploy setup and admin management
- 📦 IDP configuration from environment variables or database
- 🔄 Automatic metadata import from IDP URLs
- 🎯 Event-driven authentication (handle login your way)
- ⚙️ Artisan commands for IDP management
- 🌐 English and Spanish translations included

📚 Documentation
---------------

[](#-documentation)

👉 **[Read the full documentation at beartropy.com/saml2](https://beartropy.com/saml2)**

Installation
------------

[](#installation)

```
composer require beartropy/saml2
```

Publish the configuration and run migrations:

```
php artisan vendor:publish --tag=beartropy-saml2-config
php artisan migrate
```

Quick Start
-----------

[](#quick-start)

### Option A: Using the Setup Wizard (Recommended)

[](#option-a-using-the-setup-wizard-recommended)

After installation, simply navigate to:

```
https://your-app.com/saml2/setup

```

The **First-Deploy Setup Wizard** will guide you through:

1. Displaying your SP metadata (Entity ID, ACS URL, Metadata URL) to share with your IDP administrator
2. Configuring your IDP via:
    - **Metadata URL** - Fetch and parse automatically
    - **Paste XML** - Copy/paste metadata from your IDP
    - **Manual Entry** - Enter Entity ID, SSO URL, Certificate manually

> **Note**: The setup wizard requires authentication (since v0.3.0) and is only accessible before the first IDP is configured. After that, use the Admin Panel.

### Option B: Using Artisan Commands

[](#option-b-using-artisan-commands)

#### 1. Configure your Service Provider

[](#1-configure-your-service-provider)

Add to your `.env`:

```
SAML2_SP_ENTITY_ID=https://your-app.com
```

For signed assertions (recommended), generate SP certificates:

```
php artisan saml2:generate-cert
```

#### 2. Add an Identity Provider

[](#2-add-an-identity-provider)

From a metadata URL:

```
php artisan saml2:create-idp azure --from-url=https://login.microsoftonline.com/.../federationmetadata.xml
```

Or interactively:

```
php artisan saml2:create-idp azure --interactive
```

---

Admin Panel
-----------

[](#admin-panel)

Once configured, manage your SAML2 settings through the web-based admin panel:

```
https://your-app.com/saml2/admin

```

### Features

[](#features-1)

FeatureDescription**Dashboard**View SP metadata and list all configured IDPs**Create IDP**Add new Identity Providers with metadata import**Edit IDP**Modify IDP settings (Entity ID, SSO URL, Certificate, etc.)**Attribute Mapping**Configure per-IDP attribute mapping or use global config**Toggle Status**Activate/deactivate IDPs without deleting**Refresh Metadata**Auto-update IDP settings from metadata URL**Delete IDP**Remove an IDP from database### Admin Configuration

[](#admin-configuration)

Customize the admin panel in `config/beartropy-saml2.php`:

```
// Enable/disable admin panel
'admin_enabled' => env('SAML2_ADMIN_ENABLED', true),

// Route prefix (default: /saml2/admin)
'admin_route_prefix' => env('SAML2_ADMIN_PREFIX', 'saml2/admin'),

// Middleware to protect admin routes
'admin_middleware' => ['web', 'auth'],  // Add 'admin' or custom middleware as needed
```

#### Protecting Admin Routes

[](#protecting-admin-routes)

Add your own authorization middleware:

```
// config/beartropy-saml2.php
'admin_middleware' => ['web', 'auth', 'can:manage-saml'],
```

Or use a Gate in your `AuthServiceProvider`:

```
Gate::define('manage-saml', function ($user) {
    return $user->hasRole('admin');
});
```

---

Handle Authentication Events
----------------------------

[](#handle-authentication-events)

Publish a standard listener:

```
php artisan saml2:publish-listener
```

This creates `app/Listeners/HandleSaml2Login.php`:

```
public function handle(Saml2LoginEvent $event): void
{
    // Find or create user
    $user = User::firstOrCreate(
        ['email' => $event->getEmail()],
        ['name' => $event->getName()]
    );

    // Log them in
    Auth::login($user);
}
```

> **Note**: The listener must be registered manually in your `EventServiceProvider` or with the `#[AsListener]` attribute (Laravel 11+). See the [Setup Guide](docs/en/SETUP.md) for details.

---

Integrate with Your Routes
--------------------------

[](#integrate-with-your-routes)

**Simple** - a login link:

```

    Login with Azure AD

```

**Full Integration** - replacing auth routes:

```
// routes/auth.php

Route::middleware('guest')->group(function () {
    if (app()->environment('local')) {
        // Local login for development
        Route::get('/login', [AuthController::class, 'showLogin'])->name('login');
        Route::post('/login', [AuthController::class, 'authenticate']);
    } else {
        // SAML Login - redirects to IDP
        Route::get('/login', function () {
            return redirect()->route('saml2.login', ['idp' => 'your-idp-key']);
        })->name('login');
    }
});

Route::middleware('auth')->group(function () {
    if (app()->environment('local')) {
        Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
    } else {
        // SAML Logout (SLO)
        Route::match(['get', 'post'], '/logout', function () {
            return redirect()->route('saml2.logout');
        })->name('logout');
    }
});
```

---

Artisan Commands
----------------

[](#artisan-commands)

CommandDescription`saml2:create-idp {key}`Create a new IDP`saml2:list-idps`List all configured IDPs`saml2:test-idp {key}`Test IDP configuration`saml2:delete-idp {key}`Delete an IDP`saml2:generate-cert`Generate SP certificates`saml2:refresh-metadata`Refresh IDP metadata from URLs`saml2:publish-listener`Publish standard login listener`saml2:reset-setup`Reset to first-deploy state### Reset Setup Command

[](#reset-setup-command)

If you need to reconfigure from scratch:

```
# Reset setup state only (keeps IDPs)
php artisan saml2:reset-setup

# Reset setup state AND delete all IDPs
php artisan saml2:reset-setup --with-idps
```

After running this, the setup wizard at `/saml2/setup` will be accessible again.

---

Routes
------

[](#routes)

The package registers these routes:

### SAML Routes

[](#saml-routes)

RouteMethodDescription`/saml2/setup`GETFirst-deploy setup wizard`/saml2/login/{idp?}`GETInitiate SSO login`/saml2/acs`POSTGeneric ACS - auto-detects IDP`/saml2/acs/{idp}`POSTACS with explicit IDP key`/saml2/sls/{idp}`GET/POSTSingle Logout Service`/saml2/metadata`GETSP Metadata XML`/saml2/logout/{idp?}`GETInitiate logout### Admin Routes

[](#admin-routes)

RouteMethodDescription`/saml2/admin`GETAdmin dashboard`/saml2/admin/idp/create`GETCreate IDP form`/saml2/admin/idp`POSTStore new IDP`/saml2/admin/idp/{id}`GET/PUTEdit/update IDP`/saml2/admin/idp/{id}`DELETEDelete IDP`/saml2/admin/idp/{id}/toggle`POSTActivate/deactivate`/saml2/admin/idp/{id}/mapping`GET/POSTAttribute mapping editor`/saml2/admin/idp/{id}/refresh`POSTRefresh metadata---

Attribute Mapping
-----------------

[](#attribute-mapping)

Attribute mapping allows you to normalize SAML attributes from different IDPs.

### Global Mapping (Config)

[](#global-mapping-config)

Set default mapping in `config/beartropy-saml2.php`:

```
'attribute_mapping' => [
    'email' => 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress',
    'name' => 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name',
    'first_name' => 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname',
    'last_name' => 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname',
],
```

### Per-IDP Mapping (Admin Panel or Code)

[](#per-idp-mapping-admin-panel-or-code)

Each IDP can have custom mapping that overrides the global config.

**Via Admin Panel:**

1. Go to `/saml2/admin`
2. Click "Mapping" on any IDP
3. Toggle "Use global mapping" off
4. Add your custom field mappings

**Via Code:**

```
use Beartropy\Saml2\Models\Saml2Idp;

$idp = Saml2Idp::where('key', 'azure')->first();
$idp->attribute_mapping = [
    'email' => 'http://schemas.microsoft.com/identity/claims/emailaddress',
    'name' => 'http://schemas.microsoft.com/identity/claims/displayname',
    'roles' => 'http://schemas.microsoft.com/ws/2008/06/identity/claims/groups',
];
$idp->save();
```

### Using Attributes in Your Listener

[](#using-attributes-in-your-listener)

```
public function handle(Saml2LoginEvent $event): void
{
    // Mapped attributes (uses IDP-specific or falls back to global)
    $email = $event->getEmail();              // Shorthand
    $name = $event->getName();                // Shorthand
    $custom = $event->getAttribute('roles');  // Custom mapped field

    // Raw SAML attributes (always available)
    $rawEmail = $event->getRawAttribute('http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress');

    // All data
    $allMapped = $event->attributes;
    $allRaw = $event->rawAttributes;
}
```

---

Configuration Reference
-----------------------

[](#configuration-reference)

### IDP Source

[](#idp-source)

```
// config/beartropy-saml2.php

// 'env' - Single IDP from environment only
// 'database' - Multiple IDPs from database
// 'both' - Check env first, then database
'idp_source' => env('SAML2_IDP_SOURCE', 'database'),
```

### Environment-based IDP

[](#environment-based-idp)

For single IDP setups via `.env`:

```
SAML2_IDP_SOURCE=env
SAML2_IDP_KEY=default
SAML2_IDP_NAME="My IDP"
SAML2_IDP_ENTITY_ID=https://idp.example.com
SAML2_IDP_SSO_URL=https://idp.example.com/sso
SAML2_IDP_SLO_URL=https://idp.example.com/slo
SAML2_IDP_CERT="MIICpDCCAYwCCQ..."
```

### Redirects

[](#redirects)

```
'login_redirect' => env('SAML2_LOGIN_REDIRECT', '/'),
'logout_redirect' => env('SAML2_LOGOUT_REDIRECT', '/'),
'error_redirect' => env('SAML2_ERROR_REDIRECT', '/login'),
```

---

Events
------

[](#events)

### Saml2LoginEvent

[](#saml2loginevent)

Dispatched after successful SAML authentication.

**Properties:**

```
$event->idpKey       // Key of the authenticating IDP
$event->nameId       // SAML NameID (usually email)
$event->attributes   // Mapped attributes (per config)
$event->rawAttributes // Original SAML attributes
$event->sessionIndex // For SLO
```

**Helper Methods:**

```
$event->getEmail();                    // Get email
$event->getName();                     // Get name
$event->getAttribute('field');          // Get mapped attribute
$event->getAttribute('field', 'default'); // With default
$event->getRawAttribute('saml_uri');    // Get raw SAML attribute
$event->toArray();                      // All data as array
```

### Saml2LogoutEvent

[](#saml2logoutevent)

Dispatched after successful SAML logout.

---

Security
--------

[](#security)

Since v0.3.0, the package ships with secure defaults:

- `wantAssertionsSigned` and `wantMessagesSigned` default to `true`
- Setup wizard requires authentication (`setup_middleware`)
- SAML routes include rate limiting (`throttle:60,1`)
- SSRF protection on metadata fetching (`block_private_metadata_urls`)
- Session regeneration after login (prevents session fixation)
- Open redirect protection on `returnTo` parameters

For signing outgoing requests (recommended), generate SP certificates:

```
php artisan saml2:generate-cert
```

Then enable request signing in your config:

```
'security' => [
    'authnRequestsSigned' => true,
    'logoutRequestSigned' => true,
    'signMetadata' => true,
],
```

---

Internationalization
--------------------

[](#internationalization)

The package includes English and Spanish translations. To publish and customize:

```
php artisan vendor:publish --tag=beartropy-saml2-lang
```

This creates files in `lang/vendor/beartropy-saml2/`.

---

Customizing Views
-----------------

[](#customizing-views)

To customize the setup wizard or admin panel views:

```
php artisan vendor:publish --tag=beartropy-saml2-views
```

This publishes views to `resources/views/vendor/beartropy-saml2/`.

> **Note**: The UI is vanilla HTML/CSS (no Tailwind or Livewire dependencies), so it works with any Laravel stack.

---

Documentation
-------------

[](#documentation)

For more detailed information, please refer to the following guides:

- **[English Documentation](docs/en/README.md)**
- **[Documentación en Español](docs/es/README.md)**

Includes detailed guides for [Configuration](docs/en/CONFIG.md), [Installation](docs/en/INSTALL.md), [Initial Setup](docs/en/SETUP.md), and the [Admin UI](docs/en/UI.md).

---

License
-------

[](#license)

MIT License - see [LICENSE.md](LICENSE.md)

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance96

Actively maintained with recent releases

Popularity18

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~8 days

Recently: every ~20 days

Total

21

Last Release

7d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/222533003?v=4)[beartropy](/maintainers/beartropy)[@beartropy](https://github.com/beartropy)

![](https://www.gravatar.com/avatar/a2e1b494339d1174075516870c7f6f8ddb4aa78e364e5f709fbf4b6c962ac7e0?d=identicon)[smithingdev](/maintainers/smithingdev)

---

Top Contributors

[![beartropy](https://avatars.githubusercontent.com/u/222533003?v=4)](https://github.com/beartropy "beartropy (34 commits)")

---

Tags

laravelSSOsamlSAML2idpsponeloginbeartropy

###  Code Quality

TestsPest

### Embed Badge

![Health badge](/badges/beartropy-saml2/health.svg)

```
[![Health](https://phpackages.com/badges/beartropy-saml2/health.svg)](https://phpackages.com/packages/beartropy-saml2)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M346](/packages/psalm-plugin-laravel)[laravel/cashier

Laravel Cashier provides an expressive, fluent interface to Stripe's subscription billing services.

2.6k29.9M148](/packages/laravel-cashier)[scaler-tech/laravel-saml2

SAML2 Service Provider integration for Laravel applications, based on OneLogin toolkit

282109.9k](/packages/scaler-tech-laravel-saml2)[api-platform/laravel

API Platform support for Laravel

58171.6k14](/packages/api-platform-laravel)[codegreencreative/laravel-samlidp

Make your PHP Laravel application an Identification Provider using SAML 2.0. This package allows you to implement your own Identification Provider (idP) using the SAML 2.0 standard to be used with supporting SAML 2.0 Service Providers (SP).

265842.7k1](/packages/codegreencreative-laravel-samlidp)[fleetbase/core-api

Core Framework and Resources for Fleetbase API

1235.9k20](/packages/fleetbase-core-api)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
