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

Ssl Certificate Laravel Package

spatie/ssl-certificate

Retrieve and validate SSL/TLS certificates for any host in PHP. This package fetches certificate details like issuer, validity dates, and expiration status, making it easy to monitor domains and detect upcoming certificate issues in Laravel apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require spatie/ssl-certificate
    

    Add the namespace to your composer.json autoload or use it directly in your code.

  2. First Use Case: Fetch and validate a certificate for a domain:

    use Spatie\SslCertificate\SslCertificate;
    
    $certificate = SslCertificate::createForHostName('example.com');
    $isValid = $certificate->isValid();
    
  3. Key Methods to Explore:

    • expirationDate(): Get the expiration date as a Carbon instance.
    • daysUntilExpirationDate(): Days remaining until expiration.
    • getIssuer(): Issuer of the certificate (e.g., "Let's Encrypt Authority X3").
    • getDomain(): Primary domain covered by the certificate.

Where to Look First

  • README.md: Focus on the "Usage" section for core functionality.
  • Exceptions: Review Spatie\SslCertificate\Exceptions for error handling (e.g., CouldNotDownloadCertificate).
  • Fluent Interface: Use SslCertificate::download()->forHost('example.com') for custom configurations (ports, IPs, socket options).

Implementation Patterns

Common Workflows

  1. Certificate Validation in Laravel Controllers:

    public function checkCertificate(Request $request, string $domain)
    {
        $certificate = SslCertificate::createForHostName($domain);
        if (!$certificate->isValid()) {
            return response()->json(['error' => 'Certificate expired'], 400);
        }
        return response()->json(['valid' => true, 'expires' => $certificate->expirationDate()]);
    }
    
  2. Batch Validation for Multiple Domains:

    $domains = ['example.com', 'api.example.com'];
    $results = collect($domains)->map(fn($domain) => [
        'domain' => $domain,
        'valid' => SslCertificate::createForHostName($domain)->isValid(),
    ]);
    
  3. Scheduled Certificate Expiry Alerts:

    // In a Laravel scheduled task (app/Console/Kernel.php)
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('check:certificates')->daily();
    }
    
    // Command to check critical certificates
    public function handle()
    {
        $criticalDomains = config('certificates.critical');
        foreach ($criticalDomains as $domain) {
            $cert = SslCertificate::createForHostName($domain);
            if ($cert->daysUntilExpirationDate() < 30) {
                Log::warning("Certificate for {$domain} expires in {$cert->daysUntilExpirationDate()} days");
            }
        }
    }
    
  4. Custom Socket Context for Proxies:

    $certificate = SslCertificate::download()
        ->withSocketContextOptions([
            'ssl' => [
                'verify_peer' => false, // Bypass for internal services
                'verify_peer_name' => false,
            ],
        ])
        ->forHost('internal-service.local');
    
  5. Fingerprint Comparison for Security Audits:

    $expectedFingerprint = 'SHA256:...';
    $actualFingerprint = SslCertificate::createForHostName('secure.example.com')->getFingerprintSha256();
    if ($expectedFingerprint !== $actualFingerprint) {
        throw new \RuntimeException('Certificate fingerprint mismatch!');
    }
    

Integration Tips

  • Laravel Service Providers: Bind the certificate checker to the container for dependency injection:

    $this->app->bind(SslCertificate::class, function () {
        return new SslCertificate();
    });
    
  • Form Request Validation: Validate certificate validity in a FormRequest:

    public function rules()
    {
        return [
            'domain' => [
                'required',
                function ($attribute, $value, $fail) {
                    $cert = SslCertificate::createForHostName($value);
                    if (!$cert->isValid()) {
                        $fail('The certificate for the domain is invalid.');
                    }
                },
            ],
        ];
    }
    
  • API Rate Limiting: Use certificate validation to rate-limit API calls from specific domains:

    $cert = SslCertificate::createForHostName($request->getHost());
    $rateLimiter->hit($cert->getFingerprintSha256());
    
  • Caching Certificates: Cache certificate data to avoid repeated network calls (e.g., in a queue worker):

    $cacheKey = "certificate:{$domain}";
    $certificate = Cache::remember($cacheKey, now()->addHours(1), function () use ($domain) {
        return SslCertificate::createForHostName($domain);
    });
    

