PHPackages                             spiral-packages/signed-urls - 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. spiral-packages/signed-urls

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

spiral-packages/signed-urls
===========================

Create and validate signed URLs in Spiral Framework

1.1.0(5mo ago)3742[3 PRs](https://github.com/spiral-packages/signed-urls/pulls)MITPHPPHP ^8.1CI passing

Since Jun 17Pushed 4mo ago1 watchersCompare

[ Source](https://github.com/spiral-packages/signed-urls)[ Packagist](https://packagist.org/packages/spiral-packages/signed-urls)[ Docs](https://github.com/spiral-packages/signed-urls)[ RSS](/packages/spiral-packages-signed-urls/feed)WikiDiscussions master Synced 4w ago

READMEChangelog (5)Dependencies (7)Versions (10)Used By (0)

Signed URL generator for Spiral Framework based on Laravel
==========================================================

[](#signed-url-generator-for-spiral-framework-based-on-laravel)

[![PHP](https://camo.githubusercontent.com/ed8b964423a7ac3423f2cb06b37de8b1046767dd66065167d0f1edb635330757/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f73706972616c2d7061636b616765732f7369676e65642d75726c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spiral-packages/signed-urls)[![Latest Version on Packagist](https://camo.githubusercontent.com/f3e44cf09c56d5b5d2debb870bcc80f3f845dfe89c583309e07c6db1029af2d1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f73706972616c2d7061636b616765732f7369676e65642d75726c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spiral-packages/signed-urls)[![GitHub Tests Action Status](https://camo.githubusercontent.com/68d3598f903755f3d0d4f86bf526600a2e9be8f781f20ed27e35b612cea2721b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f73706972616c2d7061636b616765732f7369676e65642d75726c732f72756e2d74657374733f6c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/spiral-packages/signed-urls/actions?query=workflow%3Arun-tests+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/46be8c249fced3850992ad0e909f44555e8324190b1ee5cffcd8cc32185e39b3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f73706972616c2d7061636b616765732f7369676e65642d75726c732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/spiral-packages/signed-urls)

The package allows you to easily create "signed" URLs to named routes. These URLs have a "signature" hash appended to the query string which allows Spiral Framework to verify that the URL has not been modified since it was created.

Signed URLs are especially useful for routes that are publicly accessible yet need a layer of protection against URL manipulation.

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

[](#requirements)

Make sure that your server is configured with following PHP version and extensions:

- PHP 8.1+
- Spiral framework 3.0+

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

[](#installation)

You can install the package via composer:

```
composer require spiral-packages/signed-urls
```

After package install you need to register bootloader from the package.

```
protected const LOAD = [
    // ...
    \Spiral\SignedUrls\Bootloader\SignedUrlsBootloader::class,
];
```

> **Note**if you are using [`spiral-packages/discoverer`](https://github.com/spiral-packages/discoverer), you don't need to register bootloader by yourself.

Specify env variables

```
# Secret key for generating the HMAC variant of the message digest.
# REQUIRED
SIGNED_URLS_KEY=secret

# Name of selected hashing algorithm (i.e. "md5", "sha256", "haval160,4", etc..)
# OPTIONAL (sha256 by default)
SIGNED_URLS_ALGO=sha256
```

Usage
-----

[](#usage)

For example, you might use signed URLs to implement a public "email verification" link that is emailed to your customers:

```
class VerifyEmailNotification
{
    public function __construct(
        private readonly \Spiral\SignedUrls\UrlGeneratorInterface $urls
        private readonly  \Spiral\Views\ViewInterface $view
    ) {}

    public function buildView(): string
    {
        return $this->view->render([
            'signed_url' => $this->urls->signedRoute(
                route: 'verify-email',
                parameters: ['user_id' => 100]
            )
        ]);
    }
}
```

If you would like to generate a temporary signed route URL that expires after a specified amount of time, you may pass expiration date in method. When Spiral Framework validates a temporary signed route URL, it will ensure that the expiration timestamp that is encoded into the signed URL has not expired:

```
class VerifyEmailNotification
{
    public function __construct(
        private readonly \Spiral\SignedUrls\UrlGeneratorInterface $urls
        private readonly  \Spiral\Views\ViewInterface $view
    ) {}

    public function buildView(): string
    {
        return $this->view->render([
            'signed_url' => $this->urls->signedRoute(
                route: 'verify-email',
                parameters: ['user_id' => 100],
                expiration: new \DateTime('...')
            )
        ]);
    }
}
```

You may sign not only routes but also Urls:

```
class VerifyEmailNotification
{
    public function __construct(
        private readonly \Spiral\SignedUrls\UrlGeneratorInterface $urls
        private readonly  \Spiral\Views\ViewInterface $view
    ) {}

    public function buildView(): string
    {
        return $this->view->render([
            'signed_url' => $this->urls->signedUrl(
                uri: new \Nyholm\Psr7\Uri('http://site.com/verify-email/?user_id=1'),
                expiration: new \DateTime('...')
            )
        ]);
    }
}
```

### Validating Signed Urls

[](#validating-signed-urls)

To verify that a URL has a valid signature, you should call the hasValidSignature method:

```
class EmailVerificationController
{
    public function __construct(
        private readonly \Spiral\SignedUrls\UrlGeneratorInterface $urls
    ) {}

    public function verify(\Psr\Http\Message\RequestInterface $request): string
    {
        if (!$this->urls->hasValidSignature($request->getUri())) {
            return 'ERROR';
        }

        return 'OK';
    }
}
```

Instead of validating signed URLs using the incoming request instance, you may assign the `Spiral\SignedUrls\Middleware\ValidateSignature` middleware to the route:

```
class EmailVerificationController
{
    public function __construct(
        private readonly \Spiral\SignedUrls\UrlGeneratorInterface $urls
    ) {}

    #[\Spiral\Router\Annotation\Route(
        name: 'verify-email',
        route: '...',
        middleware: \Spiral\SignedUrls\Middleware\ValidateSignature::class
    )]
    public function verify(\Psr\Http\Message\RequestInterface $request): string
    {
        return 'OK';
    }
}
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

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

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

[](#contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Pavel Buchnev](https://github.com/butschster)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE) for more information.

###  Health Score

45

—

FairBetter than 92% of packages

Maintenance77

Regular maintenance activity

Popularity18

Limited adoption so far

Community9

Small or concentrated contributor base

Maturity62

Established project with proven stability

 Bus Factor1

Top contributor holds 94.1% 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 ~312 days

Total

5

Last Release

173d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/773481?v=4)[Pavel Buchnev](/maintainers/butschster)[@butschster](https://github.com/butschster)

---

Top Contributors

[![butschster](https://avatars.githubusercontent.com/u/773481?v=4)](https://github.com/butschster "butschster (16 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (1 commits)")

---

Tags

componentphpphp81psr-7signaturespiral-frameworkurl-generatorphpspiralspiral-frameworkphp81signed-urlsurl-generator

###  Code Quality

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/spiral-packages-signed-urls/health.svg)

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

###  Alternatives

[aimeos/aimeos-base

Aimeos base layer for abstracting from host environments

2.1k134.0k1](/packages/aimeos-aimeos-base)[spiral/temporal-bridge

Temporal integration package for Spiral Framework

58901.5k](/packages/spiral-temporal-bridge)[jaxon-php/jaxon-core

Jaxon is an open source PHP library for easily creating Ajax web applications

73142.3k25](/packages/jaxon-php-jaxon-core)[obs/esdk-obs-php

OBS PHP SDK

58121.1k3](/packages/obs-esdk-obs-php)

PHPackages © 2026

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