singleloginsystem/app/Console/Commands/GenerateSamlKeysCommand.php
= 4849736c60 Feat: add intials SAML SSO compatibility.
- SAML public certificate generation
- Authentication using SAML
2026-05-27 05:49:36 +00:00

116 lines
3.2 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
class GenerateSamlKeysCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'saml:generate-keys {--force : Overwrite existing keys}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Generate self-signed SAML private key and public certificate for the IdP';
/**
* Execute the console command.
*/
public function handle(): int
{
$directory = storage_path('app/saml');
$keyPath = "{$directory}/idp.key";
$certPath = "{$directory}/idp.crt";
if (! File::exists($directory)) {
File::makeDirectory($directory, 0755, true);
}
if (File::exists($keyPath) && File::exists($certPath) && ! $this->option('force')) {
$this->info('SAML keys already exist. Use --force to overwrite them.');
return self::SUCCESS;
}
$this->info('Generating SAML keys...');
$config = [
'digest_alg' => 'sha256',
'private_key_bits' => 2048,
'private_key_type' => OPENSSL_KEYTYPE_RSA,
];
// Create keypair
$res = openssl_pkey_new($config);
if (false === $res) {
$this->error('Failed to generate private key. Ensure OpenSSL is configured.');
return self::FAILURE;
}
// Export private key
if (! openssl_pkey_export($res, $privKey)) {
$this->error('Failed to export private key.');
return self::FAILURE;
}
// Generate CSR and self-signed certificate
$dn = [
'countryName' => 'US',
'stateOrProvinceName' => 'California',
'localityName' => 'San Francisco',
'organizationName' => 'Laravel SSO',
'organizationalUnitName' => 'IT Department',
'commonName' => 'laravel-sso-idp',
'emailAddress' => 'admin@sso.local',
];
$csr = openssl_csr_new($dn, $res, ['digest_alg' => 'sha256']);
if (false === $csr) {
$this->error('Failed to create CSR.');
return self::FAILURE;
}
$cert = openssl_csr_sign($csr, null, $res, 3650, ['digest_alg' => 'sha256']); // 10 years validity
if (false === $cert) {
$this->error('Failed to sign certificate.');
return self::FAILURE;
}
if (! openssl_x509_export($cert, $certOut)) {
$this->error('Failed to export certificate.');
return self::FAILURE;
}
// Write files
File::put($keyPath, $privKey);
File::put($certPath, $certOut);
// Update or add .gitignore inside the saml directory
$gitignorePath = "{$directory}/.gitignore";
if (! File::exists($gitignorePath)) {
File::put($gitignorePath, "idp.key\n");
}
$this->info('Keys generated successfully:');
$this->line("- Private Key: {$keyPath}");
$this->line("- Certificate: {$certPath}");
return self::SUCCESS;
}
}