Skip to content

[HttpFoundation] Add #[IsSignatureValid] attribute #60395

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: 7.4
Choose a base branch
from

Conversation

santysisi
Copy link
Contributor

@santysisi santysisi commented May 9, 2025

Q A
Branch? 7.4
Bug fix? no
New feature? yes
Deprecations? no
Issues Feature #60189
License MIT

✨ New Feature: #[IsSignatureValid] Attribute

This attribute enables declarative signature validation on controller actions. It ensures that requests using specific HTTP methods are validated using UriSigner. If the signature is invalid, a SignedUriException is thrown.

✅ Usage Examples

#[IsSignatureValid] // Applies to all HTTP methods by default
public function someAction(): Response
#[IsSignatureValid(methods: ['POST', 'PUT'])] // Only validates POST and PUT requests
public function updateAction(): Response
#[IsSignatureValid(signer: 'my_custom_signer_service')] // Uses a custom UriSigner service
public function customSignedAction(): Response

@santysisi santysisi requested a review from chalasr as a code owner May 9, 2025 21:24
@carsonbot carsonbot added this to the 7.3 milestone May 9, 2025
@santysisi santysisi force-pushed the feature/verify-signature-attribute branch 5 times, most recently from 4730169 to c72ef83 Compare May 9, 2025 22:27
@santysisi
Copy link
Contributor Author

santysisi commented May 9, 2025

Hi 👋
I'll update this version 7.3 to 7.4 once the new minor dev version is released.

Edit: I updated this version to 7.3 because I need this method from UriSigner.

@kbond
Copy link
Member

kbond commented May 12, 2025

This is looking great @santysisi! I'll give it a more thorough review after 7.3 is released.

@santysisi santysisi force-pushed the feature/verify-signature-attribute branch from c72ef83 to 85320cf Compare May 18, 2025 03:00
@santysisi
Copy link
Contributor Author

We could also consider adding an extra argument to the attribute called methods to restrict the validation to specific HTTP methods. This would align with the current behavior of the IsCsrfTokenValid attribute.

@fabpot fabpot modified the milestones: 7.3, 7.4 May 26, 2025
@santysisi santysisi force-pushed the feature/verify-signature-attribute branch from 85320cf to c000b69 Compare May 29, 2025 23:01
@santysisi
Copy link
Contributor Author

We could also consider adding an extra argument to the attribute called methods to restrict the validation to specific HTTP methods. This would align with the current behavior of the IsCsrfTokenValid attribute.

Hi 👋 I'll update this version 7.3 to 7.4 once the new minor dev version is released.

Edit: I updated this version to 7.3 because I need this method from UriSigner.

ready these 2 changes 🚀

Copy link
Member

@kbond kbond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really great, nice work @santysisi!

@santysisi
Copy link
Contributor Author

I believe the error is not relevant 🤔
I only rebased the branch to resolve some conflicts, so there shouldn't be any functional changes introduced.

@santysisi santysisi force-pushed the feature/verify-signature-attribute branch 2 times, most recently from 8d79649 to 2290ba3 Compare July 12, 2025 19:43
@santysisi
Copy link
Contributor Author

Hi @ruudk 👋 Thanks so much for your suggestions ❤️
I think it's a really good idea 🚀
I've made the necessary changes to implement it 💪

@santysisi
Copy link
Contributor Author

status: needs review

I think the error in the test is not relevant in the context of the PR

@@ -37,7 +37,8 @@
"symfony/security-csrf": "^6.4|^7.0|^8.0",
"symfony/translation": "^6.4|^7.0|^8.0",
"psr/log": "^1|^2|^3",
"web-token/jwt-library": "^3.3.2|^4.0"
"web-token/jwt-library": "^3.3.2|^4.0",
"symfony/dependency-injection": "^6.4|^7.0|^8.0"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the symfony/dependency-injection component as a dev dependency because I need the ContainerBuilder to test the new CompilerPass.

