PHPackages                             leoralph/signed-url - 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. leoralph/signed-url

ActiveLibrary

leoralph/signed-url
===================

Enhanced signed URLs for Laravel, including attaching data, click limits and expiry.

v6.0.0(1y ago)0439↑11.1%MITPHPPHP ^8.0

Since Dec 6Pushed 1y agoCompare

[ Source](https://github.com/leoralph/signed-url)[ Packagist](https://packagist.org/packages/leoralph/signed-url)[ RSS](/packages/leoralph-signed-url/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)Dependencies (8)Versions (2)Used By (0)

Laravel Signed URLs
===================

[](#laravel-signed-urls)

> Enhanced signed URLs for Laravel, including attaching data, click limits and expiry.

[![Build Status](https://camo.githubusercontent.com/24d714756295c26e80825a0da4efce7eabbd9d63afd69fec302bd11c39845d7e/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c696e6b6579732d6170702f7369676e65642d75726c2f6261646765732f6275696c642e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/linkeys-app/signed-url/build-status/master)[![Code Coverage](https://camo.githubusercontent.com/626b7f4454b28c287b36f3c22d5375192de6354f0f817f80ec76329c1f6b5963/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c696e6b6579732d6170702f7369676e65642d75726c2f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/linkeys-app/signed-url/?branch=master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/cc95cbce4d98b122108a041070b5447bc58aea3b627de42424fac02a0efe57d7/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f6c696e6b6579732d6170702f7369676e65642d75726c2f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/linkeys-app/signed-url/?branch=master)[![Total Downloads](https://camo.githubusercontent.com/ad23c08dbf0572050007d6026dc427e58d87e4f6d9959be64470b08a7eb9bd87/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6c696e6b6579732f7369676e65642d75726c2e737667)](https://packagist.org/packages/linkeys/signed-url)[![Licence](https://camo.githubusercontent.com/5d37b70b6b0cda61fa2d8fd75d6a73e9d80c7a97fdc8b498b955f7e3d736f56c/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f6c696e6b6579732f7369676e65642d75726c2e737667)](https://packagist.org/packages/linkeys/signed-url)

Table of Contents
-----------------

[](#table-of-contents)

- [Introduction](#introduction)
- [Version Compatibility](#version-compatibility)
- [Getting Started](#getting-started)
    - [Installation](#installation)
- [Usage](#usage)
    - [Overview](#overview)
    - [Creating a Link](#creating-a-link)
    - [Handling a Link](#handling-a-link)
- [Examples](#examples)
- [Licence](#license)
- [Contact](#contact)

Introduction
------------

[](#introduction)

Revamped URL signing brought to Laravel. Pass data through any url securely, and control expiry and number of clicks.

- Securely attach data to links to make it available to your controllers.
- Create links of a limited lifetime.
- Limit the number of clicks allowed on a link.
- Limit the number of clicks on a group of links, such as only allowing one of a group of links to be clicked.

Version Compatibility
---------------------

[](#version-compatibility)

LaravelUrl Signer5.7.x1.0.x5.8.x1.0.x6.x1.0.37.x2.0.x8.x3.0.x9.x4.0.x10.x5.0.xGetting Started
---------------

[](#getting-started)

It couldn't be easier to install and set up url signing in your laravel app.

### Installation

[](#installation)

1. Install through the composer package manager

    ```
    composer require linkeys/signed-url

    ```
2. (Optional) Publish the assets

    ```
    php artisan vendor:publish --provider="Linkeys\UrlSigner\Providers\UrlSignerServiceProvider"

    ```

    You can also use the `--tag=config` or `--tag=migrations` flags to only publish the configuration files or the migrations.
3. Run the migrations

    `php artisan migrate`

Usage
-----

[](#usage)

### Overview

[](#overview)

This package works by modifying a URL to give it a signature. This must be a url you have registered in your routes. When the signed URL is opened in the browser, our middleware will not only inject the attached data into a controller request, but throw exceptions if the link has expired, been clicked too many times or altered in any way.

### Creating a Link

[](#creating-a-link)

#### Standard Link

[](#standard-link)

The easiest way to create a link is through the facade:

```
$link = \Linkeys\UrlSigner\Facade\UrlSigner::generate('https://www.example.com/invitation');
echo $link->getFullUrl(); // https://www.example.com/invitation?uuid=UUID
```

The link can now be sent out or used just like normal signed URLs. You may also use the sign method, which is simply an alias for generate, and the alias instead of importing the full facade namespace

```
$link = UrlSigner::sign('https://www.example.com/invitation');
```

You can also resolve an instance of `\Linkeys\UrlSigner\Contracts\UrlSigner` from the container and call the facade functions directly.

#### Data

[](#data)

Instead of encoding data into the url yourself, simply pass it as the second argument.

```
$link = \Linkeys\UrlSigner\Facade\UrlSigner::generate('https://www.example.com/invitation', ['foo' => 'bar']);
echo $link->getFullUrl(); // https://www.example.com/invitation?uuid=UUID
```

In your controller, e.g. InvitationController.php

```
echo $request->get('foo');  // bar
```

Through this method, the data can't be altered by anyone and can't even be seen by users, securing your application and hiding implementation details.

#### Expiry

[](#expiry)

Additional to a basic link is the ability to set the expiry of the link. Only want a link to be available for 24 hours?

```
$link = \Linkeys\UrlSigner\Facade\UrlSigner::generate('https://www.example.com/invitation', ['foo' => 'bar'], '+24 hours');
```

The expiry accepts a string, unix timestamp or a datetime instance (i.e. Carbon).

#### Click Limit

[](#click-limit)

The number of clicks of a link can also be set. If you only want a user to be able to click a link one time:

```
$link = \Linkeys\UrlSigner\Facade\UrlSigner::generate('https://www.example.com/invitation', ['foo' => 'bar'], '+24 hours', 1);
```

The first time the link is clicked, the route will work like normal. The second time, since the link only has a single click, an exception will be thrown. Of course, passing `null` instead of `'+24 hours'` to the expiry parameter will create links of an indefinite lifetime.

#### Link Groups

[](#link-groups)

By grouping links, the click limit may be spread across multiple links. Given a group with a click limit of 2 but 3 links will only allow two total clicks. Expiry is default for links unless they specify it themselves.

```
    $group = \Linkeys\UrlSigner\Facade\UrlSigner::group(function($links) {
        $links->generate('https://www.example.com', ['foo'=>'bar']),
        $links->generate('https://www.example.com', ['foo'=>'baz'])
    }, '+ 24 hours', 1)'
```

This will create two links, both with different data and expiring in 24 hours, but since the group click limit is 1 only a single link may be clicked. This is useful for situations in which you want to give the user a choice of links to click, such as for an invitation (the user should only be able to click 'Yes' or 'No' to respond).

The expiry parameter in a group is a default applied to all links in the group which don't have an expiry date. If you set the expiry date in the link in addition to the in the group, only the link expiry will be checked.

You can access the links using `$group->links;`, which wll return a Laravel collection.

### Handling a Link

[](#handling-a-link)

#### Middleware

[](#middleware)

To enable exceptions to be thrown when a link is invalid in any way, simply add the `'link'`middleware to any relevant routes. This will take care of:

- Ensuring the URL has not been changed.
- Checking the link has not expired.
- Checking the link hasn't reached the limit on number of clicks.
- Adding the link and relevant data into the request.

#### Retrieving Link Information

[](#retrieving-link-information)

We automatically put all data attached to a link into the request attributes. The following is a controller method called when a user clicks on a generated link with data attached.

```
public function acceptInvitation(Request $request)
{
    // Given the link has the data ['foo' => 'bar']...
    $bar = $request->get('foo');

    // To retrieve the link instance:
    $link = $request->get(\Linkeys\UrlSigner\Models\Link::class);
    var_dump($link->data)  // ['foo' => 'bar']
}
```

#### Error handling

[](#error-handling)

The middleware will throw exceptions when the link is invalid in any way. By default, these will be handled by Laravel to display an error page with a simple message.

By using your apps exception handler, you can choose to show custom pages to respond to each of the following situations by catching an error and returning a response:

ConditionExceptionURL has been changedLinkNotFoundExceptionSignature was not foundLinkNotFoundExceptionLink has been clicked too many timesLinkClickLimitReachedExceptionLink group has been clicked too many timesLinkGroupClickLimitReachedExceptionLink has expiredLinkExpiredExceptionLink group has expired and link had no expiryLinkGroupExpiredExceptionThrough using exception inheritance, you can control which pages to show for which exception, or just have a single page for all link exceptions. The inheritance diagram is shown below, with all classes being in the namespace `\Linkeys\UrlSigner\Exceptions` except for `\Exception`.

[![Exception Inheritance](exceptions.png)](exceptions.png)

Examples
--------

[](#examples)

Coming soon...

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

[](#contributing)

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are **greatly appreciated**. See `CONTRIBUTING.md` for more information.

1. Fork the Project
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
3. Commit your Changes (`git commit -m 'Add some AmazingFeature`)
4. Push to the Branch (`git push origin feature/AmazingFeature`)
5. Open a pull request

License
-------

[](#license)

Distributed under the MIT License. See `LICENSE` for more information.

Contact
-------

[](#contact)

Toby Twigger -

Project Link:

###  Health Score

29

—

LowBetter than 60% of packages

Maintenance39

Infrequent updates — may be unmaintained

Popularity15

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

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

519d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/defaa0a5b62af5372e8a5bb1e48b0593fe707a679f924c8c5d297e43d3ff7f6a?d=identicon)[LeoRalph](/maintainers/LeoRalph)

---

Top Contributors

[![tobytwigger](https://avatars.githubusercontent.com/u/24829185?v=4)](https://github.com/tobytwigger "tobytwigger (19 commits)")[![tobytwigger-swytch](https://avatars.githubusercontent.com/u/200782613?v=4)](https://github.com/tobytwigger-swytch "tobytwigger-swytch (3 commits)")[![leoralph](https://avatars.githubusercontent.com/u/86016347?v=4)](https://github.com/leoralph "leoralph (1 commits)")

---

Tags

urllaravellinksignedexpiresingle uselinkeys

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/leoralph-signed-url/health.svg)

```
[![Health](https://phpackages.com/badges/leoralph-signed-url/health.svg)](https://phpackages.com/packages/leoralph-signed-url)
```

###  Alternatives

[linkeys/signed-url

Enhanced signed URLs for Laravel, including attaching data, click limits and expiry.

2259.6k1](/packages/linkeys-signed-url)[laravel/framework

The Laravel Framework.

34.6k509.9M17.0k](/packages/laravel-framework)[laravel/horizon

Dashboard and code-driven configuration for Laravel queues.

4.2k84.2M224](/packages/laravel-horizon)[laravel/octane

Supercharge your Laravel application's performance.

4.0k21.5M156](/packages/laravel-octane)[knuckleswtf/scribe

Generate API documentation for humans from your Laravel codebase.✍

2.3k12.2M45](/packages/knuckleswtf-scribe)[laravel/nightwatch

The official Laravel Nightwatch package.

3486.1M13](/packages/laravel-nightwatch)

PHPackages © 2026

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