Field Level Access with RIA Services

There are lots of reason you may need to customize the access to given fields within an entity.  For example, HIPPA compliance requires that some data not be exposed to only employees with a need to know.   It is often not sufficient to just NOT show the data in the Silverlight client, you need to not even send it over the wire. 

This example works with Silverlight 4\RIA Services Beta and Visual Studio 2010 Beta2

I built a very simple RIA Services + Silverlight 4 example to show how this could be done.   First, let’s run the app, then we can look at how we built it.

The first thing to notice is when we run it, no users are logged in, so we get no access to the data at all. 


First, let’s log in as a Rocky, who is a jr. employee at our company.  He should NOT have access to the social security numbers of employees, but the other information is good for him to be able to access.


As you can see, no SSNs are displayed.

Now, let’s log in as Billy, who is our HR Manager…  As you can see, Billy has a need to know what the SSN is for most employees, so those are visible to him.  But notice, even he can not see VP level personal information. 


OK, now let’s look at how we implemented this.   Really the key code is the domain service on which runs on the server:

  1:     [RequiresAuthentication]
  2:     [EnableClientAccess()]
  3:     public class EmployeesDomainService : LinqToEntitiesDomainService<NORTHWNDEntities>
  4:     {
  6:         public IQueryable<Employee> GetEmployees()
  7:         {
  8:             foreach (var e in this.ObjectContext.Employees)
  9:             {
 10:                 if (!this.ServiceContext.User.IsInRole("HRManagers"))
 11:                 {
 12:                     e.SSN = null;
 13:                 }
 14:                 else if (e.Title.Contains("Vice President"))
 15:                 {
 16:                     e.SSN = null;
 17:                 }
 18:             }
 19:             return this.ObjectContext.Employees;
 20:         }

In line 1, we mark this services are only accessible to users that are logged in.

In line 10, we are making sure that only the user making the request is in the role that enables them to have access to the SSN, if not, we null it out.

In line 14, we have a (lame) example to show accessing data on the entity to decide if the user should have access.  In this case, even the HRManager can’t access the VP’s SSN. 


Some notes on running the app:

  • Download the source code
  • Billy and Rocky’s passwords are “password1!”
  • Be sure the refresh the page after logging in or out
  • You can customize the roles by using the IIS Admin tool or the ASP.NET configuration properties on the Web solution



Comments (15)

  1. Tad says:

    Do you have an example of how you would handle an update?  

  2. Greg says:

    Using this technique, what happens when Rocky updates an entity?  Since the server sent null for the SSN will his update of Address, City, Birth Date cause the SSN field to be set to null in the database?

  3. Ted Howard says:

    I’ve always wanted a way to do this in a declarative or programmatic fashion. After all, what you coded is a blacklist/whitelist pattern but as a functional programmatic piece tied into the data access layer. I’ve been waiting for a declarative, programmatic ACL solution for Data Entities because I have various ideas that require it.

    Still, thanks for the code. I’m sure it’s a very common request.

  4. Ruben says:

    Doesn’t this break for queries? Suppose the Silverlight client would ask for

    from e in context.GetEmployees() select e.SSN

    Wouldn’t that cause the service to enumerate all Employee entities, clearing the SSN, and then secondly execute a SELECT SSN FROM Employees on the database? Isn’t that the point of returning an IQueryable?

  5. Brett J says:

    Thats nice and all, but it feels like a half-baked hack.  The SSN *COLUMN* should be hidden to the user. No sense in telling them "oh btw you can’t see this data".  Not to mention, they’ll go report to someone "Hey, the database deleted everyones SSN’s its all blank!"

    I don’t consider this an elegant solution if it leaves the column visible to Rocky

  6. ksang says:

    good workaround, will be nice if can use attribute to specified and remove the properties during runtime.

  7. Alex Simkin says:

    This should be handled through Presentation Model, not directly through entities.

    To hide column we can have additional IsSSNVisible property in presentation model and bind DataGridTextColumn.Visible to it.

  8. Brett Styles says:

    Maybe their should be a feature in RIA like in SYNC framework ‘DataColumns.AddRange’ where the columns can be filtered at the server. Use this with IsInRole to return only columns required as we do in SYNC now. A better option would be to declaritavely add a [roles(role1,role2)] to the Metadata DomainService class. Either way the client side grid etc would need the ability to not display a column if the column data is missing from the ria data.  

  9. Art says:

    Is there any way to do this in a base class? My existing ancient C++ BOL/DAL allows for per table / per user (or user group) security customization which is stored in the db itself.

    In other words, a sys admin can configure all CRUD operations of a table and all read/read-write/no-access privs on a per column basis based on a user’s name or domain group.

    I would like to move to entity framework / RIA and am having trouble figuring out how to do this.

  10. developer says:

    I believe in real world DBA or HR system won’t let query fields like SSN and salary. System should have views and not need to worry about application level hard coding. This could lead to big issue when adding or changing role would cause fields like ssn visible to unintended users

  11. Dan Forsyth says:

    Alex, if you leave this sort of thing to the Presentation Model, then all the info still goes across the wire and is still available to the user with little effort.

  12. ManuelFelicio says:

    How about implementing RequiresRole in entity metadata for property-level access? That way, the domain service could serialize only the properties that the user has access. I think thats very straight forward.

  13. I’ve done this using a bit of AOP magic where a WCF Channel intercepts this and decides based on role/claim if the access to some data should be ommited and in this case, it would simply set this property to it’s default value.

    That solution isn’t complete as some of you stated. Also when the user send the data back the DAL needs to avoid updating those fields. This proves to be a bit tricky as some ORMs don’t have the proper hooks. We were using a "hacked" version of Linq2SQL where we were manually doing all data modifications (yes it sounds ugly and you better not do it, don’t use L2S for big apps, we hit some road block and there was no way back)

    The other missing part is the UI. This isn’t really for security just to provide a better user experience. We have some attached behaviors that allow us to hide any UIElement based on role/claims. It looks something like

    <dg:Colum Security:Visible.ToRole="Managers"/>

    It was really easy to implement. The namespace can be confused, this isn’t about security, this is just for UserExperience.

    The only way to secure your data is not sending it as Brad mentioned, which was the actual point of the blog post.

  14. Jeremy Danyow says:

    here is a solution that won’t require any changes to the domain service’s query and update methods:


    public class DemographicService : LinqToEntitiesDomainService<DemographicEntities>


       protected override DemographicEntities CreateObjectContext()


           var context = base.CreateObjectContext();

           context.ObjectMaterialized +=

               (s, e) =>


                   if (this.ServiceContext.User.IsInRole("Administrator"))

                       return;  //user is Admin… no need to secure fields

                   Client client = e.Entity as Client;

                   if (client == null)

                       return;  //not an entity we care about securing…

                   //suppress client ssn and medical policy number

                   client.Ssn = string.Empty;

                   client.MedicalPolicyID = string.Empty;

                   //reset change tracking


                       .ChangeObjectState(e.Entity, EntityState.Unchanged);


           return context;


       . . .

       . . .      

       . . .    


  15. Excellent Jeremy, I’ll keep that in mind, it’s still a lot more work than what I would expect, but it’s a step int he right direction. I think this could be extended to provide  set of strategies that knows how to deal with different types.

    I’m think in something like

    public class ClientSecurityProvider : SecureEntityStrategy<Client> {

     public void Secure(Client entity){

       client.Ssn = string.Empty;

       client.MedicalPolicyID = string.Empty;



    Then the framework will take care of determining which strategies to call and do set the state to UnChanged.