public function process(ContainerBuilder $container): void
{
$locateableServices = [];
foreach ($container->getDefinitions() as $id => $definition) {
Copy link
Member

@kbond kbond Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think looping over all the definitions is the correct method to handle this. @nicolas-grekas wdyt?

Also, UriSigner isn't final so it could be an sub-class.

Copy link
Contributor Author

@santysisi santysisi Jul 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi 👋 Thanks a lot for your comment!

You're absolutely right, that was totally my mistake 🙏 .
Since UriSigner isn’t final, it can indeed be subclassed. I’ve updated the condition in the if statement to use is_a to correctly check if it's an instance of UriSigner or one of its subclasses.

I also added a test to cover this behavior and ensure it works as expected.

Thanks again for catching that ❤️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 You might be right and apologies if this isn’t the proper way to handle it.
I based my implementation on existing methods in ContainerBuilder, like findTaggedServiceIds, findTaggedResourceIds, and findTags, which also loop through definitions. But again, that might not be ideal in this case, sorry about that!

I'd really appreciate your input on a better approach. If you can suggest one, I’ll be happy to update the code to follow your recommendation.

Thanks again!

Copy link
Contributor Author

@santysisi santysisi Jul 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi! 👋

I’ve tried a new approach to create the ServiceLocator.
I added autoconfiguration for UriSigner with a security.uri_signer tag, and I’m now using findTaggedServiceIds instead of looping through all the definitions.

Please let me know if this method looks better to you 😄
Thanks again! ❤️

Edit: I was also thinking , maybe we could introduce a UriSignerInterface instead. That way, instead of autoconfiguring the concrete UriSigner, we could autoconfigure services implementing UriSignerInterface. This change would allow developers to pass not only the UriSigner service or ones that extend it, but any custom service that implements the interface.

Wdyt? If you agree, I’d be happy to open another PR to add the interface 😄

@santysisi santysisi force-pushed the feature/verify-signature-attribute branch 4 times, most recently from 30c02bd to f20400b Compare July 15, 2025 10:47
nicolas-grekas added a commit that referenced this pull request Jul 15, 2025
…h argument (santysisi)

This PR was merged into the 7.4 branch.

Discussion
----------

[HttpKernel][Security] Refactor: use `getAttributes` with argument

| Q             | A
| ------------- | ---
| Branch?       | 7.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | no
| License       | MIT

Refactored code to consistently use `$event->getAttributes($className)` instead of accessing the full array. This simplifies attribute retrieval and improves readability.

[Reference](#60395 (comment))

Commits
-------

6769c9a [HttpKernel][Security] Refactor: use `getAttributes` with argument
symfony-splitter pushed a commit to symfony/http-kernel that referenced this pull request Jul 15, 2025
…h argument (santysisi)

This PR was merged into the 7.4 branch.

Discussion
----------

[HttpKernel][Security] Refactor: use `getAttributes` with argument

| Q             | A
| ------------- | ---
| Branch?       | 7.4
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | no
| License       | MIT

Refactored code to consistently use `$event->getAttributes($className)` instead of accessing the full array. This simplifies attribute retrieval and improves readability.

[Reference](symfony/symfony#60395 (comment))

Commits
-------

6769c9a8287 [HttpKernel][Security] Refactor: use `getAttributes` with argument
*
* @author Santiago San Martin <sanmartindev@gmail.com>
*/
class UriSignerLocatorPass implements CompilerPassInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the tagged service is the way to go. If so, we don't need this compiler pass. You can register controller.is_signature_valid_attribute_listener in config and use tagged_locator() for its argument.

Copy link
Contributor Author

@santysisi santysisi Jul 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your help! ❤️ I've made the changes.

Edit: There are some errors, I'll try to resolve them tonight.

@santysisi santysisi force-pushed the feature/verify-signature-attribute branch 3 times, most recently from a7d8c95 to 1d8202c Compare July 15, 2025 13:25
@kbond
Copy link
Member

kbond commented Jul 15, 2025

Awesome, let's wait for some others to take a look. As I said, I think tagged services is the way to go but maybe someone has a different idea.

@santysisi santysisi force-pushed the feature/verify-signature-attribute branch from 1d8202c to d2ff216 Compare July 17, 2025 22:47
@alexander-schranz
Copy link
Contributor

I did not go over all comments, but for me it looks false this live inside Security namespace.

The UriSigner I can use currently without any SecurityBundle / Security services, so from my point of view the attribute should work also without any security related service and be more part of the FrameworkBundle like the UriSigner service itself.

@santysisi santysisi force-pushed the feature/verify-signature-attribute branch from d2ff216 to 35cbbc0 Compare July 18, 2025 22:42
@santysisi
Copy link
Contributor Author

I did not go over all comments, but for me it looks false this live inside Security namespace.

The UriSigner I can use currently without any SecurityBundle / Security services, so from my point of view the attribute should work also without any security related service and be more part of the FrameworkBundle like the UriSigner service itself.

Hi 👋 First of all, thank you very much for your comment 😊

You're right. When I started working on this feature, I saw this new attribute as something similar to IsGranted or IsCsrfTokenValid, which is why I initially placed it in the symfony/security-http component and the symfony/security-bundle bundle.

However, you're right that UriSigner resides in the symfony/http-foundation component and can be used without the symfony/security-bundle or any other security components. Therefore, it would make more sense for this attribute to reside in HttpFoundation and be part of the FrameworkBundle instead of the SecurityBundle.

Thanks again for the comment!

What do you think, @kbond?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants