Salesforce Spring '20 Community Guest User Apocalypse
Tags: salesforce, security, database, news
Published: 2020-01-08 18:29:26

---
title: Salesforce Spring '20 Community Guest User Apocalypse
published: true
description:  "Okay, not that bad, but ..."
date: 2020-01-08 15:00:00 UTC
tags: salesforce,security,database,news
cover_image: https://katiekodes.com/images/lava.jpg
canonical_url: https://katiekodes.com/salesforce-spring-20-guest-user/
---

All right ... a nuisance, not an apocalypse.  Heads up:  There are some things changing with [Guest User access Salesforce Communities](https://releasenotes.docs.salesforce.com/en-us/spring20/release-notes/rn_networks_guest_user.htm) in the Spring '20 release that can break your business's customer experience if you're not on top of them.

Besides the [release notes](https://releasenotes.docs.salesforce.com/en-us/spring20/release-notes/rn_networks_guest_user.htm), I recommend reading the "View Details" and "Get Started" links of the 3 alerts dated Feb 29, 2020 **inside your org** under **Setup** -> **Security Alerts**.  I find them a little less abstract.

* Direct link:  [https://test.salesforce.com/ui/setup/securityUpdates/SecurityUpdatesPage](https://test.salesforce.com/ui/setup/securityUpdates/SecurityUpdatesPage)

Below, I'll explain my understanding so far of what's changing for Guest Users in Salesforce production orgs on March 1 -- alongside examples of the issues my org is dealing with.

---

## Are you impacted?

![](https://katiekodes.com/images/question-confused.jpg)

### Do you have a Community?

To determine if you use Salesforce Communities, visit [**Setup** -> **All Communities**](https://login.salesforce.com/_ui/networks/setup/SetupNetworksPage) and see if any "communities" are listed in "Active" status.

If you don't have any at all, you can ignore this whole article -- although make sure to spread the word to a friend who _does_ use Communities.

### Do you let Guest Users use the Community?

If you have active Communities listed, look at each one's URL _(something along the lines of `https://yourorg.xx00.force.com/something`)_ and ask yourself what kinds of humans you send to web sites beginning with that URL.

Now ask yourself:

> "Do I **ever** send members of the general public to any such web sites?
> 
> "If so, do those web sites **provide them data out of my Salesforce org** or **let them write data into my Salesforce org**?"

#### Are you really, really sure?

Don't be too quick to answer "No."

> For example, we use Communities to host forms that collect sensitive data from prospective customers.
> 
> Most of the web pages within our Community that do anything interesting require someone to be logged into the Community with a username and password.  Those web pages are _**not**_ impacted by Spring '20 changes.
> 
> However, the web page where people _**sign up for an account upon their very first visit**_ most definitely _**is impacted**_, because it _writes_ a new **User** record to our Salesforce org when they provide us their e-mail address and the password they'd like to use.
> 
> So even though we might initially think, "No, everything's locked down behind a Community User login page," it turns out it's not!  The "get an account" page itself is open to the public.

Furthermore, we also have a few forms that allow people to see upcoming events and RSVP to the events.  These Community web pages are _**not**_ hidden behind a login requirement at all _(they don't ask private enough information to bother -- they're more like Eventbrite events)_.

Each of these RSVP forms reads information about the event it is allowing someone to RSVP to _(so as to display the event's name at the top of the form)_, and also writes data back to our Salesforce org _(noting the details about the person who RSVPed)_.

Be sure to sit down with your org's whole administrator + developer team and really think through these kinds of "edge cases."

### Visit each page yourself

> If you come up with such web pages, **visit them**, using [versions of their URLs from a sandbox](https://test.salesforce.com/_ui/networks/setup/SetupNetworksPage) that has **Spring '20** turned on.
> 
> In such a sandbox, Salesforce should have already "flipped the switches" it plans to flip on March 1.
> 
> * Check **if the web pages load** properly.
> * Fill out all their form fields, click all their buttons, and **see if anything doesn't behave as expected**.
> 
> If you only have a **Winter '20** sandbox, you can manually check/uncheck the boxes that Salesforce will be auto-checking/auto-unchecking on March 1 -- I'll go over where to find them in the review, below, of what changed.

You might need to use a web browser in "Incognito" or "Private" mode, with password manager autologin functionality turned off, to make sure you aren't accidentally logged into the Community or into Salesforce.

---

## What's changing #1:  No ownership allowed

![](https://katiekodes.com/images/screenshots/screenshot-spring20-guest-users/reassignownertodefault.png)

Under **Setup** -> **Communities Settings**, there's a little checkbox labeled "**Reassign new records created by guest users to the default owner**" that is going to get checked.  From what I understand, you won't be able to un-check it.

The "Security Alert" notes within Salesforce also seem to imply that there won't be _any_ ownership of Salesforce records allowed by community Guest Users, since the notes ask you to edit old data to make sure that records are owned by someone else.

> _(If you're in Winter '20 in your sandbox and want to see what will happen when Salesforce implements these changes, just check it yourself and change your records to be owned by someone else.)_

This likely doesn't impact you from a business perspective, except that it prevents a loophole through the change I'm about to describe next ...

---

## What's changing #2:  Record access lockdown

![](https://katiekodes.com/images/screenshots/screenshot-spring20-guest-users/secureguestuserrecordaccess.png)

Under **Setup** -> **Sharing Settings**, there's a little checkbox that says "**Secure guest user record access**" that is going to get checked  From what I understand, you won't be able to un-check it.

> _(If you're in Winter '20 in your sandbox and want to see what will happen when Salesforce implements this change, just check it yourself.)_

Here's what that little checkbox does:

### Impacts

#### Impact 1:  Private sharing

This checkbox toggles **every object** in your org so that Guest Users have no Read or Write access to records from those objects.

That is, it puts the objects into "Private" sharing mode from the perspective of the Guest User.

"Private sharing" mode means that a user can only learn about the existence of, or modify, records that it owns.  _(And since there's another change coming out on March 1 saying that Guest Users will no longer own records, this is effectively a lockdown for Guest Users preventing any Read/Write access.)_

That said, you can _sort of_ restore "Read" sharing-access to Guest Users on a record-by-record basis.  More on "sort of" in a moment.

#### Impact 2:  No manual sharing

This checkbox disables making an end-run around the new rule by granting access to Guest Users by using "manual sharing" on a record-by-record basis.

#### Impact 3:  No public group membership

This doesn't impact my org, so I don't have much to say about how impactful it would be.

#### Impact 4:  No queue membership

This doesn't impact my org, so I don't have much to say about how impactful it would be.

### Fixes

#### Restoring read access

Under **Setup** -> **Sharing Settings**, most of the page is taken up by a "Related List" for each object in your org listing out existing "**Sharing Settings**" for that object and offering a "**New**" button for creating additional ones.

Once the "Secure guest user record access" checkbox has been checked in an org, a new "**Guest user access, based on criteria**" option shows up under "**Step 2: Select your rule type**" when you click this "New" button.

The only type of access it allows you to grant to an object, for a Guest User, is **Read**.

Unfortunately, the user interface doesn't allow you to grant Read access to **every record** of the object.  You have to pick at least 1 field-value-based filter criterion under "**Step 3: Select which records to be shared**," and "Id NOT EQUALS _(blank)_" is not an option,  you sly devil.

If your business case for Guest Users in Communities absolutely requires that they be able to see data from every single record of a given object, I can think of three solutions:

1. You get very sly about your "criteria" -- e.g. `CreatedById` `startsWith` `005` _(which should always be true, since that's the first 3 digits of any User ID)_.
2. You leave record access locked down to No Read/Write for Guest Users, don't bother with "**Sharing Settings**, and have your Community pages do essential work on behalf of Guest Users with Apex running in "system mode" and "without sharing" _(BE CAREFUL!  NOT FOR AMATEURS!)_.
3. If the only object you care about letting a Guest User be able to read data from is **User**, and if the only type of user record you need them to be able to read data from is "user of the same community who doesn't also happen to be a proper internal Salesforce user," instead of using "Sharing Settings" against the "User" object, you can go to **Setup** -> **All Communities** -> _(pick a community)_ -> **Workspaces** -> **Administration** -> **Preferences**, and check a checkbox called **Let guest users see other members of this community**.

#### Write access workaround

1. You may have to amend the Apex and Visualforce / JavaScript behind pages of your community so that certain Community pages do certain work on behalf of Guest Users as a different user and/or in "system mode" and "without sharing" _(BE CAREFUL!  NOT FOR AMATEURS!)_.

Bring snacks -- this is going to take some serious Admin-Dev collaboration time, with a healthy dose of concern about security.

Remember that you want to follow [principles of "least privilege"](https://en.wikipedia.org/wiki/Principle_of_least_privilege) when designing these workarounds, not make _your_ life easier as an admin or a dev.

---

## What's changing #3:  No "user records" read-access loophole

![](https://katiekodes.com/images/screenshots/screenshot-spring20-guest-users/viewallusers.png)

The **profile-specific** permission "**View All Users**" will no longer be a checkbox you're allowed to check for a profile used by Guest Users.

This could have served as a loophole to the "record access lockdown" in the case of the **User** object -- now it can't.

> _(If you're in Winter '20 in your sandbox and want to see what will happen when Salesforce implements this change, just check un-check the "View All Users" checkbox under **System Permissions** within the relevant profile yourself.)_

### Restoring access

#### Other Community Users, not Salesforce

If the only type of **User** record that you need Guest Users to be able to read data from is "user of the same community who doesn't also happen to be a proper internal Salesforce user," instead of using "Sharing Settings" against the "User" object, you can go to **Setup** -> **All Communities** -> _(pick a community)_ -> **Workspaces** -> **Administration** -> **Preferences**, and check a checkbox called **Let guest users see other members of this community**.

#### Salesforce Users

If you _also_ need Guest Users to be able to read data from **User** records belonging to people who happen to be proper internal Salesforce users _(e.g. letting the "create an account" page for a community match to someone who already works for your company as a Salesforce user)_...

...You'll want to create "Sharing Settings" on the **User** object, like you would for any other object.

See "[Restoring Read Access](#restoring-read-access)" above.

Admins and Devs should partner to think carefully about, and test, whether this is actually necesary.  Remember, follow [principles of "least privilege"](https://en.wikipedia.org/wiki/Principle_of_least_privilege) when designing workarounds to Salesforce locking down security.

---

![](https://katiekodes.com/images/currencies-wide.jpg)

## Business impact

When the "Secure guest user record access" checkbox was checked as Spring '20 went live in our QA sandbox, some things broke and others didn't.

### What stayed up

1. A Visualforce Page called `EventRegistration`, accessible publicly at `https://orgname.cs00.force.com/communityname/EventRegistration`, still loaded and showed a calendar shape -- it didn't redirect people to log in _(however, it was blank)_.
2. A Visualforce Page called `CreateNewAccount`, accessible publicly at `https://orgname.cs00.force.com/communityname/CreateNewAccount`, still prompted for a name, email address, and password as usual.
3. A Visualforce Page called `LogMeIn`, accessible publicly at `https://orgname.cs00.force.com/communityname/LogMeIn`, still allowed a registered community users to type an e-mail address and password, and to access the Community behind the login prompt.
4. A Visualforce Page called `ForgotPassword`, accessible publicly at `https://orgname.cs00.force.com/communityname/ForgotPassword`, still prompted for an e-mail address.
	* Upon submitting an e-mail address that didn't exist, it gave the usual error message saying, `Sorry, that's not even a member of our community.`
	* Upon submitting an e-mail address that does exist, it took me to `https://orgname.cs00.force.com/communityname/PasswordSent` -- I was testing with a fake e-mail address, so no idea if it really arrived.  But it rendered the page saying it sent me a password reset link.

### What broke

1. Actually trying to **submit** data to the Visualforce Page called `EventRegistration`, accessible publicly at `https://orgname.cs00.force.com/communityname/CreateNewAccount`, took the user to a Visualforce page with a red error message at the top saying, "`Your request cannot be processed at this time. The site administrator has been alerted.`"
2. Trying to visit the URL to register for an event, which involves passing a Salesforce record ID as a URL parameter to the Visualforce Page called `EventRegistration`.  e.g. When visiting `https://orgname.cs00.force.com/communityname/EventRegistration?eventId=0AA000008298v89` with a web browser, people got instantly redirected to `https://orgname.cs00.force.com/communityname/LogMeIn?startURL=%2Fcommunityname%2FEventRegistration%3FeventId%3D0AA000008298v89` _(the Visualforce Page called `LogMeIn`)_.
	* Note:  Although I was able to get the page to load properly by adding a guest-user-specific sharing setting for "**Our Events**" object with a criterion of `CreatedById` `startsWith` `005`, the "submit" button still does not work properly, because it involves **writing** data to the database.
	* When I try to submit a registration form, I am shown an error message at the top of the registration form saying:  `Insert failed. First exception on row 0; first error: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY, insufficient access rights on cross-reference id: []`
3. The calendar at `EventRegistration` _(without an `eventId` URL parameter)_ was blank instead of filled with a list of events and their registration links.
	* Note:  I believe I was able to fix this by adding a guest-user-specific sharing setting for "**Our Events**" object with a criterion of `CreatedById` `startsWith` `005`.

---

![](https://katiekodes.com/images/tools-wide.jpg)

## Expected technical issues

Here's what I suspect we'll have to examine closely:

1. The business process of "Checking against existing **User** records by e-mail address and deciding whether or not to create a new **User**" could be part of the problem with `CreateNewAccount`.
2. We have 3rd-party "managed package" triggers in place that, upon new **User** creation, create a new **Contact**.  That could also be part of the problem with `CreateNewAccount`.
3. What worms do we have to shove back into a can _(e.g. very **carefully** rewrite pieces of them to run in "system mode without sharing" concerning Process Builders / Workflow Rules / Flows / Triggers that run when **User** or **Contact** records are created/edited)_?  And how about all of the automations that kick off when those automations cause other records to be created/edited/deleted? Yikes.
4. What kinds of data processes _(e.g. creation of records in our "who's registered for what event" object)_ will we need to **carefully** rewrite to run in something like "system mode without sharing" when someone clicks the "submit" button on a page?  e.g. `EventRegistration?eventId=0AA000008298v89`?

![Photo of Jon Stewart depressedly blowing a party noisemaker](https://media.giphy.com/media/13IQzmybzcRMw8/giphy.gif)

So.  January's going to be a real party.

How's your [#GuestUserPocalypse](https://twitter.com/hashtag/GuestUserPocalypse) going?