Skip to content

Portal & Community Security: Experience Cloud Access

Portal security (Experience Cloud) introduces a second layer of complexity to the Salesforce security model. External users — customers, partners, suppliers — have different license types, different sharing behavior, and different security constraints than internal users. Getting portal security wrong is a common CTA failure point because candidates apply internal security patterns to external user scenarios.

External User Architecture Overview

flowchart TD
    subgraph "Internal Users"
        IU["Internal Users\n(Salesforce License)"]
        IH["Internal Role Hierarchy"]
        IOWD["Internal OWD"]
    end

    subgraph "External Users"
        EU["External Users\n(Community/Partner License)"]
        EH["Portal Role Hierarchy\n(Under Account)"]
        EOWD["External OWD\n(Separate Setting)"]
    end

    subgraph "Shared"
        SR["Sharing Rules"]
        PS["Permission Sets"]
        FLS["FLS"]
    end

    IU --> IH --> IOWD
    EU --> EH --> EOWD
    IOWD --> SR
    EOWD --> SR
    IU --> PS --> FLS
    EU --> PS --> FLS

    style IU fill:#1565c0,color:#fff
    style EU fill:#e65100,color:#fff
    style EOWD fill:#c62828,color:#fff

External User License Types

The license type determines what a user can do and how sharing works. This is one of the most critical decisions in portal architecture.

License Comparison

LicenseData AccessSharing BehaviorRole HierarchyRecord OwnershipCost
Customer CommunityOwn records + sharedCommunity sharing rulesPortal roles (under Account)YesLowest
Customer Community PlusOwn + shared + reportsStandard sharing + community rulesFull portal role hierarchyYesMedium
Partner CommunityOwn + shared + reportingStandard sharing + partner rulesPartner role hierarchyYesMedium-High
External AppsOwn records + sharedCommunity sharing rulesPortal rolesYesLowest (API optimized)
ChannelSimilar to PartnerStandard sharing + partner rulesPartner role hierarchyYesMedium-High
Guest UserOnly what sharing rules grantGuest user sharing rules onlyNoneNoFree

License Selection Decision

flowchart TD
    Start["External User\nNeeds Access"] --> Q1{"Do they need to\nlog in?"}
    Q1 -->|No| Guest["Guest User\n(Unauthenticated)"]
    Q1 -->|Yes| Q2{"Do they need\nreporting and dashboards?"}
    Q2 -->|No| Q3{"Is it a partner\nwho sells with you?"}
    Q2 -->|Yes| Q4{"Partner or Customer?"}
    Q3 -->|Yes| Partner["Partner Community License"]
    Q3 -->|No| Q5{"Will they have high\nAPI/integration needs?"}
    Q5 -->|Yes| ExtApps["External Apps License"]
    Q5 -->|No| CC["Customer Community License"]
    Q4 -->|Partner| CCP["Partner Community License"]
    Q4 -->|Customer| CCPL["Customer Community Plus License"]

    style Guest fill:#c62828,color:#fff
    style CC fill:#2e7d32,color:#fff
    style CCPL fill:#1565c0,color:#fff
    style Partner fill:#e65100,color:#fff
    style ExtApps fill:#4a148c,color:#fff

External OWD

Salesforce has separate OWD settings for external users. The External OWD can be the same as or more restrictive than the internal OWD — never less restrictive.

Internal vs External OWD

Internal OWDAllowed External OWDWhy
PrivatePrivate onlyExternal cannot be less restrictive
Public Read OnlyPrivate or Public Read OnlyCan restrict external further
Public Read/WritePrivate, Public Read Only, or Public Read/WriteCan restrict external further

External OWD Defaults

When you change an internal OWD, the external OWD defaults to the same value. But if you have external users, you almost always want the external OWD to be MORE restrictive than the internal OWD. Review external OWD separately for every object.

External OWD Design Approach

flowchart TD
    Step1["1. Set Internal OWD\nfor internal users first"] --> Step2["2. For EACH object,\nask: should external users\nsee each other's records?"]
    Step2 -->|"Usually No"| Private["Set External OWD = Private"]
    Step2 -->|"Yes, for collaboration"| ReadOnly["Set External OWD = Public Read Only"]
    Step2 -->|"Yes, full collaboration"| ReadWrite["Set External OWD = Public Read/Write"]
    Private --> Step3["3. Use sharing rules\nto grant specific cross-account access"]

    style Private fill:#c62828,color:#fff
    style Step1 fill:#1565c0,color:#fff

Portal Role Hierarchy

External users have their own role hierarchy that sits beneath their Account in the internal role hierarchy. The structure differs between customer and partner portals.

Portal Role Hierarchy Structure

