So-Called Advent Calendar Day 20 - Securing Your SOQL

In the spirit of the holiday season, this is a series of short blog posts covering random things I have learned while doing Salesforce development, one for each day of Advent.

A common misconception I have heard is that using with sharing when declaring an Apex class enforces security in your code. However, that only enforces sharing rules, i.e. it prevents the running user from querying and updating records that they do not have sharing access.

It DOES NOT enforce FLS. Even if the running user does not have read/edit access to a field on an sObject, when that field is queried in Apex, that field will be populated. Using <apex:outputField> in Visualforce will prevent the user from seeing the value, but the value is still fetched in apex.

There are two security mechanisms in Apex that are in beta that can really help you enforce field level security in your code.

The SOQL clause WITH SECURITY_ENFORCED
The stripInaccessible method

Salesforce documentation does a great job outline how they work, but they are not interchangeable.

WITH SECURITY_ENFORCED

When the clause WITH SECURITY_ENFORCED is added to SOQL query, if the running user does not Read access to any of fields in the SELECT statement, an exception will be thrown. For example

List<Account> accounts = [SELECT Website FROM Account WITH SECURITY_ENFORCED];

This query will throw an error if the running user does not have Read access to the Account.Website field. It only applies to the SELECT statement. For example:

List<Account> accounts = [SELECT Id FROM Account WHERE Website = 'socalledprogrammer.com' WITH SECURITY_ENFORCED];

Since Account.Website is not included in the SELECT statement, this won’t throw an error even if the running user doesn’t haven’t Read access to the field.

So with a single statement, you can start enforcing field level security in your queries. However, the downside is that the query fails hard and the error message does tell you what field is needed. Also, I have seen it used with queries that try to emulate SELECT *, which means that EVERY field on the object needs to be readable by the running user in order to run at all. So while the query is secure, to get the app to run at all you’d have to grant access to every field on the object, defeating your security effort. Luckily Salesforce provides an alternative.

The .stripInaccessible method

The stripInaccessible method is a little more nuanced and does the check after the query is made. Here’s the example from Salesforce’s documentation:

List<Account> accounts = [SELECT Name, Website FROM Account];
SObjectAccessDecision decision = Security.stripInaccessible(AccessType.READABLE, accounts);

for (Integer i = 0; i < accountsWithContacts.size(); i++) 
{
    System.debug('Insecure record access: '+accountsWithContacts[i]);
    System.debug('Secure record access: '+decision.getRecords()[i]);
}

// Print modified indexes
  System.debug('Records modified by stripInaccessible: '+decision.getModifiedIndexes());

// Print removed fields
  System.debug('Fields removed by stripInaccessible: '+decision.getRemovedFields());

This gives you a little more control because you make a decision based on the results of the security check. For example, you could log an error for an admin to check to later to see if there are missing permissions, or if someone is trying to see something they aren’t supposed to.

To be honest, I can’t think of a really good reason to use WITH SECURITY_ENFORCED. The error it throws is too vague and it makes it really hard to debug. But it’s good to know there is a quick option to bail hard on a query if the running user doesn’t have the necessary permissions.

These items are still in beta, but I would give them a try. Security often gets forgotten when writing Apex, so it’s nice to have additional easy to use tools to make things a little more secure in your code.

So-Called Advent Calendar Day 19 - WhatsThis.js

In the spirit of the holiday season, this is a series of short blog posts covering random things I have learned while doing Salesforce development, one for each day of Advent.

Jack skellington
JavaScript Town isn't nearly as exciting

The “this” keyword can be hard to wrap your head around, and I personally have wrestled with it for a long time (which makes me think it’s a language problem and not my fault! But I digress). So while I was trying to learn how to use it, I found it was much more fun to sing about it!

Here’s a song I wrote a few years ago about this:

WhatsThis.js

(to the tune of ‘What’s This?’ From The Nightmare Before Christmas)

What's this, what's this?
My scope is everywhere.
What's this?
And now it isn't there.

What's this?
Call, apply and bind,
What am I typing
setTimeout? This isn't fair!
What's this?

What's this? What's this?
I guess I'll check this blog
What's this?
Now try console.log()

What's this?
The code is lined with
debugs laughing
breakpoints trying to see what's happening
Have I possibly gone daffy?
What is this?

What's this?

There's functions throwing exceptions
undefined it said
Suddenly it's working
And now my code is dead

this is equal to the window?
Oh, I can't believe my eyes
This async function has a new
scope coming from inside...

Alert! What's this?
They're binding to the scope! Var that?
That is still defined! Inspired!
This is set to that to keep this constant
Every single time it fires
What's this?

What's this?
Right here! A method named call? How queer
And who would ever think?
Apply?

This is bound to all sorts of things
Following a call stack like a string
And there's a smile on everyone
So now correct me if I'm wrong

This is dumb!
This is fun!
Oh, could it be I got my wish?
What's this?

Oh my, what now?
A callback argument?
But look, call() cannot be sent
Or apply(), no parameters to declare them
Or ensnare them, but bind() ensures that they are
Defined inside this function... hmm....

What's this?

This is still just missing
The scope cannot be found
And in their place there seems to be
Undefined's all around

Instead of binding correctly
Another var I have to declare
The sight of programs crashing
Are absolutely everywhere

The stacks, the calls!
They're everywhere and all, around
I never felt so confused, before!
This implied scope keeps hoisting up
I simply cannot get this function up

I want this, oh I want this
I want this to be known
I've got to know, I've got to know
Is there a syntax that is sound?
What! Is! This!

Arrow functions? Hmm…

So-Called Advent Calendar Day 18 - Fire Drills - You have to slow down to speed up

In the spirit of the holiday season, this is a series of short blog posts covering random things I have learned while doing Salesforce development, one for each day of Advent.

We have all been there before. You get the message on Slack, a panicked chat message. The dreaded P0 issue. Something is broken and we have to fix it NOW.

Generally my first instinct is to dive into the code and figure out what’s wrong. Churn out the code, get it tested, merge it into master, and get it pushed to production as soon as possible. Deployments in Salesforce can take up to an hour in some of the orgs I have worked in, so we need to move quickly!

Looking back now, this is almost always the wrong way to react. Before you even touch the code, every one needs to stop and align on the problem. Set up a meeting, either in person or remotely, with everyone that needs to be involved. You may end up inviting individuals that don’t really need to be involved, but given the critical nature of the issue, it’s better to be overcommunicative than under.

Now take the time align everyone on the issue:

  • What is not working properly? How should it be working?
  • How many people are affected? What is the consequence of not fixing the problem?
  • How should we should find the cause of the issue?
  • Who should be working on it?
  • How will we test if we have actually resolved the issue?
  • Have we accounted for all use cases?
  • What are the potential consequences of pushing out this fix?
  • Do we need to do any communication to customers? Both during and after the fix is made?

After it is clear everyone’s role needed to execute, only then should you execute. You have to slow down first and align or you risk making things even worse. And after everything has settled down, you have to do a retro on the issue with everyone involved. Here are a few questions to answer, but it should not be limited to this

  • What caused the issue?
  • Could we have caught this earlier? What improvements do we have to make?
  • Are there any unintended consequences?
  • Was there any fallout from this issue?
  • Are there any actions items moving forward?

And most importantly, take a moment to praise each other for jumping on board. Regardless of how it goes, recognize the hard work involved in resolving these issues. You will undoubtedly make mistakes, but they were the best calls you could make at the time.

As a side lesson - because of the time and resources required to address the issue, before you sound that alarm, ask yourself is this really an emergency?