PHPackages                             masterix21/laravel-licensing-client - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. masterix21/laravel-licensing-client

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

masterix21/laravel-licensing-client
===================================

This is my package laravel-licensing-client

v1.0.0(7mo ago)0141[4 PRs](https://github.com/masterix21/laravel-licensing-client/pulls)MITPHPPHP ^8.2CI passing

Since Sep 16Pushed 1mo agoCompare

[ Source](https://github.com/masterix21/laravel-licensing-client)[ Packagist](https://packagist.org/packages/masterix21/laravel-licensing-client)[ Docs](https://github.com/masterix21/laravel-licensing-client)[ GitHub Sponsors]()[ RSS](/packages/masterix21-laravel-licensing-client/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (18)Versions (6)Used By (0)

Laravel Licensing Client
========================

[](#laravel-licensing-client)

[![Latest Version on Packagist](https://camo.githubusercontent.com/cb9f12f0b26c81442b16fe32febd9d8b5c89743bc1568ef393df0ac835ff23c4/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6d6173746572697832312f6c61726176656c2d6c6963656e73696e672d636c69656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/masterix21/laravel-licensing-client)[![GitHub Tests Action Status](https://camo.githubusercontent.com/dd07c49f59830d8a73bf822048d3a1e679e3ab50d51caf57d7d9f12510ab9c64/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6173746572697832312f6c61726176656c2d6c6963656e73696e672d636c69656e742f72756e2d74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/masterix21/laravel-licensing-client/actions?query=workflow%3Arun-tests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/ce76e7f45e465be95dcaa304833ea2d0abc3e04a649aa2e943ed357c1d56fcd7/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6d6173746572697832312f6c61726176656c2d6c6963656e73696e672d636c69656e742f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/masterix21/laravel-licensing-client/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/7a624e03b76f426b3bdfbb9c28cd7feda3b9a74a70e3db465d027ae812c8ce13/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6d6173746572697832312f6c61726176656c2d6c6963656e73696e672d636c69656e742e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/masterix21/laravel-licensing-client)

A comprehensive Laravel package for integrating license validation in your applications. This client package works seamlessly with the [Laravel Licensing](https://github.com/masterix21/laravel-licensing) server to provide secure, offline-capable license management using PASETO v4 tokens.

Sponsorship
-----------

[](#sponsorship)

⭐ **Support this project!** If you find this package helpful, please consider [sponsoring the development](https://github.com/sponsors/masterix21) to help maintain and improve it.

Related Packages
----------------

[](#related-packages)

This package is part of the Laravel Licensing ecosystem:

- **[Laravel Licensing Server](https://github.com/masterix21/laravel-licensing)** - The server-side package that manages licenses, activations, and validations
- **[Laravel Licensing Filament Manager](https://github.com/masterix21/laravel-licensing-filament-manager)** - A complete admin panel built with Filament for managing licenses through a user-friendly interface

Features
--------

[](#features)

- 🔐 **Secure offline validation** using PASETO v4 tokens
- 🖥️ **Device fingerprinting** to prevent license sharing
- ⏰ **Grace period support** for handling server downtime
- 💾 **Token caching** for improved performance
- 🛡️ **Middleware protection** for routes
- 🎨 **Artisan commands** for license management
- 📊 **Usage limit tracking**
- 🔄 **Automatic token refresh**
- ❤️ **Heartbeat mechanism** for license status updates

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

[](#requirements)

- PHP 8.1 or higher
- Laravel 10.0 or higher

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

[](#installation)

Install the package via Composer:

```
composer require masterix21/laravel-licensing-client
```

Publish the configuration file:

```
php artisan vendor:publish --tag="licensing-client-config"
```

Run the migrations:

```
php artisan migrate
```

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

[](#configuration)

Configure the package in `config/licensing-client.php`:

```
return [
    // Licensing server configuration
    'server_url' => env('LICENSING_SERVER_URL', 'https://licensing.example.com'),
    'api_version' => env('LICENSING_API_VERSION', 'v1'),

    // PASETO v4 public key for offline token validation
    'public_key' => env('LICENSING_PUBLIC_KEY', ''),

    // Default license key (can be overridden at runtime)
    'license_key' => env('LICENSE_KEY', ''),

    // Storage configuration
    'storage_path' => storage_path('licensing'),

    // Cache configuration
    'cache' => [
        'enabled' => env('LICENSING_CACHE_ENABLED', true),
        'store' => env('LICENSING_CACHE_STORE', 'file'),
        'ttl' => env('LICENSING_CACHE_TTL', 3600), // 1 hour
    ],

    // Heartbeat configuration
    'heartbeat' => [
        'enabled' => env('LICENSING_HEARTBEAT_ENABLED', true),
        'interval' => env('LICENSING_HEARTBEAT_INTERVAL', 3600), // 1 hour
    ],

    // Grace period for server unavailability (in hours)
    'grace_period' => env('LICENSING_GRACE_PERIOD', 72), // 3 days

    // Routes to exclude from license checking
    'excluded_routes' => [
        'login',
        'register',
        'password/*',
        'health',
    ],
];
```

### Environment Variables

[](#environment-variables)

Add these to your `.env` file:

```
LICENSING_SERVER_URL=https://your-licensing-server.com
LICENSING_PUBLIC_KEY=your-paseto-v4-public-key
LICENSE_KEY=YOUR-LICENSE-KEY-HERE
```

Basic Usage
-----------

[](#basic-usage)

### Using the Facade

[](#using-the-facade)

```
use LucaLongo\LaravelLicensingClient\Facades\LaravelLicensingClient;

// Activate a license
$activated = LaravelLicensingClient::activate('LICENSE-KEY-123');

// Check if license is valid
if (LaravelLicensingClient::isValid()) {
    // License is valid, proceed with application logic
}

// Get license information
$licenseInfo = LaravelLicensingClient::getLicenseInfo();
// Returns: [
//     'license_key' => 'LICENSE-KEY-123',
//     'customer_email' => 'customer@example.com',
//     'customer_name' => 'John Doe',
//     'expires_at' => '2025-01-01T00:00:00Z',
//     'max_usages' => 5,
//     'current_usages' => 2,
//     'features' => ['feature1', 'feature2'],
//     'metadata' => ['custom' => 'data']
// ]

// Check if expiring soon (within 7 days)
if (LaravelLicensingClient::isExpiringSoon(7)) {
    // Notify user to renew license
}

// Refresh the license token
LaravelLicensingClient::refresh();

// Deactivate a license
LaravelLicensingClient::deactivate('LICENSE-KEY-123');
```

### Dependency Injection

[](#dependency-injection)

```
use LucaLongo\LaravelLicensingClient\LaravelLicensingClient;

class LicenseController extends Controller
{
    public function __construct(
        private LaravelLicensingClient $licensing
    ) {}

    public function status()
    {
        if ($this->licensing->isValid()) {
            return response()->json([
                'valid' => true,
                'info' => $this->licensing->getLicenseInfo()
            ]);
        }

        return response()->json(['valid' => false], 403);
    }
}
```

Middleware Protection
---------------------

[](#middleware-protection)

Protect your routes using the `license` middleware:

```
// In routes/web.php or routes/api.php

// Protect individual routes
Route::get('/dashboard', DashboardController::class)
    ->middleware('license');

// Protect route groups
Route::middleware(['license'])->group(function () {
    Route::get('/reports', ReportsController::class);
    Route::get('/analytics', AnalyticsController::class);
});

// API routes with license protection
Route::prefix('api')->middleware(['api', 'license'])->group(function () {
    Route::apiResource('products', ProductController::class);
});
```

### Excluding Routes

[](#excluding-routes)

Configure routes that should be accessible without a license in `config/licensing-client.php`:

```
'excluded_routes' => [
    'login',
    'register',
    'password/*',     // Wildcard support
    'api/health',
    'public/*',
],
```

### Handling License Expiration in Middleware

[](#handling-license-expiration-in-middleware)

The middleware automatically:

- Validates the license on each request
- Attempts to refresh expired tokens
- Starts grace period if server is unreachable
- Sends heartbeats to track usage
- Adds expiration warnings to request attributes

Access expiration warnings in your controllers:

```
public function dashboard(Request $request)
{
    if ($request->attributes->get('license_expiring_soon')) {
        $expiresAt = $request->attributes->get('license_expires_at');
        // Show warning banner to user
    }

    return view('dashboard');
}
```

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

[](#artisan-commands)

### Activate a License

[](#activate-a-license)

```
# With license key as argument
php artisan license:activate YOUR-LICENSE-KEY

# Interactive mode (will prompt for key)
php artisan license:activate
```

### Validate License Status

[](#validate-license-status)

```
# Check current license
php artisan license:validate

# Check specific license
php artisan license:validate --key=ANOTHER-LICENSE-KEY
```

### Display License Information

[](#display-license-information)

```
php artisan license:info
```

Output:

```
License Information:
====================
Status: ✓ Active
License Key: YOUR-LICENSE-KEY
Customer: John Doe (john@example.com)
Expires: 2025-01-01 00:00:00 (in 180 days)
Usage: 2 / 5 activations
Features: feature1, feature2, premium_support

```

### Refresh License Token

[](#refresh-license-token)

```
php artisan license:refresh
```

### Deactivate License

[](#deactivate-license)

```
php artisan license:deactivate

# With confirmation bypass
php artisan license:deactivate --force
```

Task Scheduling
---------------

[](#task-scheduling)

### Automatic License Maintenance

[](#automatic-license-maintenance)

The package includes automatic license maintenance through Laravel's task scheduler. When heartbeat is enabled, it automatically sends heartbeat signals to keep your license status synchronized with the server.

To enable automatic scheduling, add the following to your `app/Console/Kernel.php`:

```
protected function schedule(Schedule $schedule): void
{
    // The package automatically schedules heartbeat when enabled in config
    // No manual configuration needed if heartbeat.enabled is true
}
```

The heartbeat runs based on your configuration:

- **Default interval**: Every 60 minutes (3600 seconds)
- **Configurable via**: `LICENSING_HEARTBEAT_INTERVAL` environment variable (in seconds)

### Manual License Checks

[](#manual-license-checks)

If you prefer manual control or need additional license checks, you can schedule commands:

```
use Illuminate\Console\Scheduling\Schedule;

protected function schedule(Schedule $schedule): void
{
    // Validate license daily
    $schedule->command('license:validate')
        ->daily()
        ->onFailure(function () {
            // Handle invalid license
            Log::error('License validation failed');
        });

    // Refresh license token weekly
    $schedule->command('license:refresh')
        ->weekly()
        ->onSuccess(function () {
            Log::info('License token refreshed successfully');
        });

    // Check and notify about expiring licenses
    $schedule->call(function () {
        if (LaravelLicensingClient::isExpiringSoon(7)) {
            // Send notification about expiring license
            Mail::to(config('mail.admin'))->send(new LicenseExpiringSoon());
        }
    })->daily();
}
```

### Configuration

[](#configuration-1)

The scheduling behavior is controlled by these settings in `config/licensing-client.php`:

```
'heartbeat' => [
    'enabled' => env('LICENSING_HEARTBEAT_ENABLED', true),
    'interval' => env('LICENSING_HEARTBEAT_INTERVAL', 3600), // seconds
],
```

To disable automatic heartbeat:

```
LICENSING_HEARTBEAT_ENABLED=false
```

To change heartbeat frequency (e.g., every 30 minutes):

```
LICENSING_HEARTBEAT_INTERVAL=1800
```

Grace Period Management
-----------------------

[](#grace-period-management)

When the licensing server is unreachable, the package automatically enters a grace period:

```
// Check if in grace period
if (LaravelLicensingClient::isInGracePeriod()) {
    // Show warning that license server is unreachable
    // Application continues to work for configured grace period
}

// Manually start grace period (useful for testing)
LaravelLicensingClient::startGracePeriod();

// Check server health
if (!LaravelLicensingClient::isServerHealthy()) {
    // Server is down, grace period may be active
}
```

Advanced Usage
--------------

[](#advanced-usage)

### Custom License Validation

[](#custom-license-validation)

```
use LucaLongo\LaravelLicensingClient\Services\TokenValidator;

class CustomLicenseValidator
{
    public function __construct(
        private TokenValidator $validator
    ) {}

    public function validateBusinessRules(string $token): bool
    {
        try {
            $claims = $this->validator->validate($token);

            // Custom validation logic
            if ($claims['plan'] !== 'enterprise') {
                return false;
            }

            // Check custom features
            $requiredFeatures = ['api_access', 'white_label'];
            $hasFeatures = !empty(array_intersect(
                $requiredFeatures,
                $claims['features'] ?? []
            ));

            return $hasFeatures;
        } catch (\Exception $e) {
            return false;
        }
    }
}
```

### Heartbeat Customization

[](#heartbeat-customization)

Send custom data with heartbeats:

```
// In a service provider or scheduled job
use LucaLongo\LaravelLicensingClient\Facades\LaravelLicensingClient;

LaravelLicensingClient::heartbeat(
    licenseKey: 'LICENSE-KEY',
    data: [
        'active_users' => User::where('last_login', '>', now()->subDay())->count(),
        'storage_used' => DiskUsage::calculate(),
        'api_calls_today' => ApiLog::today()->count(),
    ]
);
```

### Token Storage Access

[](#token-storage-access)

Direct access to token storage for advanced scenarios:

```
use LucaLongo\LaravelLicensingClient\Services\TokenStorage;

class LicenseDebugService
{
    public function __construct(
        private TokenStorage $storage
    ) {}

    public function debugInfo(string $licenseKey): array
    {
        return [
            'has_token' => $this->storage->exists($licenseKey),
            'last_heartbeat' => $this->storage->getLastHeartbeat($licenseKey),
            'grace_period' => $this->storage->getGracePeriod(),
            'cached' => Cache::has("license_token:{$licenseKey}"),
        ];
    }
}
```

### Custom Fingerprint Generation

[](#custom-fingerprint-generation)

Extend the fingerprint generator for custom device identification:

```
use LucaLongo\LaravelLicensingClient\Services\FingerprintGenerator;

class CustomFingerprintGenerator extends FingerprintGenerator
{
    public function generate(): string
    {
        $metadata = $this->getMetadata();

        // Add custom identifiers
        $metadata['docker_container'] = env('HOSTNAME');
        $metadata['deployment_id'] = config('app.deployment_id');

        return hash('sha256', json_encode($metadata));
    }
}

// Register in a service provider
$this->app->bind(FingerprintGenerator::class, CustomFingerprintGenerator::class);
```

Error Handling
--------------

[](#error-handling)

The package throws specific exceptions for different scenarios:

```
use LucaLongo\LaravelLicensingClient\Exceptions\LicensingException;
use LucaLongo\LaravelLicensingClient\Facades\LaravelLicensingClient;

try {
    LaravelLicensingClient::validate();
} catch (LicensingException $e) {
    switch ($e->getMessage()) {
        case 'The license has expired.':
            // Handle expiration
            break;
        case 'License usage limit has been exceeded.':
            // Handle usage limit
            break;
        case 'Device fingerprint does not match the licensed device.':
            // Handle device mismatch
            break;
        case 'The license has not been activated.':
            // Prompt for activation
            break;
        default:
            // Generic error handling
            Log::error('License validation failed', [
                'error' => $e->getMessage()
            ]);
    }
}
```

Testing
-------

[](#testing)

The package includes comprehensive test coverage. When using in your tests:

```
use LucaLongo\LaravelLicensingClient\Facades\LaravelLicensingClient;
use Illuminate\Support\Facades\Http;

class FeatureTest extends TestCase
{
    public function test_protected_route_with_valid_license()
    {
        // Mock the licensing server responses
        Http::fake([
            '*/api/licensing/v1/activate' => Http::response([
                'token' => 'valid-paseto-token',
                'expires_at' => now()->addYear()->toIso8601String(),
            ], 200),
        ]);

        // Activate a test license
        LaravelLicensingClient::activate('TEST-LICENSE');

        // Test protected route
        $response = $this->get('/protected-route');
        $response->assertStatus(200);
    }

    public function test_grace_period_activation()
    {
        // Mock server as unreachable
        Http::fake([
            '*/api/licensing/v1/*' => Http::response(null, 500),
        ]);

        // Start grace period
        LaravelLicensingClient::startGracePeriod();

        // Should still access protected routes
        $response = $this->get('/protected-route');
        $response->assertStatus(200);
    }
}
```

### Mocking in Unit Tests

[](#mocking-in-unit-tests)

```
use LucaLongo\LaravelLicensingClient\LaravelLicensingClient;
use Mockery;

class ServiceTest extends TestCase
{
    public function test_service_with_license_check()
    {
        $licensingMock = Mockery::mock(LaravelLicensingClient::class);
        $licensingMock->shouldReceive('isValid')
            ->once()
            ->andReturn(true);
        $licensingMock->shouldReceive('getLicenseInfo')
            ->once()
            ->andReturn([
                'customer_email' => 'test@example.com',
                'features' => ['premium'],
            ]);

        $this->app->instance(LaravelLicensingClient::class, $licensingMock);

        // Test your service
        $service = app(YourService::class);
        $result = $service->premiumFeature();

        $this->assertTrue($result);
    }
}
```

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

[](#troubleshooting)

### Common Issues

[](#common-issues)

#### License validation fails with "Invalid public key format"

[](#license-validation-fails-with-invalid-public-key-format)

- Ensure the PASETO v4 public key is correctly formatted
- The key should be base64-encoded in the correct PASETO format
- Verify the key matches the one used by the licensing server

#### Grace period not activating

[](#grace-period-not-activating)

- Check that the grace period is configured in hours (default: 72)
- Verify the server health endpoint is correctly configured
- Check storage permissions for the grace period file

#### Heartbeat not sending

[](#heartbeat-not-sending)

- Ensure heartbeat is enabled in configuration
- Check the heartbeat interval setting
- Verify network connectivity to the licensing server

#### Token not caching

[](#token-not-caching)

- Verify cache is enabled in configuration
- Check the configured cache store exists
- Ensure cache permissions are set correctly

### Debug Mode

[](#debug-mode)

Enable debug logging for troubleshooting:

```
// In config/logging.php
'channels' => [
    'licensing' => [
        'driver' => 'single',
        'path' => storage_path('logs/licensing.log'),
        'level' => env('LICENSING_LOG_LEVEL', 'debug'),
    ],
],
```

Then in your code:

```
use Illuminate\Support\Facades\Log;

Log::channel('licensing')->info('License check', [
    'valid' => LaravelLicensingClient::isValid(),
    'info' => LaravelLicensingClient::getLicenseInfo(),
]);
```

Security Considerations
-----------------------

[](#security-considerations)

1. **Store the public key securely**: Use environment variables, never commit to version control
2. **Validate fingerprints**: Ensure device fingerprinting is properly configured to prevent license sharing
3. **Monitor heartbeats**: Track unusual patterns in heartbeat data for potential abuse
4. **Implement rate limiting**: Add rate limiting to license validation endpoints
5. **Audit license usage**: Log all activation, deactivation, and validation events
6. **Secure token storage**: Tokens are automatically encrypted when stored

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

This package is open-sourced software licensed under the [MIT license](LICENSE.md).

Support
-------

[](#support)

For issues and questions, please use the [GitHub issue tracker](https://github.com/masterix21/laravel-licensing-client/issues).

Consider [sponsoring this project](https://github.com/sponsors/masterix21) if you use it in production!

Credits
-------

[](#credits)

- [Luca Longo](https://github.com/masterix21)
- Built to work with [Laravel Licensing](https://github.com/masterix21/laravel-licensing) server
- Admin interface available via [Laravel Licensing Filament Manager](https://github.com/masterix21/laravel-licensing-filament-manager)

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

###  Health Score

39

—

LowBetter than 86% of packages

Maintenance78

Regular maintenance activity

Popularity9

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 89.5% 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

238d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/177020fc4adb5c08acee3e6fe0b65002a96665c5d5c522a3ef009b4105fd634f?d=identicon)[masterix](/maintainers/masterix)

---

Top Contributors

[![masterix21](https://avatars.githubusercontent.com/u/6555012?v=4)](https://github.com/masterix21 "masterix21 (17 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (1 commits)")

---

Tags

laravelLuca Longolaravel-licensing-client

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/masterix21-laravel-licensing-client/health.svg)

```
[![Health](https://phpackages.com/badges/masterix21-laravel-licensing-client/health.svg)](https://phpackages.com/packages/masterix21-laravel-licensing-client)
```

###  Alternatives

[nativephp/mobile

NativePHP for Mobile

82724.0k43](/packages/nativephp-mobile)[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[spatie/laravel-rdap

Perform RDAP queries in a Laravel app

72108.3k2](/packages/spatie-laravel-rdap)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

255.2k](/packages/aedart-athenaeum)[tonysm/importmap-laravel

Use ESM with importmap to manage modern JavaScript in Laravel without transpiling or bundling.

148399.8k1](/packages/tonysm-importmap-laravel)[bensampo/laravel-embed

Painless responsive embeds for videos, slideshows and more.

142146.8k](/packages/bensampo-laravel-embed)

PHPackages © 2026

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