{"id":15021911,"url":"https://github.com/cooptilleuls/urlsignerbundle","last_synced_at":"2025-04-12T15:40:15.389Z","repository":{"id":41957140,"uuid":"331003968","full_name":"coopTilleuls/UrlSignerBundle","owner":"coopTilleuls","description":"Create and validate signed URLs with a limited lifetime in Symfony","archived":false,"fork":false,"pushed_at":"2025-04-07T08:17:08.000Z","size":107,"stargazers_count":79,"open_issues_count":0,"forks_count":4,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-04-11T20:47:58.601Z","etag":null,"topics":["encryption","security","sign","symfony","symfony-bundle","url"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coopTilleuls.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-19T14:18:46.000Z","updated_at":"2025-04-07T08:17:12.000Z","dependencies_parsed_at":"2023-02-18T07:30:46.167Z","dependency_job_id":"564ed106-3b79-4003-9daf-be5ad9d09e63","html_url":"https://github.com/coopTilleuls/UrlSignerBundle","commit_stats":{"total_commits":43,"total_committers":6,"mean_commits":7.166666666666667,"dds":"0.13953488372093026","last_synced_commit":"3e79328a48eb9e249f8535506c33026eed3a2a07"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopTilleuls%2FUrlSignerBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopTilleuls%2FUrlSignerBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopTilleuls%2FUrlSignerBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coopTilleuls%2FUrlSignerBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coopTilleuls","download_url":"https://codeload.github.com/coopTilleuls/UrlSignerBundle/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248590736,"owners_count":21129883,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["encryption","security","sign","symfony","symfony-bundle","url"],"created_at":"2024-09-24T19:57:12.804Z","updated_at":"2025-04-12T15:40:15.353Z","avatar_url":"https://github.com/coopTilleuls.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UrlSignerBundle\n\n[![Packagist Version](https://img.shields.io/packagist/v/tilleuls/url-signer-bundle.svg)](https://packagist.org/packages/tilleuls/url-signer-bundle)\n[![Actions Status](https://github.com/coopTilleuls/UrlSignerBundle/workflows/CI/badge.svg)](https://github.com/coopTilleuls/UrlSignerBundle/actions)\n[![Coverage Status](https://coveralls.io/repos/github/coopTilleuls/UrlSignerBundle/badge.svg?branch=main)](https://coveralls.io/github/coopTilleuls/UrlSignerBundle?branch=main)\n[![Infection MSI](https://img.shields.io/endpoint?url=https%3A%2F%2Fbadge-api.stryker-mutator.io%2Fgithub.com%2FcoopTilleuls%2FUrlSignerBundle%2Fmain)](https://dashboard.stryker-mutator.io/reports/github.com/coopTilleuls/UrlSignerBundle/main)\n[![Type Coverage](https://shepherd.dev/github/coopTilleuls/UrlSignerBundle/coverage.svg)](https://shepherd.dev/github/coopTilleuls/UrlSignerBundle)\n\nCreate and validate signed URLs with a limited lifetime in Symfony.\n\nThis bundle is based on [spatie/url-signer](https://github.com/spatie/url-signer).\n\n## Installation\n\nMake sure Composer is installed globally, as explained in the\n[installation chapter](https://getcomposer.org/doc/00-intro.md)\nof the Composer documentation.\n\nOpen a command console, enter your project directory and execute:\n\n```console\ncomposer require tilleuls/url-signer-bundle\n```\n\n**If you're using [Symfony Flex](https://github.com/symfony/flex), all configuration is already done.\nYou can customize it in `config/packages/url_signer.yaml` file.**\n\nOtherwise, enable the bundle by adding it to the list of registered bundles\nin the `config/bundles.php` file of your project:\n\n```php\n// config/bundles.php\n\nreturn [\n    // ...\n    CoopTilleuls\\UrlSignerBundle\\CoopTilleulsUrlSignerBundle::class =\u003e ['all' =\u003e true],\n];\n```\n\n## Configuration\n\nAdd a signature key (as environment variable):\n\n```yml\n# config/packages/url_signer.yaml\ncoop_tilleuls_url_signer:\n    signature_key: '%env(string:SIGNATURE_KEY)%'\n```\n\nIn dev mode, you can use an `.env` file:\n\n```env\n# .env (or .env.local)\nSIGNATURE_KEY=your_signature_key\n```\n\nYou can change the signer used to create the signature:\n\n```yml\n# config/packages/url_signer.yaml\ncoop_tilleuls_url_signer:\n    signer: 'md5' # 'sha256' by default\n```\n\nThe default expiration time can be changed too.\n\nIn seconds:\n\n```yml\n# config/packages/url_signer.yaml\ncoop_tilleuls_url_signer:\n    default_expiration: 3600 # 86400 by default\n```\n\nWith a date/time string:\n\n```yml\n# config/packages/url_signer.yaml\ncoop_tilleuls_url_signer:\n    default_expiration: '1 day'\n```\n\nYou can also customize the URL parameter names:\n\n```yml\n# config/packages/url_signer.yaml\ncoop_tilleuls_url_signer:\n    expires_parameter: 'exp' # 'expires' by default\n    signature_parameter: 'sign' # 'signature' by default\n```\n\n## Usage\n\n### Generate a Signed URL\n\nTo create a temporary signed URL for a route, you first need to inject the URL signer to your service or controller:\n\n```php\n// src/Controller/DocumentController.php\nnamespace App\\Controller;\n\nuse CoopTilleuls\\UrlSignerBundle\\UrlSigner\\UrlSignerInterface;\n\nclass DocumentController\n{\n    public function __construct(\n        private UrlSignerInterface $urlSigner,\n    ) {}\n}\n```\n\nIf autowiring is enabled (the default Symfony configuration) in your application, you have nothing more to do.\n\nOtherwise, inject the `url_signer.signer` service in the configuration:\n\n```yml\n# config/services.yaml\nservices:\n    App\\Controller\\DocumentController:\n        arguments:\n            $urlSigner: '@url_signer.signer'\n```\n\nYou can now use the URL signer to generate a signed path or a signed URL:\n\n```php\n// src/Controller/DocumentController.php\nnamespace App\\Controller;\n\nuse Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController;\n\nclass DocumentController extends AbstractController\n{\n    private function generateSignedUrl(): string\n    {\n        // Or $url = $this-\u003egenerateUrl('secured_document', ['id' =\u003e 42], UrlGeneratorInterface::ABSOLUTE_URL);\n        $url = $this-\u003egenerateUrl('secured_document', ['id' =\u003e 42]);\n        // Will expire after one hour.\n        $expiration = (new \\DateTime('now'))-\u003eadd(new \\DateInterval('PT1H'));\n        // An integer can also be used for the expiration: it will correspond to a number of seconds. For 1 hour:\n        // $expiration = 3600;\n\n        // Not passing the second argument will use the default expiration time (86400 seconds by default).\n        // return $this-\u003eurlSigner-\u003esign($url);\n\n        // Will return a path like this: /documents/42?expires=1611316656\u0026signature=82f6958bd5c96fda58b7a55ade7f651fadb51e12171d58ed271e744bcc7c85c3\n        // Or a URL depending on what has been signed before.\n        return $this-\u003eurlSigner-\u003esign($url, $expiration);\n    }\n}\n```\n\n### Validate Signed Route Requests\n\nTo deny access to a route if the signature is not valid,\nadd a `_signed` [extra parameter](https://symfony.com/doc/current/routing.html#extra-parameters) to the route configuration:\n\n```yml\n# config/routes.yaml\nsecured_document:\n    path: /documents/{id}\n    controller: App\\Controller\\DocumentController::index\n    defaults:\n        _signed: true\n```\n\nIf the signature is invalid (bad signature or expired URL), the request will receive a 403 response (access denied).\n\n## Custom Signer\n\nIf you need to use a specific hash algorithm for generating the signature, you can create your own signer.\n\nCreate a class extending the `AbstractUrlSigner` class:\n\n```php\n// src/UrlSigner/CustomUrlSigner.php\nnamespace App\\UrlSigner;\n\nuse CoopTilleuls\\UrlSignerBundle\\UrlSigner\\AbstractUrlSigner;\n\nclass CustomUrlSigner extends AbstractUrlSigner\n{\n    public static function getName(): string\n    {\n        return 'custom';\n    }\n\n    protected function createSignature(string $url, string $expiration, string $signatureKey): string\n    {\n        return hash_hmac('algo', \"{$url}::{$expiration}\", $signatureKey);\n    }\n}\n```\n\nIf autoconfiguring is enabled (the default Symfony configuration) in your application, you are done.\n\nOtherwise, register and tag your service:\n\n```yml\n# config/services.yaml\nservices:\n    App\\UrlSigner\\CustomUrlSigner:\n        # You don't need to specify the arguments\n        tags: ['url_signer.signer']\n```\n\nYou can now use your custom signer:\n\n```yml\n# config/packages/url_signer.yaml\ncoop_tilleuls_url_signer:\n    signer: 'custom'\n```\n\n## Credits\n\nCreated by [Alan Poulain](https://github.com/alanpoulain) for [Les-Tilleuls.coop](https://les-tilleuls.coop/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcooptilleuls%2Furlsignerbundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcooptilleuls%2Furlsignerbundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcooptilleuls%2Furlsignerbundle/lists"}