Why Apex ‘with sharing’ Behaves Differently for External Users in Salesforce

Published by

on

Public Read/Write but No Records?

A Lightning Web Component (LWC) retrieves records via an Apex method using with sharing.

Everything looked correct.

  • The object permissions were in place.
  • Field-level security was verified.
  • The Apex class used with sharing.
  • And the object’s OWD was set to Public Read/Write.

Yet the LWC datatable stayed empty. The same SOQL query, when run in the Developer Console, returned records immediately.
Changing the Apex class to without sharing also fixed the issue.


The First Assumption That Causes the Problem

Most of us assume this:

  • If OWD is Public Read/Write, any user with object access should see the records.

That assumption is only true for internal users.


Salesforce uses two separate sharing models. Salesforce evaluates record access differently based on who the user is.
There are two distinct models:

  • Internal user sharing
  • External user sharing

These models are configured independently and enforced independently.


Default Internal Access: What It Really Controls

Default Internal Access applies only to users with:

  • UserType = Standard
  • Internal Salesforce licenses

When this is set to: Public Read/Write

  • Records are visible
  • Ownership does not restrict access
  • Queries return data

And this is why the query worked in Developer Console.


Default External Access: The Setting That Actually Matters Here

External users (Partner, Customer, Experience Cloud, Power Partner) do not use Default Internal Access at all.

They rely on: Default External Access
By Default this is set to: Private
This means,

  • External users see no records by default
  • Even if internal access is Public Read/Write
  • Even if object permissions are granted

Why Apex with sharing Returned Zero Rows

The Apex debug log revealed the key detail:

UserType = POWER_PARTNER

And everything made sense. Because the code was running as an external user, Salesforce enforced:

  • Default External Access
  • External sharing rules
  • Sharing sets
  • Apex managed sharing

And it ignored:

  • Default Internal Access
  • Role hierarchy
  • Profile-level assumptions

So, the query returned zero rows in the class. No Exception, No Warning, Just an empty result set.


Why without sharing Appeared to Fix the Issue

When the class was changed to:

public without sharing class className

Runs Apex in system context, which:

  • Bypasses record-level sharing
  • Ignores external access restrictions

This returns records but bypasses security


How to Confirm the Issue

Add the following debug statements in Apex:

System.debug(UserInfo.getUserType());

If UserType is:

POWER_PARTNER

or any other External User Type, then External Sharing being Enforced.


Resolution

The issue was resolved by updating the object’s Default External Access setting in Sharing Settings.

  • Under Setup
  • In Quick Find, search for Sharing Settings
  • Open Sharing Settings
  • Locate the required object
  • Click Edit
Change Made

Under the Objects Sharing settings:
Default External Access:
Private -> Public Read

Click Save.


Result

  • Partner users (UserType = POWER_PARTNER) were able to see records
  • Apex classes using with sharing started returning records

Why This Fix Worked

  • The Apex code was executing as a Power Partner User Type
  • Salesforce enforced Default External Access, not Default Internal Access
  • When External Access was set to Private, external users had no record visibility
  • Changing it to Public Read explicitly granted read access to all external users for that object

Key Takeaway

Apex with sharing always respects the current user’s sharing model.

If the user is external, Salesforce enforces external access rules only.
Once we understand this distinction, the behavior becomes predictable.

Leave a comment