Salesforce: Enforcing Security in Apex

Sharing is Caring

Salesforce allows data access to be specified at the object level, field level, and finally record level. To get listed on the AppExchange an application has to go through a really extensive security review process. As part of the review process Salesforce confirms that security permissions are being adhered to. Unfortunately, apex doesn’t automatically follow the rules.

Visualforce does if the fields are being referenced in the page.

Object Level Security

Object Level security, also known as CRUD, is used to limit access to an object. It’s pretty granular as you can control whether an object can be created, edited (updated), read, or deleted.

An example of how to enforce READ in apex on the opportunity can be seen below:

private List<Opportunity> getOpportunities() { 
    List<Opportunity> retVal = null; 
    if (Schema.sObjectType.Opportunity.isAccessible() ) {
        retVal = [select Id
                        ,Name
                        ,Amount from Opportunity Where IsClosed = false Limit 100];
    }
    
    return retVal;
}

Naturally, it’s rare that we would also just want to get a list and only ever do a READ only operation on them. Instead we would probably need to do something more like this:

private List<Opportunity> getOpportunities() {
    List<Opportunity> retVal = null;
    
    if (Schema.sObjectType.Opportunity.isAccessible()
        && Schema.sObjectType.Opportunity.isDeletable()
        && Schema.sObjectType.Opportunity.isUpdateable() ) {
        retVal = [select Id ,Name ,Amount from Opportunity Where IsClosed = false Limit 100];
    }
    
    return retVal;
}

Please note that you should probably throw some sort of exception and display an error to the user. Also note that this solution is in no way complete, because it completely ignores Field Level Security.

Schema.sObjectType is used frequently in dynamic apex and has lots of other very useful methods.

Field Level Security

Field Level Security, also known as FLS, is a technique for limiting a user’s access to certain data. For example, it may not make sense for a Support Rep to see how much of a commission a Sales rep was paid or what the expected revenue is.

Field level security is usually set by the administrator and can be set in a couple of different ways: on the profile or through permission sets.

I previously wrote a blog post about Basic Security in Salesforce and how the permissions are set and where they are set.

Here’s a full example of how to get a list of opportunities that could be READ, Updated (Edited) or Deleted entirely.

If later in the code, your user will need to update or delete values you need to make sure you call isDeletable() and isUpdateable() for each value. I always check if isAccessible() when querying.

private boolean isObjectVisibleToUser() {
return Schema.sObjectType.Opportunity.isAccessible()
    && Schema.sObjectType.Opportunity.isDeletable()
    && Schema.sObjectType.Opportunity.isUpdateable(
}
 
private boolean isFieldsVisibleToUser() {
    return Schema.sObjectType.Opportunity.Fields.Id.isAccessible()
        && Schema.sObjectType.Opportunit.Fields.Id.isDeletable()
        && Schema.sObjectType.Opportunity.Fields.Id.isUpdateable()
        && Schema.sObjectType.Opportunity.Fields.Name.isAccessible()
        && Schema.sObjectType.Opportunit.Fields.Name.isDeletable()
        && Schema.sObjectType.Opportunity.Fields.Name.isUpdateable()
        && Schema.sObjectType.Opportunity.Fields.Amount.isAccessible()
        && Schema.sObjectType.Opportunit.Fields.Amount.isDeletable()
        && Schema.sObjectType.Opportunity.Fields.Amount.isUpdateable()
}
 
private List<;Opportunity>; getOpportunities() {
    List<;Opportunity>; retVal = null;
    
    if (isObjectVisibleToUser() && isFieldsVisibleToUser() ) {
        retVal = [select Id
            ,Name
            ,Amount from Opportunity Where IsClosed = false Limit 100];
    }
 
    return retVal;
}

As you can see this is really quite messy and results in a lot of duplicate code. Every time we need to add or remove a field we would need to change multiple places. We could make this a lot more generic and make it reusable in other situations.

Sharing is Caring

Brian is a software architect and technology leader living in Niagara Falls with 13+ years of development experience. He is passionate about automation, business process re-engineering, and building a better tomorrow.

Brian is a proud father of four: two boys, and two girls and has been happily married to Crystal for more than ten years. From time to time, Brian may post about his faith, his family, and definitely about technology.