I'm working on building an API backend with Symfony3 and have a question about how to apply field level permissions to the PUT endpoint for updating an object (User in this example).
My User entity has multiple fields, firstName, lastName, username, etc.
If a PUT request is sent to the /users/{userId} endpoint, I deserialize the request JSON into an array, pass the array (and the User fetched from the database) into a normalizer which applies the request data to the User properties.
I would like an ADMIN to be able to update all fields, but the user themselves to only be able to update their first and last names.
So somewhere in my code I need to check before I apply the updates to the User object, e.g. if the username field is present in the PUT request, I need to check if the requesting user is an admin before applying that update to the user object.
Injecting security into the normalizer seems like an obvious solution, but feels like security should not be a concern of the normalizer.
I could check the permissions after deserializing the request, and before passing to the normalizer, and then just remove fields from the array if the user does not have access, e.g. if not admin remove [username] from array.
Looking for thoughts/suggestions on the right way to accomplish this....
Thanks!
Wanted to post some feedback I got in #symfony IRC:
I would not have the normalizer write into the user. I'd have the normalizer generate a DTO, which you would then validate given the permissions of the target user and user taking the action.
If that validator fails, throw the whole thing out and return a permission denied error, otherwise apply the DTO to the user and persist it.
the "validator" could be a form (build a form with acceptable to modify fields given active and target user; form is not valid if there are extra fields submitted). Or it could be a security voter, or your own custom mechanism.