Authorization is still a dilemma in development of business applications. ASP.Net provides the membership provider which supports user/role membership and domain service also supports it so you can use UserContext in the client side and User.IsInRole() gives you the user’s role memberships.
This looks good, but is certainly not enough. First of all authorization can be quiet complex such that authorization rules should be applied on a record-by-record basis and also the authorization rules can be more complicated than a single IsInRole check. For example a use in certain rolls can access a filed of a record only if the state of the user (e.g. Queensland) is similar to the state of the object (e.g. Pharmacy in Queensland).
Currently, you have to implement authorization on the server-side. Then you have to implement the same thing in your database using SQL techniques and you have to implement all the scraps again in the client side to figure out which filed or views are visible and which are read only!!! This is owe-full, isn’t it?
The way I would like to do all my authorization is as follows:
- In the service side I want to be able to assign authorization attributes to the model’s metadata, (similar to authorized attribute in MVC which you can apply to controllers) . I should be able to have custom authorizations.
- In the service side for Queries, I want to have a filter athorized method, which get’s an IEnumerable of roles and/or users and filters the records, it should remove the records that user can not have access to, scrap the fileds that user has no access to (if he has access to the record) and attach an access attribute to the whole collection and each individual field (if different from the collection).
- In the service side for Commands, I want to have a check authorized method, which get’s an IEnumerable of roles and/or users, and the object which is supposed to be changed and returns a boolean identifying if is allowed or not.
- It would be great if in the service side, exists an IsAllowed method which get’s the data context and a list of users and roles and returns if the modifications in the context can be authorized.
- In the client side, there should be an attribute attached to each returned object from the service. The attribute contains the fields the accessible fields. For example “Name” is visible and read-only, “DateOfBirth” is visible and editable, etc. This attribute can be used to change the view appearance for visible and read-only fields. For MVVM, the visibility and edit-ability of parts of a view can be bound to these attributes (of course through a method or using a converter).
- In the client side, there should be a service that generates a dummy empty object with it’s authorization attributes to be bound o the view for creating a new object.
- In the Database side, a function should be automatically generated, to do the authorization. Although this may look impossible in presence of custom authorization, there are ways to do that: First, to use a provider model and force user to implement the same custom authorization as SQL function. Second, (only for SQL Server) use CLR and create a CLR class that uses the same service side methods for this reason.
Extra benefit of using this approach is that, the authorization rules can be changed without any change to the client side. Full loose coupling!
Note that although this approach provide full end to end authorization by only defining rules at one place (if implemented completely) effectively, it can not be efficient (specially in DB side). User still should use their own personalized queries to query large datasets. However, his job can be simplified by shortlisting the results by more general rules, and fine tune authorization by filtering using the generated authorization functions.
I try to implement this in my spare time and update implementation details in the blog.