flowchart TD
    subgraph "Internal Hierarchy"
        CEO["CEO"]
        VP["VP Sales"]
        AM["Account Manager\n(Account Owner)"]
    end

    subgraph "Partner Portal (Account: Acme Partners)"
        PE["Partner Executive"]
        PM["Partner Manager"]
        PU["Partner User"]
    end

    subgraph "Customer Portal (Account: BigCorp)"
        CE["Customer Executive"]
        CM["Customer Manager"]
        CU["Customer User"]
    end

    CEO --> VP --> AM
    AM -->|"Implicit sharing"| PE
    AM -->|"Implicit sharing"| CE
    PE --> PM --> PU
    CE --> CM --> CU

    style CEO fill:#1565c0,color:#fff
    style AM fill:#2e7d32,color:#fff
    style PE fill:#e65100,color:#fff
    style CE fill:#4a148c,color:#fff

How Portal Roles Are Auto-Created

When you create the first community user on an Account, Salesforce automatically generates portal roles for that Account. Understanding this auto-creation is important because it affects role hierarchy size and sharing calculations.

flowchart TD
    Admin["Admin creates first\nCommunity user on Account"] --> Check{"License type?"}

    Check -->|"Customer Community\nPlus or Partner"| Create3["Auto-creates 3 roles\nunder Account Owner's role"]
    Check -->|"Customer Community\nor External Apps"| Create1["Auto-creates 1 role\n(flat, no hierarchy)"]

    Create3 --> R1["Account Name -\nCustomer/Partner Executive"]
    Create3 --> R2["Account Name -\nCustomer/Partner Manager"]
    Create3 --> R3["Account Name -\nCustomer/Partner User"]
    R1 --> R2 --> R3

    Create3 --> Note1["First user assigned to\nlowest role (User) by default"]

    Create1 --> Flat["Account Name -\nCustomer/Partner User\n(no hierarchy levels)"]

    style Create3 fill:#1565c0,color:#fff
    style Create1 fill:#2e7d32,color:#fff

Role Volume at Scale

Each Account with community users generates up to 3 roles. An org with 10,000 partner accounts creates up to 30,000 portal roles. This bloats the role hierarchy and increases group membership table maintenance time. Use Customer Community (1 role) over Community Plus (3 roles) when hierarchy is not needed. Configure the number of customer roles (1-3) under Setup > Communities Settings.

Portal Role Hierarchy Levels

License TypeAvailable RolesDefault Roles
Customer Community1 role (flat)User
Customer Community Plus3 roles (Executive, Manager, User)All three created per Account
Partner Community3 roles (Executive, Manager, User)All three created per Account
External Apps1 role (flat)User

Community License Role Limitation

Customer Community (non-Plus) users do NOT participate in the portal role hierarchy. They are essentially flat — each user can only see their own records plus records shared explicitly. This is by design for high-volume, low-cost scenarios. If a customer needs hierarchical visibility, use Customer Community Plus.

High-Volume Customer Portal Users

Customer Community and External Apps license users are classified as High-Volume Customer Portal (HVCP) users when the org has more than a certain threshold. HVCP users have special sharing behavior.

HVCP Sharing Behavior

FeatureStandard Portal UsersHVCP Users
Share tablesUse standard share tablesUse separate sharing tables (optimized for scale)
Role hierarchyParticipate in portal hierarchyDo NOT participate in hierarchy
Sharing rulesOwnership + criteria-basedSharing sets + share groups
Record visibilityOWD + hierarchy + rulesOwn records + sharing sets only
ScaleModerate (thousands)Massive (millions)
PerformanceStandard sharing calculationOptimized — no hierarchy computation

Sharing Sets

Sharing Sets are the mechanism for granting HVCP users access to records beyond their own.

flowchart LR
    SharingSet["Sharing Set"] --> AccessMap["Access Mapping"]
    AccessMap --> Obj["Target Object\n(e.g., Case)"]
    AccessMap --> Lookup["Lookup Field\n(e.g., Case.AccountId)"]
    AccessMap --> UserField["User's Account\n(Contact.AccountId)"]
    AccessMap --> Level["Access Level\n(Read Only or Read/Write)"]

    Note["If the target object's lookup\nmatches the user's Account,\ngrant access"]

    style SharingSet fill:#1565c0,color:#fff

Example: A Sharing Set grants Customer Community users Read/Write access to Cases where Case.AccountId matches the user’s Contact.AccountId. This means portal users see Cases related to their own Account.

Sharing Set Data Flow

flowchart LR
    subgraph "Portal User Context"
        PU["Portal User\n(Community License)"]
        PC["User's Contact Record\nContact.AccountId = 001ABC"]
    end

    subgraph "Sharing Set Evaluation"
        SS["Sharing Set\nAccess Mapping"]
        Match{"Does target record's\nlookup field match\nuser's Account?"}
    end

    subgraph "Target Records"
        C1["Case A\nAccountId = 001ABC"]
        C2["Case B\nAccountId = 001ABC"]
        C3["Case C\nAccountId = 001XYZ"]
    end

    PU --> PC
    PC -->|"AccountId = 001ABC"| SS
    SS --> Match
    Match -->|"Match: 001ABC = 001ABC"| C1
    Match -->|"Match: 001ABC = 001ABC"| C2
    Match -->|"No match: 001ABC ≠ 001XYZ"| C3

    style C1 fill:#2e7d32,color:#fff
    style C2 fill:#2e7d32,color:#fff
    style C3 fill:#c62828,color:#fff
    style PU fill:#1565c0,color:#fff