Gotchas and Tips

Pitfalls

  1. Certificate Authority Trust:

    • Issue: The package does not verify if the certificate is signed by a trusted CA (as noted in the README).
    • Workaround: Use PHP’s built-in stream_context_create() with verify_peer and cafile options for CA validation:
      $context = stream_context_create([
          'ssl' => [
              'verify_peer' => true,
              'cafile' => '/path/to/cacert.pem',
          ],
      ]);
      $certificate = SslCertificate::download()
          ->withSocketContextOptions(['ssl' => ['verify_peer' => true]])
          ->forHost('example.com');
      
  2. Wildcard Domains:

    • Issue: isValid('example.com') returns false for a wildcard certificate (*.example.com).
    • Fix: Use getAdditionalDomains() to check coverage:
      $cert = SslCertificate::createForHostName('*.example.com');
      $isCovered = in_array('example.com', $cert->getAdditionalDomains());
      
  3. IPv6 Addresses:

    • Issue: IPv6 addresses may fail silently or throw InvalidIpAddress if not formatted correctly.
    • Tip: Enclose IPv6 addresses in brackets:
      $certificate = SslCertificate::download()
          ->fromIpAddress('2a00:1450:4001:80e::200e')
          ->forHost('google.com');
      
  4. Expired Certificates:

    • Issue: By default, createForHostName() fails for expired certificates.
    • Solution: Pass $verifyCertificate = false to bypass:
      $certificate = SslCertificate::createForHostName('expired.badssl.com', 5, false);
      
  5. Port-Specific Certificates:

    • Issue: Some services use different certificates on non-standard ports (e.g., 443 vs. 8443).
    • Tip: Always specify the port explicitly:
      $certificate = SslCertificate::createForHostName('example.com:8443');
      
  6. Carbon Version Conflicts:

    • Issue: The package supports Carbon v2 and v3, but daysUntilExpirationDate() may return negative values in Carbon v3.
    • Fix: Use absoluteDiffInDays() for clarity:
      $daysRemaining = $certificate->expirationDate()->diffInDays(now(), false);
      
  7. Public Key Algorithm Deprecations:

    • Issue: Older certificates may use deprecated algorithms (e.g., RSA-SHA1).
    • Tip: Log or flag insecure algorithms:
      $algorithm = $certificate->getPublicKeyAlgorithm();
      if (str_contains($algorithm, 'SHA1')) {
          Log::warning("Insecure algorithm detected: {$algorithm}");
      }
      

Debugging Tips

  1. Enable Stream Warnings: Add this to your script to debug connection issues:

    error_reporting(E_ALL);
    ini_set('display_errors', 1);
    
  2. Inspect Raw Certificate Data: Convert the certificate to an array for debugging:

    dd($certificate->toArray());
    
  3. Timeout Handling: Increase the timeout for slow connections:

    $certificate = SslCertificate::createForHostName('slow.example.com', 10); // 10-second timeout
    
  4. Certificate Conversion: Convert between formats (e.g., PEM to DER) for testing:

    $pemData = $certificate->toPem();
    file_put_contents('certificate.pem', $pemData);
    

Extension Points

  1. Custom Certificate Validation Logic: Extend the SslCertificate class to add domain-specific rules:
    class CustomCertificate extends SslCertificate
    {
        public function isValidForOrganization(string $expectedOrg): bool
        {
            return $this->isValid() && $this->get
    
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.
codraw/framework-extra-bundle
codraw/messenger
codraw/security
codraw/mailer
codraw/contracts
codraw/profiling
codraw/dependency-injection
codraw/tester
codraw/core
nexmo/api-specification
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony