PHPackages                             nazrulalif/laravel-pem-license-validator - 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. [Validation &amp; Sanitization](/categories/validation)
4. /
5. nazrulalif/laravel-pem-license-validator

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

nazrulalif/laravel-pem-license-validator
========================================

Offline PEM license validation for Laravel applications using RSA-4096 signatures

v1.0.0(8mo ago)01MITPHPPHP ^8.1

Since Oct 22Pushed 8mo agoCompare

[ Source](https://github.com/Nazrulalif/laravel-pem-license-validator)[ Packagist](https://packagist.org/packages/nazrulalif/laravel-pem-license-validator)[ RSS](/packages/nazrulalif-laravel-pem-license-validator/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (1)Versions (2)Used By (0)

Laravel PEM License Validator
=============================

[](#laravel-pem-license-validator)

Offline license validation for Laravel applications using RSA-4096 signed PEM files.

Features
--------

[](#features)

- ✅ Offline validation (no internet required)
- ✅ RSA-4096 signature verification
- ✅ Configurable caching
- ✅ Optional grace period
- ✅ Hardware binding support
- ✅ Product key validation
- ✅ Feature flags (JSON-based)
- ✅ Laravel middleware included
- ✅ Facade support

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 9.0+
- OpenSSL extension
- JSON extension

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

[](#installation)

```
composer require nazrulalif/laravel-pem-license-validator:dev-master
```

### Publish Configuration

[](#publish-configuration)

```
php artisan vendor:publish --provider="Nazrulalif\LaravelPemLicenseValidator\LicenseServiceProvider"
```

This creates `config/license.php`

### Place License File

[](#place-license-file)

Place your `license.pem` file in:

```
storage/app/license.pem

```

Configuration
-------------

[](#configuration)

Edit `config/license.php`:

```
return [
    'license_path' => storage_path('app/license.pem'),

    'cache' => [
        'enabled' => true,
        'ttl' => 86400, // 24 hours
        'driver' => 'file',
    ],

    'grace_period_days' => 0, // 0=disabled, 7=7 days after expiry

    'product_key' => env('LICENSE_PRODUCT_KEY'), // Optional product validation

    'public_key' => env('LICENSE_PUBLIC_KEY', '-----BEGIN PUBLIC KEY-----...'),

    'on_failure' => [
        'redirect' => '/license-expired',
        'log' => true,
    ],
];
```

### Environment Variables

[](#environment-variables)

Add these to your `.env` file:

```
LICENSE_PATH=storage/app/license.pem
LICENSE_CACHE_ENABLED=true
LICENSE_CACHE_TTL=86400
LICENSE_GRACE_PERIOD_DAYS=0
LICENSE_PRODUCT_KEY=your-product-key
LICENSE_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----
...your public key here...
-----END PUBLIC KEY-----"
LICENSE_FAILURE_REDIRECT=/license-expired
LICENSE_FAILURE_LOG=true
LICENSE_FAILURE_ABORT_CODE=403
```

**Note:** `LICENSE_PRODUCT_KEY` is optional. If set, the license must contain a matching `productKey` field for validation to pass.

Usage
-----

[](#usage)

### Basic Validation

[](#basic-validation)

```
use Nazrulalif\LaravelPemLicenseValidator\LicenseValidator;

$validator = new LicenseValidator(config('license'));

if ($validator->isValid()) {
    $license = $validator->getLicenseData();
    echo "Valid until: " . $license['expiryDate'];
} else {
    abort(403, 'Invalid license');
}
```

### Using Facade

[](#using-facade)

```
use Nazrulalif\LaravelPemLicenseValidator\Facades\License;

if (License::isValid()) {
    $daysLeft = License::getDaysRemaining();
    echo "License expires in {$daysLeft} days";
}
```

### Middleware Protection

[](#middleware-protection)

Register in `app/Http/Kernel.php`:

```
protected $middlewareAliases = [
    'license' => \Nazrulalif\LaravelPemLicenseValidator\Middleware\ValidateLicense::class,
];
```

Use in routes:

```
Route::middleware('license')->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::get('/settings', [SettingsController::class, 'index']);
});
```

### Bootstrap Validation

[](#bootstrap-validation)

In `app/Providers/AppServiceProvider.php`:

```
public function boot()
{
    try {
        $validator = app(\Nazrulalif\LaravelPemLicenseValidator\LicenseValidator::class);

        if (!$validator->isValid()) {
            abort(403, 'Invalid or expired license: ' . $validator->getError());
        }

        // Check grace period
        if ($validator->isInGracePeriod()) {
            logger()->warning('License in grace period. Days remaining: ' . $validator->getDaysRemaining());
        }

    } catch (\Exception $e) {
        abort(500, 'License validation error: ' . $e->getMessage());
    }
}
```

### Feature Checks

[](#feature-checks)

```
use Nazrulalif\LaravelPemLicenseValidator\Facades\License;

// Check if feature exists
if (License::hasFeature('api_access')) {
    // Enable API routes
}

// Get feature value with default
$maxUsers = License::getFeature('UserLimit', 10);

// Get all features
$features = License::getLicenseData()['features'];
```

API Reference
-------------

[](#api-reference)

### LicenseValidator

[](#licensevalidator)

```
// Validate license
$validator->validate(): array

// Check if valid
$validator->isValid(): bool

// Get license data
$validator->getLicenseData(): array

// Get days remaining
$validator->getDaysRemaining(): int

// Check grace period
$validator->isInGracePeriod(): bool

// Get feature value
$validator->getFeature(string $key, mixed $default = null): mixed

// Check feature exists
$validator->hasFeature(string $key): bool

// Get error message
$validator->getError(): ?string
```

License Data Structure
----------------------

[](#license-data-structure)

```
{
  "productKey": "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX",
  "licenseId": "LIC-1234567890",
  "licenseType": "PROFESSIONAL",
  "companyName": "Acme Corporation",
  "email": "customer@example.com",
  "maxDevices": 5,
  "features": {
    "UserLimit": 50,
    "sso": true,
    "api_access": true,
    "storage_gb": 100
  },
  "hardwareId": null,
  "issueDate": "2025-01-01T00:00:00Z",
  "expiryDate": "2026-01-01T00:00:00Z"
}
```

Exception Handling
------------------

[](#exception-handling)

```
use Nazrulalif\LaravelPemLicenseValidator\Exceptions\LicenseException;

try {
    $validator->validate();
} catch (LicenseException $e) {
    switch ($e->getCode()) {
        case LicenseException::FILE_NOT_FOUND:
            // Handle missing file
            break;
        case LicenseException::INVALID_SIGNATURE:
            // Handle tampered license
            break;
        case LicenseException::EXPIRED:
            // Handle expiry
            break;
        case LicenseException::HARDWARE_MISMATCH:
            // Handle hardware binding
            break;
        case LicenseException::PRODUCT_KEY_MISMATCH:
            // Handle product key validation failure
            break;
    }
}
```

Troubleshooting
---------------

[](#troubleshooting)

### License file not found

[](#license-file-not-found)

Ensure `license.pem` exists at the configured path (default: `storage/app/license.pem`)

### Invalid signature

[](#invalid-signature)

- License file may be corrupted or tampered
- Public key in config doesn't match the key used to sign the license

### Product key mismatch

[](#product-key-mismatch)

- The `productKey` in the license doesn't match `LICENSE_PRODUCT_KEY` in your `.env`
- License was issued for a different product
- Remove `LICENSE_PRODUCT_KEY` from `.env` to disable product key validation

### Permission denied

[](#permission-denied)

```
chmod 644 storage/app/license.pem
```

### Cache issues

[](#cache-issues)

Clear license cache:

```
License::clearCache();
```

Security
--------

[](#security)

- Never commit `license.pem` to version control
- Add to `.gitignore`: `storage/app/license.pem`
- Keep public key secure in `.env` file
- Use HTTPS when transferring license files

Support
-------

[](#support)

For issues or questions, contact:

License
-------

[](#license)

MIT License - see LICENSE file

###  Health Score

29

—

LowBetter than 57% of packages

Maintenance60

Regular maintenance activity

Popularity1

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity44

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

Unknown

Total

1

Last Release

256d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/135031645?v=4)[Nazrul Alif](/maintainers/Nazrulalif)[@Nazrulalif](https://github.com/Nazrulalif)

---

Top Contributors

[![Nazrulalif](https://avatars.githubusercontent.com/u/135031645?v=4)](https://github.com/Nazrulalif "Nazrulalif (7 commits)")

---

Tags

laravelvalidationlicensersapemoffline

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/nazrulalif-laravel-pem-license-validator/health.svg)

```
[![Health](https://phpackages.com/badges/nazrulalif-laravel-pem-license-validator/health.svg)](https://phpackages.com/packages/nazrulalif-laravel-pem-license-validator)
```

###  Alternatives

[stuyam/laravel-phone-validator

A phone validator for Laravel using the free Twilio phone lookup service.

2861.9k](/packages/stuyam-laravel-phone-validator)[skysplit/laravel5-intl-translation

Laravel 5 package for better translation syntax using php-intl extension

10106.6k](/packages/skysplit-laravel5-intl-translation)[pacerit/laravel-polish-validation-rules

Simple Polish Validation rules for Laravel and Lumen framework

1453.9k](/packages/pacerit-laravel-polish-validation-rules)[laravel-validation-rules/ip

Validate if an ip address is public or private.

1629.7k](/packages/laravel-validation-rules-ip)[cohensive/validation

Extra functionality for Laravel 5 Validator.

1413.9k](/packages/cohensive-validation)[fab2s/dt0

Immutable DTOs with bidirectional casting. No framework required. 8x faster than the alternative.

102.3k1](/packages/fab2s-dt0)

PHPackages © 2026

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