PHPackages                             tilleuls/url-signer-bundle - 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. [Security](/categories/security)
4. /
5. tilleuls/url-signer-bundle

ActiveSymfony-bundle[Security](/categories/security)

tilleuls/url-signer-bundle
==========================

Create and validate signed URLs with a limited lifetime in Symfony

v2.2.3(2mo ago)81340.1k—1%5[1 PRs](https://github.com/coopTilleuls/UrlSignerBundle/pulls)MITPHPPHP &gt;=8.1CI failing

Since Jan 26Pushed 2mo ago13 watchersCompare

[ Source](https://github.com/coopTilleuls/UrlSignerBundle)[ Packagist](https://packagist.org/packages/tilleuls/url-signer-bundle)[ RSS](/packages/tilleuls-url-signer-bundle/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (37)Versions (12)Used By (0)

UrlSignerBundle
===============

[](#urlsignerbundle)

[![Packagist Version](https://camo.githubusercontent.com/6877063030762111cd17a4dc097aa6114668bf83869e7eccbdc8dd6f605baa77/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f74696c6c65756c732f75726c2d7369676e65722d62756e646c652e737667)](https://packagist.org/packages/tilleuls/url-signer-bundle)[![Actions Status](https://github.com/coopTilleuls/UrlSignerBundle/workflows/CI/badge.svg)](https://github.com/coopTilleuls/UrlSignerBundle/actions)[![Coverage Status](https://camo.githubusercontent.com/86996cd2447f9568e918a35f215fba39e20beb639ccc1c45c54774e4e38fa9f0/68747470733a2f2f636f766572616c6c732e696f2f7265706f732f6769746875622f636f6f7054696c6c65756c732f55726c5369676e657242756e646c652f62616467652e7376673f6272616e63683d6d61696e)](https://coveralls.io/github/coopTilleuls/UrlSignerBundle?branch=main)[![Infection MSI](https://camo.githubusercontent.com/fb64af75f35eb2f186375dce9f209e3c868864de81bcf9ae80854d8f584189d1/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d253246636f6f7054696c6c65756c7325324655726c5369676e657242756e646c652532466d61696e)](https://dashboard.stryker-mutator.io/reports/github.com/coopTilleuls/UrlSignerBundle/main)[![Type Coverage](https://camo.githubusercontent.com/8b2e4a6a0fdcebb4f3424a46e6ba95d6aec00c56cff9a091e880ebc517d94264/68747470733a2f2f73686570686572642e6465762f6769746875622f636f6f7054696c6c65756c732f55726c5369676e657242756e646c652f636f7665726167652e737667)](https://shepherd.dev/github/coopTilleuls/UrlSignerBundle)

Create and validate signed URLs with a limited lifetime in Symfony.

This bundle is based on [spatie/url-signer](https://github.com/spatie/url-signer).

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

[](#installation)

Make sure Composer is installed globally, as explained in the [installation chapter](https://getcomposer.org/doc/00-intro.md)of the Composer documentation.

Open a command console, enter your project directory and execute:

```
composer require tilleuls/url-signer-bundle
```

**If you're using [Symfony Flex](https://github.com/symfony/flex), all configuration is already done. You can customize it in `config/packages/url_signer.yaml` file.**

Otherwise, enable the bundle by adding it to the list of registered bundles in the `config/bundles.php` file of your project:

```
// config/bundles.php

return [
    // ...
    CoopTilleuls\UrlSignerBundle\CoopTilleulsUrlSignerBundle::class => ['all' => true],
];
```

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

[](#configuration)

Add a signature key (as environment variable):

```
# config/packages/url_signer.yaml
coop_tilleuls_url_signer:
    signature_key: '%env(string:SIGNATURE_KEY)%'
```

In dev mode, you can use an `.env` file:

```
# .env (or .env.local)
SIGNATURE_KEY=your_signature_key
```

You can change the signer used to create the signature:

```
# config/packages/url_signer.yaml
coop_tilleuls_url_signer:
    signer: 'md5' # 'sha256' by default
```

The default expiration time can be changed too.

In seconds:

```
# config/packages/url_signer.yaml
coop_tilleuls_url_signer:
    default_expiration: 3600 # 86400 by default
```

With a date/time string:

```
# config/packages/url_signer.yaml
coop_tilleuls_url_signer:
    default_expiration: '1 day'
```

You can also customize the URL parameter names:

```
# config/packages/url_signer.yaml
coop_tilleuls_url_signer:
    expires_parameter: 'exp' # 'expires' by default
    signature_parameter: 'sign' # 'signature' by default
```

Usage
-----

[](#usage)

### Generate a Signed URL

[](#generate-a-signed-url)

To create a temporary signed URL for a route, you first need to inject the URL signer to your service or controller:

```
// src/Controller/DocumentController.php
namespace App\Controller;

use CoopTilleuls\UrlSignerBundle\UrlSigner\UrlSignerInterface;

class DocumentController
{
    public function __construct(
        private UrlSignerInterface $urlSigner,
    ) {}
}
```

If autowiring is enabled (the default Symfony configuration) in your application, you have nothing more to do.

Otherwise, inject the `url_signer.signer` service in the configuration:

```
# config/services.yaml
services:
    App\Controller\DocumentController:
        arguments:
            $urlSigner: '@url_signer.signer'
```

You can now use the URL signer to generate a signed path or a signed URL:

```
// src/Controller/DocumentController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

class DocumentController extends AbstractController
{
    private function generateSignedUrl(): string
    {
        // Or $url = $this->generateUrl('secured_document', ['id' => 42], UrlGeneratorInterface::ABSOLUTE_URL);
        $url = $this->generateUrl('secured_document', ['id' => 42]);
        // Will expire after one hour.
        $expiration = (new \DateTime('now'))->add(new \DateInterval('PT1H'));
        // An integer can also be used for the expiration: it will correspond to a number of seconds. For 1 hour:
        // $expiration = 3600;

        // Not passing the second argument will use the default expiration time (86400 seconds by default).
        // return $this->urlSigner->sign($url);

        // Will return a path like this: /documents/42?expires=1611316656&signature=82f6958bd5c96fda58b7a55ade7f651fadb51e12171d58ed271e744bcc7c85c3
        // Or a URL depending on what has been signed before.
        return $this->urlSigner->sign($url, $expiration);
    }
}
```

### Validate Signed Route Requests

[](#validate-signed-route-requests)

To deny access to a route if the signature is not valid, add a `_signed` [extra parameter](https://symfony.com/doc/current/routing.html#extra-parameters) to the route configuration:

```
# config/routes.yaml
secured_document:
    path: /documents/{id}
    controller: App\Controller\DocumentController::index
    defaults:
        _signed: true
```

If the signature is invalid (bad signature or expired URL), the request will receive a 403 response (access denied).

Custom Signer
-------------

[](#custom-signer)

If you need to use a specific hash algorithm for generating the signature, you can create your own signer.

Create a class extending the `AbstractUrlSigner` class:

```
// src/UrlSigner/CustomUrlSigner.php
namespace App\UrlSigner;

use CoopTilleuls\UrlSignerBundle\UrlSigner\AbstractUrlSigner;

class CustomUrlSigner extends AbstractUrlSigner
{
    public static function getName(): string
    {
        return 'custom';
    }

    protected function createSignature(string $url, string $expiration, string $signatureKey): string
    {
        return hash_hmac('algo', "{$url}::{$expiration}", $signatureKey);
    }
}
```

If autoconfiguring is enabled (the default Symfony configuration) in your application, you are done.

Otherwise, register and tag your service:

```
# config/services.yaml
services:
    App\UrlSigner\CustomUrlSigner:
        # You don't need to specify the arguments
        tags: ['url_signer.signer']
```

You can now use your custom signer:

```
# config/packages/url_signer.yaml
coop_tilleuls_url_signer:
    signer: 'custom'
```

Credits
-------

[](#credits)

Created by [Alan Poulain](https://github.com/alanpoulain) for [Les-Tilleuls.coop](https://les-tilleuls.coop/).

###  Health Score

59

—

FairBetter than 99% of packages

Maintenance84

Actively maintained with recent releases

Popularity49

Moderate usage in the ecosystem

Community21

Small or concentrated contributor base

Maturity68

Established project with proven stability

 Bus Factor1

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

Every ~185 days

Recently: every ~225 days

Total

11

Last Release

82d ago

Major Versions

v1.2.0 → v2.0.02023-03-15

PHP version history (2 changes)v1.0.0PHP &gt;=7.4

v2.0.0PHP &gt;=8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/57224?v=4)[Kévin Dunglas](/maintainers/dunglas)[@dunglas](https://github.com/dunglas)

![](https://www.gravatar.com/avatar/da08ebc4ac8aac1a8fac352d831d1b610913edbb5099252e02361081b5b8a066?d=identicon)[Alan Poulain](/maintainers/Alan%20Poulain)

---

Top Contributors

[![alanpoulain](https://avatars.githubusercontent.com/u/10920253?v=4)](https://github.com/alanpoulain "alanpoulain (50 commits)")[![thbil](https://avatars.githubusercontent.com/u/11739744?v=4)](https://github.com/thbil "thbil (2 commits)")[![natepage](https://avatars.githubusercontent.com/u/11576446?v=4)](https://github.com/natepage "natepage (1 commits)")[![pauljosephkrogulec](https://avatars.githubusercontent.com/u/42961012?v=4)](https://github.com/pauljosephkrogulec "pauljosephkrogulec (1 commits)")[![simonjamain](https://avatars.githubusercontent.com/u/6118295?v=4)](https://github.com/simonjamain "simonjamain (1 commits)")[![norkunas](https://avatars.githubusercontent.com/u/2722872?v=4)](https://github.com/norkunas "norkunas (1 commits)")[![MatTheCat](https://avatars.githubusercontent.com/u/1898254?v=4)](https://github.com/MatTheCat "MatTheCat (1 commits)")

---

Tags

encryptionsecuritysignsymfonysymfony-bundleurlurlsymfonysecurityencryptionsign

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Psalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/tilleuls-url-signer-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/tilleuls-url-signer-bundle/health.svg)](https://phpackages.com/packages/tilleuls-url-signer-bundle)
```

###  Alternatives

[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[scheb/2fa

Two-factor authentication for Symfony applications (please use scheb/2fa-bundle to install)

578630.7k1](/packages/scheb-2fa)[pugx/autocompleter-bundle

Add an autocomplete type to forms

93861.6k3](/packages/pugx-autocompleter-bundle)[spomky-labs/pwa-bundle

Progressive Web App Manifest Generator Bundle for Symfony.

6144.4k1](/packages/spomky-labs-pwa-bundle)

PHPackages © 2026

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