Skip to content

[Security][SecurityBundle] User authorization checker #48142

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

Merged
merged 1 commit into from
Dec 7, 2024

Conversation

natewiebe13
Copy link
Contributor

@natewiebe13 natewiebe13 commented Nov 7, 2022

Q A
Branch? 7.3
Bug fix? no
New feature? yes
Deprecations? no
Tickets Fix #43372
License MIT
Doc PR symfony/symfony-docs#18033

isGranted() assumes that it's checking against the currently logged in user. This provides the same functionality to check against a user during times when there isn't a session (cronjobs/commands, message queue, etc.) or for a different user than the one logged in.

Having this functionality allows for removing the dependency on sessions entirely for services reducing the number of issues that come up during a project because some underlying function was session dependent.

@carsonbot

This comment was marked as outdated.

Copy link
Member

@derrabus derrabus left a comment

Choose a reason for hiding this comment

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

Thank you for your PR.

@carsonbot carsonbot changed the title User authorization checker [Security][SecurityBundle] User authorization checker Nov 8, 2022
@derrabus derrabus modified the milestones: 6.2, 6.3 Nov 8, 2022
|| AuthenticatedVoter::IS_AUTHENTICATED === $attribute
|| AuthenticatedVoter::IS_IMPERSONATOR === $attribute
|| AuthenticatedVoter::IS_REMEMBERED === $attribute) {
throw new InvalidArgumentException(sprintf('"%s" cannot decide on attribute "%s" as it requires checking the session. Use "%s" instead.', self::class, $attribute, AuthorizationCheckerInterface::class));
Copy link
Member

Choose a reason for hiding this comment

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

This check should probably be done in the AuthenticatedVoter when passing it a UserAuthorizationCheckerToken instead of making a special case here (which would not work if a custom voter uses a delegated check on the authentication level as part of their logic, as this would pass the UserAuthorizationCheckerToken to the AuthenticatedVoter without going through this UserAuthorizationChecker)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Next push will include the voter abstaining if the token is marked with the interface. I feel like it's probably still useful to know if you're using the checker improperly, rather than getting unexpected results. Any concerns with leaving this check in as well?

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure abstaining is always the right answer either though (the final decision won't ever be an abstain)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True, I guess technically since the token is internal, it really shouldn't get this far. I'm good with moving the exception into the voter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

@@ -79,6 +79,15 @@ public function isGranted(mixed $attributes, mixed $subject = null): bool
->isGranted($attributes, $subject);
}

/**
* Checks if the attributes are granted against the user and optionally supplied subject.
Copy link
Member

Choose a reason for hiding this comment

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

this should explicitly document the differences with isGranted() IMO, to make its limitation clear

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated, is this what you were looking for?

@natewiebe13 natewiebe13 requested review from derrabus and removed request for wouterj and chalasr November 8, 2022 15:56
@natewiebe13 natewiebe13 force-pushed the user-authorization-checker branch from 8c0fc43 to 60d5d92 Compare November 8, 2022 18:03
@natewiebe13 natewiebe13 requested a review from derrabus November 8, 2022 20:34
Copy link
Contributor

@HeahDude HeahDude left a comment

Choose a reason for hiding this comment

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

Nice feature, thanks!

@VincentLanglet
Copy link
Contributor

This would be a great feature. What is missing to this PR @natewiebe13 @derrabus @stof ?

@derrabus
Copy link
Member

What is missing to this PR

Another round of reviews, I suppose. I'd very much like to see this feature shipped as well.

Copy link
Contributor

@94noni 94noni left a comment

Choose a reason for hiding this comment

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

Would love to see this land on 7.2 :)

@fabpot fabpot modified the milestones: 7.2, 7.3 Nov 20, 2024
@natewiebe13 natewiebe13 force-pushed the user-authorization-checker branch 2 times, most recently from 8742756 to 260927f Compare December 3, 2024 20:51
@natewiebe13
Copy link
Contributor Author

Rebased for 7.3 🤞

@derrabus derrabus force-pushed the user-authorization-checker branch from 260927f to 3979093 Compare December 7, 2024 13:34
@derrabus derrabus force-pushed the user-authorization-checker branch from 3979093 to 096bfaa Compare December 7, 2024 13:41
@derrabus
Copy link
Member

derrabus commented Dec 7, 2024

It took time, but here we go, this is in now. Thank you very much @natewiebe13.

@derrabus derrabus merged commit 4612ff2 into symfony:7.3 Dec 7, 2024
8 of 11 checks passed
@natewiebe13 natewiebe13 deleted the user-authorization-checker branch December 7, 2024 14:12
fabpot added a commit that referenced this pull request Dec 9, 2024
…rvice façade (derrabus)

This PR was merged into the 7.3 branch.

Discussion
----------

Remove ServiceSubscriberInterface implementation from Service façade

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | Follow-up to #48142
| License       | MIT

#48142 added a `ServiceSubscriberInterface` implementation to our `Security` façade, but that implementation is never consumed. If we did that, we would fail because the `security.firewall.event_dispatcher_locator` is hinted as a generic `ServiceLocator` which we cannot autowire. This is why I'd like to remove that implementation.

Commits
-------

a185129 Remove ServiceSubscriberInterface implementation
*
* This should be used over isGranted() when checking permissions against a user that is not currently logged in or while in a CLI context.
*/
public function userIsGranted(UserInterface $user, mixed $attribute, mixed $subject = null): bool
Copy link
Member

Choose a reason for hiding this comment

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

isUserGranted no ?

Copy link
Member

Choose a reason for hiding this comment

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

👍 discussed internally, either this or isGrantedForUser()

Copy link
Member

Choose a reason for hiding this comment

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

see #59214

fabpot added a commit that referenced this pull request Dec 16, 2024
…rantedForUser() (xabbuh)

This PR was merged into the 7.3 branch.

Discussion
----------

[Security][SecurityBundle] rename userIsGranted() to isGrantedForUser()

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | see #48142 (comment)
| License       | MIT

Commits
-------

278d62c rename userIsGranted() to isGrantedForUser()
chalasr added a commit that referenced this pull request Dec 22, 2024
…)` function (natewiebe13)

This PR was merged into the 7.3 branch.

Discussion
----------

[SecurityBundle][TwigBridge] Add `is_granted_for_user()` function

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Issues        | N/A
| License       | MIT

Twig function to accompany #48142

Commits
-------

82ff3a5 Add is_granted_for_user() function to twig
symfony-splitter pushed a commit to symfony/twig-bridge that referenced this pull request Dec 22, 2024
…)` function (natewiebe13)

