I'm starting with Symfony 3, and I need some guidance about how to proceed with the process of implementing dynamic authorization and authentication.
First of all, the authentication bit is mostly done, I've done it according to this link from symfony docs: http://symfony.com/doc/current/security/entity_provider.html. What I'm yet to understand is how to implement the interface function getRoles() in order to return a value from the database (I have a table Role related to the User table).
Secondly, the authorization part. My application will require the end user to create his own access mechanism, in other words, I have an interface where the user creates a Role, then defines what pages that Role will be able to access and what privileges it'll have (create, read, update, delete, and so on). Afterwards the roles are attributed to the application users.
All in all it is pretty standard stuff so Symfony must have a clean way to do it. What I figured out so far is that I'll have to use ACLs, so I did as in the docs: http://symfony.com/doc/current/security/acl.html
My honest question here is: What now? What steps do I take to fully implement the authentication mechanism? What should I do now in order to persist and retrieve the access rules? How do I relate them with the user Roles?
P.S.: This question might be sort of a duplicate of some other questions here, but truth being told, those questions did not help me either, nor my scavenging in the docs did.
So, your question is very broad. Anyway it is a good question, so I'm going to try to reply.
THE AUTHENTICATION
Nothing to say here, I simply hope you used FOSUserBundle as suggested by the article itself: is the best way to implement a registration/login system in Symfony and it will give you an idea of how the entire process works. Starting from scratch if you are not a Symfony experienced developer seems to not be the best idea.
Give FOSUserBundle a try!
THE AUTHORIZATION PROCESS
About authorization you have basically two options: the use of Voters and the use of ACL.
In my experience the best option is ever the use of Voters.
In most cases, in fact, you will have a bidirectional reference (see Doctrine's documentation about this) in your entities between the User and the object on which (s)he have rights. In this case the ACL is not required and even discouraged.
In fact, the ACL does nothing more than creating a relationship between two objects (the User and the Article in your use case). To manage this relationship it uses a table in the database and so it has to query it to get the relationship and check for the authorization rights.
But if you already have a bidirectional reference between the User and the Article/Group directly in your entities, then you already have this relationship in place and so you can use Voters and the use of the ACL is superfluous and even, as said, discouraged as it is a useless duplication.
If you don't have this bidirectional relationship in your entities, then create it: it will be certainly useful in the future for other things and, anyway, you will have ever the ability to access your linked entities directly from your entities tree!
More, in your scenario, you cannot use ACL as you will have custom rights/privileges on your objects: the voters, again, are the best option to build this kind of things.
Don't use ACL, but Voters instead
HOW TO PROCEED
The first thing I would do, is to list in an interface all the available privileges: after all, they are strictly related to your application business logic, as it is not possible for a user to make someone able to do something that your app cannot do: if your application doesn't implement an editing flow, then it is not possible for a user to give someone the ability to edit an article. It's obvious.
So, something like this may be good:
interface PrivilegesEnum
{
const CREATE = 1;
const EDIT = 2;
const DELETE = 4;
const READ = 8;
const OTHER = 16;
// ... Other privileges
}
As you can see, I've given a numeric value to each privilege: this will give you the ability to use bitmasks that is a really powerful mechanism to manage this kind of things: it allows you to use only one field in the database to list all the privileges.
You can read more about bitmasks here:
https://www.google.it/search?q=bitmask+php+example
How to implement a bitmask in php?
Why should I use bitwise/bitmask in PHP?
http://alanhollis.com/a-quick-guide-to-using-bitmasks-for-permissions-in-php/
https://codereview.stackexchange.com/questions/1509/php-bitmask-class
https://www.google.it/search?q=php+bitmask+theory
How to implement a bitmask in php?
http://php.net/manual/en/language.operators.bitwise.php
http://php.net/manual/it/language.operators.bitwise.php
https://code.tutsplus.com/articles/understanding-bitwise-operators--active-11301
https://code.tutsplus.com/articles/number-systems-an-introduction-to-binary-hexadecimal-and-more--active-10848
I used this system in the past and those are some useful links I collected. They might help you!
BUILD A FORM TO LIST PRIVILEGES
Another thing you may find useful is a FormType to list your available privileges: you can do this writing a simple custom FormType.
HOW TO MANAGE ROLES
To manage roles read how Roles are managed by the Security Component and in FOSUserBundle (on Stackoverflow)
THE RELATIONSHIP BETWEEN USERS AND GROUPS AND ARTICLES
Once you reached this point you should have some more entities, read more about Doctrine relationship mechanisms knowing it better and you should be able to relate your users with their role, their group and the articles.
Anyway you will have all the required conceptual and practical tools needed to think better at your concrete implementation.
FINAL NOTE
As you can see, implement such type how authorization process isn't so simple.
I suggest you to think very carefully if it is really required in this stage of the development of your app, because if you can defer it in the future, then I suggest you to do it.
If you want to go online as fast as possible, implementing this system will require a lot of time to learn, implement, debug and refact the code (I'm speaking of weeks, not days!).
So, if you have all this time, then, go to implement this system. But if you feel you haven't all this time, then go with a more "static" system, go online, and then make it more "dynamic".
After all, this is the Lean Startup era!
Good luck!
Related
In my Laravel application, I have a Model called Project which has, among others, a property called approved_at. There is also a ProjectController, which contains the usual methods *(index, show, create, update, edit...)
Now, the user that created the Project can edit it (modifying its other attributes), but only some "staff" members have the right to approve one.
From what I understand, there can be two ways to handle the approval operation:
Both users, from their respective views (let's call them edit and approve) fire the ProjectController#update method, which will internally distinguish who-can-do-what by means of authorization or policies;
I create a new ProjectApprovalController, with its own update method, and check the authorization at the endpoint (eg, /projects/{id}/approve).
What is the best approach to tackle this behaviour?
It depends on what do you want to do with this in the future. If there would be some kind of extra steps to do behind the approve method for example: connection to external micro service to check if project exists in external database with subsidies then you should definitely split it.
If you don’t mind I would suggest you to not focus so much on the implementation. Your application should be removable as fast as you build it. There is a great presentation about this from Greg Young called ‘The Art of
Destroying Software’. Be more focus to build your solution with SOLID principles and test the behaviour of this method to make it easier to replace in the future.
to answer your question, second option is more restful approach, but I don’t know if that is not shooting to fly with a cannon
How do you handle situation with blameable in the DDD way?
Ofcourse we can ignore some things, but i think that when entity need some tracking (creator, updater, time updated / created) it should be in the class that actually performs some actions on entity.
For example we have post and user, what whould be the correct way?
$post = new Post();
$post->create(); // here we can set some created_id and
other attributes by using mixins or traits like some fw do
Or it is better like this:
$user->createPost($post);
$user->update($post);
As for me second is better, even when we need to track changes that does not apply to post directly, for example:
$post->doSomethingWithPost();
$user->updatePost($post);
Seems like blameable just throws out one important entity - user who manages some things on entities.
Ofcourse we should not overcomplicate things, but usually when blameable is implemented, entity from which you will get id is a logged in user, that is incorrect to the bounded context.
Here it is some Blogging Context, where user of this context updates post and not some authenticated user.
Whats your thoughts on this one? Is there some similar questions that i maybe missed?
All your examples seem like they are not designed with the DDD principles in mind. The first indicator to me is the usage of a $user variable. In 99% of the cases this is too generic to really capture the intent of a given Model. I think there are hidden concepts that would first have to be made explicit. I think along the lines of RegisteredAuthor and Administrator. At least that's what I understand from:
Here it is some Blogging Context, where user of this context updates post and not some authenticated user.
Another question is how can a "user of this context" not be authenticated? How do you know who he is?
In general in an application that explicitly requires User management we normally have something like an IdentityContext as a supporting Sub Domain. In the different contexts we then have other Models like Author or BlogAdministrator holding a reference to the User's identity (UserId) from the IdentityContext. The Red Book has some nice examples on how to implement this.
To answer the question on how to track who changed something and when:
This concept is also referred to as Auditability, which in most revenue relevant parts of system is actually a must once your organization is reaching a certain size. In this scenario I actually always recommend an Event Sourcing approach since it comes with auditability batteries included.
In your case it would actually be enough to either capture the executing UserId as Metadata to the commands like WritePostCommand or ChangePostContentsCommand or use the UserId in a RequestContext object that knows about the execution context (who was sending this command, when was it sent, is this user allowed to execute this use case).
You can then, as Alexander Langer pointed out in the comments, just use this metadata inside your Repositories or Handlers to pass the information to the Aggregates that need it, or could even just send them to an audit log to not pollute your Domain Model with this responsibilities.
NOTE: Generally I would not use the DoctrineExtensions like Blameable in your Domain Model. They depend heavily on Doctrine's Event system, and you do not want to tie your Model into an Infrastructure concern.
Kind regards
I am quite new to DDD and have some fundamental problems that i cant really understand.
Consider we have a User entity. A User has some Friend's (one to Many).
There are 2 possible solutions to fetch the friends.
Solution 1:
user.getFriends()
The Problem here is that all the friends have to be loaded or I am forced to use a Proxy.
If i use a Proxy it feels for me like cheating because the entity must not have an instance of the Repository. Can the Proxy have one?
Solution 2:
Avoid the getFriends Method and load the Friends Based on the User Repository, like:
userRepository.getFriendsOf(user)
This could sometimes be a good idea, but where to stop here? Whats about an AddressRepository for accessing user Addresses, or ?
I think you should look at it from perspective of Aggregate Roots.
In case of user.getFriends() - the user seem to be AR with associated friends which I don't think is correct. The definition of AR says "that we treat as a unit for the purpose of data changes". Friends are outside of the Boundary of user AR.
Considering the above the other option seem better - userRepository.getFriendsOf(user)
I'm not sure that either of them are correct. I think from a DDD point of view, the code is supposed to use the Ubiquitous Language of the domain. In that regard, getters are frowned upon.
Why are you getting the friends of a user? The public methods of User should reflect the ubiquitous language.
For example if your domain is a social networking site, users should have methods to update status which will internally notify friends etc. How the User knows who its friends are or how they are queried is hidden as an implementation detail.
One thing to keep in mind is that you shouldn't use your domain model for querying. So you do not want to be lazy-loading or applying any other fetching strategies.
You also need to identity your aggregates. An aggregate is loaded in its entirety from the data store.
In your case if a Friend class can only ever exist in the context of a User then it is part and parcel of the User and its life-cycle is linked to that of the User. That means that when the User is deleted (conceptually, as one probably would not want a hard delete) then the associated Friend instances are deleted also.
So if a Friend represent the association between users then it probably only contains the User Id. So you could go with a list of Ids in that case. This would depend on your domain.
I would guess that you very rarely would need to load the entire list of User instances that are friends of another user. If you need related data you could implement a light-weight query layer.
Lets say i have a number of types of documents in my system. I want to restrict access to them based on three aspects: user roles, ownership and relevance of user to the object. So for example ROLE_DOCUMENTTYPE1READ will grant user a right to read document (other roles such as ROLE_DOCUMENTTYP1WRITE will grant RW rights). Presence of connection to the document (if document has user in his 1:M related_users field) gives user right to add comments to document. And if user is owner of the object he can edit it entirely.
I can easily implement it in controller or even create a trait or something like this, but it would be too ugly and also tedious because there will be lots of entities and actions upon them, not only regular CRUD, but also additional one's that change certain fields. I want to know how usually such things should be done. Maybe there are some architectural patterns that help in this situation? Right now, as i already said, i'm going to check in every action if user is related to entity or if he is even its owner or has said roles.
You can take a look at the JMSSecurityExtraBundle and the Expression-based Authorization Language. They allow to perform complex access decision checks, and because they are compiled down to raw PHP, they are much faster than the built-in voters.
I'd like to ask other opinions about code structuring of business logic on Laravel applications, mainly regarding permissions at the row level.
For those that don't know it, Laravel is a MVC framework for PHP, much like Rails.
For the sake of understanding, let's suppose a multi-tenant application where each user has his own albums and pictures, so far so good.
Now, each user can invite others to collaborate (by uploading photos) into his album.
Both, the album's owner and collaborator that uploaded the picture may be able to delete or update information about that picture.
Only the owner may edit the album and invite new collaborators.
Collaborators can remove themselves of the album if they want so.
Pinterest should be a nice example of something similar, but our application is probably 3 or 4 times more complex.
The question is: where should I handle that kind of logic?
Laravel proposes the approach of having repositories, entities and services, which I don't fully understand, probably because of the lack of good examples. So the obvious first choice to meet those deadlines was to put it all on controllers (ew!). Now, digging into refactoring, there are many possible ways to un'spaghettize our code:
I've seen people implement ACL at row level (looks kinda dumb and overkill)
It would be possible to turn models into behavior aware objects and not only data containers, something like $album->add_photo($photo) and check permissions at that function
It would also be possible to override model's save method and do there those checks
Or, follow the Laravel proposed road of having separate layers of concern
I suppose that having methods like $album->can_be_edited_by($user) may simplify the displaying of 404 erros on routes not allowed, hiding view's links as well as validating before saving the models
Which would you recommend, and does anyone know any simple, but understandable, example of repositories, entities and services not using .NET?
Thanks!
Edit: I guess that a full ACL system would cause excessive overhead, since there may be thousands of resources associated with each user, but only one role per kind of association. For instance, pictures will have an uploader_id and albums will have an owner_id.
I could be wrong but I think ACLs are OBJECT based permissions (i.e., a user can or can't delete photos in GENERAL). What you want is more custom MODEL based permissions (row level like you said), i.e., a user can delete photos that they themselves created (SPECIFIC ones).
Most Laravel packages are designed for object based permissions I think, but not https://github.com/deefour/authorizer - this one is a great hidden gem. We don't use it in our project but I found that it really covers all the bases we'd need.
We have really advanced model permissions on our app, I have them scattered throughout my models, but I take a very model centric approach, which isn't necessarily very "laravel-esque". In your example with delete, I would override the delete method in your model or listen for the eloquent event and prevent it there. If you have to prevent read/write on certain attributes you could even do that by extending your validator or using custom mutators/getters, serializers or listening on events. More on where to add business logic in my question/answer here: https://stackoverflow.com/a/27804817/796437
I'm still trying to find the best approach, if I do I'll update this - but thought I'd post.
In Laravel you can use Policies or use solutions, like Symfony Voters.
For Laravel exists same package - Laravel Simple Voters.
Using this, you can check access to custom objects, looks like this:
Access::isGranted('edit', $post) // current user can edit this post?
You can put this logic, to example, into middleware, if you wish check requests to controllers.