3

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.

Eduardo
  • 277
  • 1
  • 6
  • 17

1 Answers1

3

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:

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!

Community
  • 1
  • 1
Aerendir
  • 6,152
  • 9
  • 55
  • 108
  • 2
    Slow clap for the answer! It is a gold mine for anyone interested in Authorization / Authentication topics... – Jovan Perovic Jan 10 '17 at 12:00
  • Thanks for the great reply, I'll be doing it and I'll give you my feedback as soon as possible. I know it will take a while to implement this properly, but I actually need it. I've already done this from scratch with Java, but I wasn't using frameworks which bind you so much in doing everything their way. So I have a good hold of the logic behind it (I was actually doing it again and trying to just 'override' the Symfony security configs, but I know it is a no go). Basically I was just struggling with the Symfony way to do it. – Eduardo Jan 10 '17 at 20:52
  • Well, voters... To be honest just saying "use voters" do not really solve my problem, maybe I just did not understand the documentation about them. And I think I realized why, so let me ask you a question: Do I need to create a voter for every object? – Eduardo Jan 10 '17 at 21:59
  • 2
    To a broad question the only answer is a broad one. I'm sorry, but that's how it is... I hadn't tell you simply "use voters", but I've explained you WHY you should use them instead of ACL. And, as frameworks do, Stackoverflow too has its own rules: ask code problems, with code examples, to solve concrete, single, real problems. I've replied to a question that is very very broad, full of different topics and put you on the right path. – Aerendir Jan 10 '17 at 22:40
  • 1
    Now, you are asking me another question: I cannot reply. And I cannot simply because this is another topic and because I haven't the answer: you should first try, then fail, then ask. And in the process you'll figure out how you want your software be written. You can write only one Voter or you can write 10 or 100. I don't know. I know nothing about your software, about the code you wrote, the way you wirte your code. Nothing. I'm sorry. Anyway, maybe this will help you: http://stackoverflow.com/questions/28179013/using-one-class-voter-for-many-entities Try, and then ask again – Aerendir Jan 10 '17 at 22:43