Share Groups

Share Groups grant internal users access to HVCP user records. This is the reverse direction — internal users needing to see portal users’ data.

MechanismDirectionPurpose
Sharing SetsGrant external users access to records”Portal users see their Account’s Cases”
Share GroupsGrant internal users access to HVCP records”Support agents see portal users’ Cases”

Guest User Security

Guest users (unauthenticated visitors) have the most restricted access in Salesforce. Since 2020, Salesforce has progressively tightened guest user security.

Guest User Security Restrictions

RestrictionDetailsSince
No record ownershipGuest users cannot own recordsAlways
Explicit sharing rules requiredMust use guest user sharing rules for any accessWinter ‘20
Secure guest user record accessRecords created by guests are owned by the site’s default ownerSpring ‘20
Object permissions must be explicitNo implicit access to any objectWinter ‘21
API access disabled by defaultGuest users cannot access APIs without explicit configurationSpring ‘21
View All / Modify All blockedCannot grant these permissions to guest usersAlways
Sharing rules limitedOnly criteria-based guest user sharing rulesWinter ‘21

Guest User Security is a CTA Red Flag

If your architecture exposes any data to unauthenticated users, the CTA board WILL probe this extensively. You must justify every piece of data visible to guest users, explain your sharing rules, and demonstrate that you have applied the principle of least privilege. Over-exposure of guest user data has caused real-world data breaches.

Guest User Architecture Pattern

flowchart TD
    GuestUser["Guest User\n(Unauthenticated)"] --> GuestProfile["Guest User Profile\n(Minimum permissions)"]
    GuestProfile --> GUSR["Guest User Sharing Rules\n(Criteria-based only)"]

    GUSR --> Q1{"What data does the\nguest NEED to see?"}
    Q1 -->|"Knowledge Articles"| KA["Share specific articles\nwhere IsPublished = true"]
    Q1 -->|"Product catalog"| PC["Share products\nwhere IsActive = true"]
    Q1 -->|"Nothing else"| No["No additional sharing rules"]

    GuestProfile --> LP["Lock down:\n- Remove all unnecessary objects\n- Remove all unnecessary fields\n- Disable API access\n- Disable Apex access"]

    style GuestUser fill:#c62828,color:#fff
    style LP fill:#c62828,color:#fff

Guest User Best Practices

  1. Audit guest user profiles quarterly — permissions creep over time
  2. Use criteria-based sharing rules only — ownership-based rules are not available for guest users
  3. Never expose PII to guest users — even masked data is risky
  4. Remove all unnecessary object permissions — explicit opt-in only
  5. Disable guest user API access — unless there is a specific, documented need
  6. Use Salesforce Health Check — it flags guest user security issues

Community-Specific Sharing Rules

Experience Cloud supports additional sharing rule types specific to external users.

Sharing Rule Types for Communities

Rule TypeApplies ToBased OnUse Case
Ownership-basedAll external usersRecord owner’s role”Partner Executive’s records shared with Partner Managers”
Criteria-basedAll external usersField values”Cases with Status = Escalated shared with Partner Executives”
Guest user sharingGuest users onlyField values (criteria)“Knowledge Articles where IsPublished = true shared with guest users”
Sharing SetsHVCP usersLookup field match”Cases shared where Case.AccountId = User’s AccountId”

Portal Security Design Process

flowchart TD
    Step1["1. Identify all external\nuser types"] --> Step2["2. Select license type\nper user type"]
    Step2 --> Step3["3. Set External OWD\nper object (default: Private)"]
    Step3 --> Step4["4. Design portal role hierarchy\n(if using Plus/Partner licenses)"]
    Step4 --> Step5["5. Configure Sharing Sets\n(for HVCP users)"]
    Step5 --> Step6["6. Add sharing rules\nfor cross-account access"]
    Step6 --> Step7["7. Lock down Guest User\nprofile and sharing"]
    Step7 --> Step8["8. Configure FLS for\nexternal profiles"]
    Step8 --> Step9["9. Test with each\nexternal user type"]

    style Step1 fill:#1565c0,color:#fff
    style Step3 fill:#c62828,color:#fff
    style Step7 fill:#c62828,color:#fff
    style Step9 fill:#2e7d32,color:#fff

Portal Security Anti-Patterns

Anti-PatternRiskCorrect Approach
Using internal OWD for external usersOver-exposure of data between accountsSet External OWD to Private separately
Giving guest users object permissions by defaultData breach — unauthenticated accessExplicit opt-in for every object
Using Customer Community Plus when Community sufficesUnnecessary cost and complexityStart with Community; upgrade only if reporting/hierarchy needed
Ignoring implicit sharing for portal usersPortal users see parent Account dataAudit implicit sharing paths
Not testing with each license typePermission gaps or over-exposureCreate test users for each license type
Sharing too much via Sharing SetsCross-account data leakageUse the narrowest lookup field match possible

Sources