This PR was merged into the 7.3 branch.

Discussion
----------

[SecurityBundle][TwigBridge] Add `is_granted_for_user()` function

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | yes
| Deprecations? | no
| Issues        | N/A
| License       | MIT

Twig function to accompany symfony/symfony#48142

Commits
-------

82ff3a5e64f Add is_granted_for_user() function to twig
javiereguiluz added a commit to symfony/symfony-docs that referenced this pull request Jan 3, 2025
…tion (natewiebe13)

This PR was merged into the 7.3 branch.

Discussion
----------

[Security] Add tip for using new isGrantedForUser() function

Adds tip for using new `isGrantedForUser()` function from symfony/symfony#48142

Commits
-------

c196b44 Add tip for using new isGrantedForUser() function
chalasr added a commit that referenced this pull request Feb 21, 2025
…kas)

This PR was merged into the 7.3 branch.

Discussion
----------

[Security] Improve DX of recent additions

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | not really
| Deprecations? | no
| Issues        | -
| License       | MIT

This is a follow up of #48142 and #59150 which were merged recently into 7.3.

Summary of the changes:
- `UserAuthorizationChecker`, the implementation of the corresponding interface is merged into the existing `AuthorizationChecker`.
- `AuthorizationChecker::isGranted()` is made aware of token changed by its new `isGrantedForUser()` method, so that calls to `is_granted()` nested into `is_granted_for_user()` calls will check the provided user, not the logged in one.
- Replace the many arguments passed to `IsGranted`'s closures by 1. a new `IsGrantedContext` and 2. the `$subject`. This makes everything simpler, easier to discover, and more extensible. Thanks to the previous item, IsGrantedContext only needs the auth-checker, not the access-decision-manager anymore. Simpler again.
- Fix to the tests, those were broken in both PRs.

Commits
-------

aa38eb8 [Security] Improve DX of recent additions
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.

Using isGranted() without a Session