Security Advanced Auth - v1.0.0
Custom SSO Providers
SsoManager itself is concrete — what's pluggable is the per-type implementation. The shipped SamlServiceProvider, OidcClient, and LdapAuthenticator are configuration-driven wrappers around external libraries. To swap in your own library or a custom protocol, register a new type.
Adding a type
use ArtisanPackUI\SecurityAdvancedAuth\Authentication\Sso\SsoManager;
$this->app->afterResolving( SsoManager::class, function ( SsoManager $manager ): void {
$manager->extend( 'kerberos', \App\Auth\Sso\KerberosProvider::class );
} );
The provider class must implement SsoProviderInterface:
interface SsoProviderInterface
{
public function getName(): string;
public function getLoginUrl( SsoConfiguration $config, array $options = [] ): string;
public function handleCallback( SsoConfiguration $config, Request $request ): SsoUser;
public function getLogoutUrl( SsoConfiguration $config, array $options = [] ): ?string;
public function handleLogout( SsoConfiguration $config, Request $request ): bool;
public function getMetadata( SsoConfiguration $config ): ?string;
}
Configurable IdP
Each IdP is an SsoConfiguration row with type, slug, and a free-form config JSON. Your provider class reads the config to know IdP-specific details (endpoints, certificates, secrets).
SsoConfiguration::create([
'slug' => 'corp-kerberos',
'name' => 'Corporate Kerberos',
'type' => 'kerberos',
'config' => [
'realm' => 'CORP.EXAMPLE.COM',
'kdc' => 'krb.corp.example.com',
// ... whatever your provider needs
],
'is_enabled' => true,
]);
Login URL: /auth/sso/corp-kerberos/login automatically routes through your KerberosProvider.
Bring-your-own SAML library
The shipped SamlServiceProvider is intentionally light. To use onelogin/php-saml (or any other SAML library):
namespace App\Auth\Sso;
use ArtisanPackUI\SecurityAdvancedAuth\Authentication\Contracts\SsoProviderInterface;
use ArtisanPackUI\SecurityAdvancedAuth\Authentication\Sso\SsoUser;
use ArtisanPackUI\SecurityAdvancedAuth\Models\SsoConfiguration;
use Illuminate\Http\Request;
use OneLogin\Saml2\Auth as Saml2Auth;
class OneLoginSamlProvider implements SsoProviderInterface
{
public function getName(): string { return 'saml'; }
public function handleCallback( SsoConfiguration $config, Request $request ): SsoUser
{
$auth = new Saml2Auth( $config->config );
$auth->processResponse();
if ( ! $auth->isAuthenticated() ) {
throw new \RuntimeException( 'SAML authentication failed: ' . implode( ', ', $auth->getErrors() ) );
}
return new SsoUser(
id: $auth->getNameId(),
email: $auth->getAttribute('email')[0] ?? null,
attributes: $auth->getAttributes(),
);
}
// ... other interface methods
}
Register it as the new saml type (replaces the shipped one for that slug):
$manager->extend( 'saml', OneLoginSamlProvider::class );
Multiple IdPs of the same type
The slug identifies the IdP, not the type. You can have 5 OIDC IdPs (okta, auth0, azure-ad, keycloak, custom-oidc) all using the same OidcClient provider — each with its own SsoConfiguration row carrying different config.
The slug becomes the URL path: /auth/sso/okta/login vs /auth/sso/auth0/login.
Bypassing the bundled controllers
If your SSO flow doesn't fit the standard redirect-callback pattern, disable the routes and wire your own controllers that call the manager directly:
$loginUrl = app(SsoManager::class)->login('corp-okta');
return redirect()->away($loginUrl);