Dynamics_crm_logoRecently, I worked on a project that required me to programmatically set up Field Security in Microsoft Dynamics CRM 2011. Field Security allows you to designate selected fields (of selected entities) to be “secure” – which means only a certain group of users can have access to it. This access is made up of three operations: read, update, and create, each of which can be granted separately. MSDN does a pretty good job giving an overview of how it works: https://msdn.microsoft.com/en-us/library/gg309608(v=crm.5).aspx  

The set up requires 3 general steps:

  1. Enable Field Security for a Field – You will need to decide which fields you want to secure and enable Field Security on them.
  2. Create Field Security Profile(s) – Each Profile defines the permissions (Read, Update, and/or Create) on each security enabled field.
  3. Associating Field Security Profile(s) to Users and/or Teams – this is what actually gives users permissions to access the fields.

These steps can be done via the web user interface, but I’m showing how to do it programmatically so that the process is repeatable and stored away in a code repository.

The code here is written for CRM 2011, but I imagine that unmodified it will work for CRM 2013 as well since the SDK didn’t change much. I will update this article once I have tested and made sure that this is the case.

1. Enable Field Security for a Field

To programmatically create a field in an entity, you’re probably building a Microsoft.Xrm.Sdk.Metadata.AttributeMetadata object, packing it into a Microsoft.Xrm.Sdk.Messages.CreateAttributeRequest object, and finally executing that request.

In order to enable Field Security on the new field, just set the IsSecured property of your AttributeMetadata to true. So if you were creating a text field, your code would look like this:

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;
StringAttributeMetadata metadata = new StringAttributeMetadata()
{
   SchemaName = "pre_ExampleTextField",
   DisplayName = new Label("Example Text Field", 1033), // 1033 = English
   RequiredLevel = new AttributeRequiredLevelManagedProperty(AttributeRequiredLevel.SystemRequired),
   Description = new Label("Field description", 1033),
   MaxLength = 300,            // Maximum characters for the text field
   Format = StringFormat.Text, // Other options are Email, Phone, URL, etc
   IsAuditEnabled = new BooleanManagedProperty(true),
   IsSecured = true            // Set IsSecured to true to enable Field Security
};

CreateAttributeRequest request = new CreateAttributeRequest()
{
   EntityName = "pre_exampleentity",
   Attribute = metadata
};

orgService.Execute(request);   // orgService is of type IOrganizationService

If you have an existing field that you want to enable Field Security on, just use a UpdateAttributeRequest instead of a CreateAttributeRequest:

using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Sdk.Messages;
AttributeMetadata metadata = new AttributeMetadata()
{
   LogicalName = "pre_ExampleExistingTextField", // For updates, specify LogicalName instead of SchemaName
   IsSecured = true
};

UpdateAttributeRequest request = new UpdateAttributeRequest ()
{
   EntityName = "pre_exampleentity",
   Attribute = metadata
};

orgService.Execute(request); // orgService is of type IOrganizationService

By this same pattern, you can disable Field Security on a field by setting IsSecured to false in your metadata.

2. Create Field Security Profile(s)

Like nearly everything else in CRM, both Field Security Profiles and the Field Permissions they include are entities. So you will create them the same way you would create any other entity record:

using Microsoft.Xrm.Sdk;
Entity profile = new Entity("fieldsecurityprofile");
profile["name"] = "Profile 1";
profile["description"] = "Description of profile 1";
Guid profileId = orgService.Create(profile); // orgService is of type IOrganizationService

Entity permission = new Entity("fieldpermission");
permission["fieldsecurityprofileid"] = new EntityReference("fieldsecurityprofile", profileId);  // Reference to the profile you just created
permission["entityname"] = "pre_exampleentity";
permission["attributelogicalname"] = "pre_exampletextfield";
permission["canread"] = new OptionSetValue(FieldPermissionType.Allowed); // Allowed and NotAllowed are the only two values of the FieldPermissionType enum
permission["cancreate"] = new OptionSetValue(FieldPermissionType.NotAllowed);
permission["canupdate"] = new OptionSetValue(FieldPermissionType.NotAllowed);
Guid permissionId = orgService.Create(permission);

You will need to create a Field Permission for every Field Security enabled field that the Profile needs access to. Important: If you don’t create a Field Permission for a particular Field Security enabled field, then that Profile will by default not have any permission for the field.

You will update or delete Field Security Profiles and Field Permissions just like you would any other entity record, you just need the GUID of the profile or permission.

3. Associating Field Security Profile(s) to Users and Teams

Finally there are built-in N:N relationships between Field Security Profiles and Users/Teams: systemuserprofiles_association and teamprofiles_association respectively. So to associate them, just create these relationships the same way as you would with any other N:N relationship. Use the Guid of the Field Permission(s) that was created above in step 2.

using Microsoft.Xrm.Sdk;
// If you were associating a profile to a User:
Relationship relationship = new Relationship("systemuserprofiles_association");
EntityReferenceCollection collection = new EntityReferenceCollection();
collection.Add(new EntityReference("fieldsecurityprofile", profileId));  // profileId is the GUID of the security profile to associate.
collection.Add(new EntityReference("fieldsecurityprofile", profileId2));
orgService.Associate("systemuser", userId, relationship, collection);    // userId is the GUID of the User we are associating the profile to.

// If you were associating a profile to a Team:
Relationship relationship = new Relationship("teamprofiles_association");
EntityReferenceCollection collection = new EntityReferenceCollection();
collection.Add(new EntityReference("fieldsecurityprofile", profileId));  // profileId is the GUID of the security profile to associate.
collection.Add(new EntityReference("fieldsecurityprofile", profileId2));
orgService.Associate("team", teamId, relationship, collection);          // teamId is the GUID of the Team we are associating the profile to.

And that’s it. If you browse to Administration – Field Security Profiles in your CRM organization, you can see the profiles that you just programmatically created.

Final Notes

Some final notes to keep in mind as well as observations about how Field Security in CRM works:

  • Don’t forget to give users permissions on the underlying entities as well – having access to a field via a Field Security Profile is useless without also having access to the field’s entity.
  • By default, all users and teams have no permission to any Field Security enabled field. So if there was a field that you need to hide from only one user, then you will need to create a Field Security Profile that does have permission to that field and somehow associate it with everybody except the one user in question.
  • CRM will “remember” the permissions on a Field Security enabled field even if you disable Field Security on that field in case Field Security is re-enabled later. This comes in handy if you have created a few Field Security Profiles that have permissions on a particular Field Security enabled field, but then accidentally disable Field Security on that field. When you re-enable Field Security on that field, all of your Field Security Profiles will still have the original permissions on that field.

Hope this proves useful for someone! Feel free to leave a comment if there’s any questions.