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
| License | Data Access | Sharing Behavior | Role Hierarchy | Record Ownership | Cost |
|---|---|---|---|---|---|
| Customer Community | Own records + shared | Community sharing rules | Portal roles (under Account) | Yes | Lowest |
| Customer Community Plus | Own + shared + reports | Standard sharing + community rules | Full portal role hierarchy | Yes | Medium |
| Partner Community | Own + shared + reporting | Standard sharing + partner rules | Partner role hierarchy | Yes | Medium-High |
| External Apps | Own records + shared | Community sharing rules | Portal roles | Yes | Lowest (API optimized) |
| Channel | Similar to Partner | Standard sharing + partner rules | Partner role hierarchy | Yes | Medium-High |
| Guest User | Only what sharing rules grant | Guest user sharing rules only | None | No | Free |
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 OWD | Allowed External OWD | Why |
|---|---|---|
| Private | Private only | External cannot be less restrictive |
| Public Read Only | Private or Public Read Only | Can restrict external further |
| Public Read/Write | Private, Public Read Only, or Public Read/Write | Can 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 Type | Available Roles | Default Roles |
|---|---|---|
| Customer Community | 1 role (flat) | User |
| Customer Community Plus | 3 roles (Executive, Manager, User) | All three created per Account |
| Partner Community | 3 roles (Executive, Manager, User) | All three created per Account |
| External Apps | 1 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
| Feature | Standard Portal Users | HVCP Users |
|---|---|---|
| Share tables | Use standard share tables | Use separate sharing tables (optimized for scale) |
| Role hierarchy | Participate in portal hierarchy | Do NOT participate in hierarchy |
| Sharing rules | Ownership + criteria-based | Sharing sets + share groups |
| Record visibility | OWD + hierarchy + rules | Own records + sharing sets only |
| Scale | Moderate (thousands) | Massive (millions) |
| Performance | Standard sharing calculation | Optimized — 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.
| Mechanism | Direction | Purpose |
|---|---|---|
| Sharing Sets | Grant external users access to records | ”Portal users see their Account’s Cases” |
| Share Groups | Grant 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
| Restriction | Details | Since |
|---|---|---|
| No record ownership | Guest users cannot own records | Always |
| Explicit sharing rules required | Must use guest user sharing rules for any access | Winter ‘20 |
| Secure guest user record access | Records created by guests are owned by the site’s default owner | Spring ‘20 |
| Object permissions must be explicit | No implicit access to any object | Winter ‘21 |
| API access disabled by default | Guest users cannot access APIs without explicit configuration | Spring ‘21 |
| View All / Modify All blocked | Cannot grant these permissions to guest users | Always |
| Sharing rules limited | Only criteria-based guest user sharing rules | Winter ‘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
- Audit guest user profiles quarterly — permissions creep over time
- Use criteria-based sharing rules only — ownership-based rules are not available for guest users
- Never expose PII to guest users — even masked data is risky
- Remove all unnecessary object permissions — explicit opt-in only
- Disable guest user API access — unless there is a specific, documented need
- 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 Type | Applies To | Based On | Use Case |
|---|---|---|---|
| Ownership-based | All external users | Record owner’s role | ”Partner Executive’s records shared with Partner Managers” |
| Criteria-based | All external users | Field values | ”Cases with Status = Escalated shared with Partner Executives” |
| Guest user sharing | Guest users only | Field values (criteria) | “Knowledge Articles where IsPublished = true shared with guest users” |
| Sharing Sets | HVCP users | Lookup 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-Pattern | Risk | Correct Approach |
|---|---|---|
| Using internal OWD for external users | Over-exposure of data between accounts | Set External OWD to Private separately |
| Giving guest users object permissions by default | Data breach — unauthenticated access | Explicit opt-in for every object |
| Using Customer Community Plus when Community suffices | Unnecessary cost and complexity | Start with Community; upgrade only if reporting/hierarchy needed |
| Ignoring implicit sharing for portal users | Portal users see parent Account data | Audit implicit sharing paths |
| Not testing with each license type | Permission gaps or over-exposure | Create test users for each license type |
| Sharing too much via Sharing Sets | Cross-account data leakage | Use the narrowest lookup field match possible |
Related Topics
- Sharing Model — internal sharing model is the foundation; portal extends it
- Identity & SSO — external user authentication and social sign-on
- Field & Object Security — external user profiles and permission sets
- Security Best Practices — portal-specific best practices
- Decision Guides — license and portal architecture decision trees
Sources
- Salesforce Help: Experience Cloud Security
- Salesforce Help: External User Licenses
- Salesforce Help: Guest User Security
- Salesforce Help: Sharing Sets
- Salesforce Help: High-Volume Portal Users
- Salesforce Help: Partner User Roles
- Salesforce Help: Community Role Configuration
- Salesforce Architects: Experience Cloud Architecture
- Salesforce Security Guide: Guest User Best Practices
- Trailhead: Optimizing Role Hierarchy and Account Roles