Claude-code-plugins-plus-skills salesforce-enterprise-rbac
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/salesforce-pack/skills/salesforce-enterprise-rbac" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-salesforce-enterprise-rbac && rm -rf "$T"
manifest:
plugins/saas-packs/salesforce-pack/skills/salesforce-enterprise-rbac/SKILL.mdsource content
Salesforce Enterprise RBAC
Overview
Configure Salesforce's multi-layered security model: Profiles (baseline permissions), Permission Sets (additive permissions), Roles (record visibility), Organization-Wide Defaults (OWD), and Sharing Rules.
Prerequisites
- Salesforce System Administrator access
- Understanding of your org's user hierarchy
- For SSO: Identity Provider (Okta, Azure AD, etc.) with SAML 2.0
Instructions
Step 1: Understand the Salesforce Security Model
┌─────────────────────────────────────────────────────────────────┐ │ Layer 1: Organization-Wide Defaults (OWD) │ │ Most restrictive baseline — controls default record access │ │ Options: Private | Public Read Only | Public Read/Write │ ├─────────────────────────────────────────────────────────────────┤ │ Layer 2: Role Hierarchy │ │ Users above in hierarchy see records of users below │ ├─────────────────────────────────────────────────────────────────┤ │ Layer 3: Sharing Rules │ │ Grant access to groups of users based on criteria or ownership │ ├─────────────────────────────────────────────────────────────────┤ │ Layer 4: Manual Sharing │ │ Record owner shares individual records │ ├─────────────────────────────────────────────────────────────────┤ │ Layer 5: Profile / Permission Set │ │ Controls CRUD + FLS (which objects and fields users can access) │ └─────────────────────────────────────────────────────────────────┘ Key principle: Salesforce OPENS access, never restricts beyond OWD. OWD sets the floor. Everything else ADDS access on top.
Step 2: Configure Profiles for Integration Users
// Query existing profiles const conn = await getConnection(); const profiles = await conn.query(` SELECT Id, Name, UserType, Description FROM Profile WHERE UserType = 'Standard' ORDER BY Name `); // Best practice: Create a custom profile for API integrations // Setup > Profiles > Clone "Standard User" > Name: "API Integration Profile" // Set object permissions: const integrationPermissions = { Account: { read: true, create: true, edit: true, delete: false }, Contact: { read: true, create: true, edit: true, delete: false }, Opportunity: { read: true, create: false, edit: false, delete: false }, Lead: { read: true, create: true, edit: true, delete: false }, Case: { read: true, create: true, edit: true, delete: false }, }; // Check a user's effective permissions via API const userPermissions = await conn.query(` SELECT Id, Name, Profile.Name, (SELECT PermissionSet.Name FROM PermissionSetAssignments) FROM User WHERE Username = 'integration@mycompany.com' `);
Step 3: Permission Sets (Additive Permissions)
// Permission Sets add permissions ON TOP of Profile // Use Permission Set Groups to bundle related sets // Query permission set assignments const psAssignments = await conn.query(` SELECT Assignee.Name, PermissionSet.Name, PermissionSet.IsCustom FROM PermissionSetAssignment WHERE Assignee.Username = 'integration@mycompany.com' `); // Create Permission Set via Metadata API (SFDX) // force-app/main/default/permissionsets/Integration_API_Access.permissionset-meta.xml
<?xml version="1.0" encoding="UTF-8"?> <PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata"> <label>Integration API Access</label> <description>API access for integration user</description> <objectPermissions> <object>Account</object> <allowRead>true</allowRead> <allowCreate>true</allowCreate> <allowEdit>true</allowEdit> <allowDelete>false</allowDelete> </objectPermissions> <fieldPermissions> <field>Account.Industry</field> <readable>true</readable> <editable>true</editable> </fieldPermissions> <fieldPermissions> <field>Account.AnnualRevenue</field> <readable>true</readable> <editable>false</editable> </fieldPermissions> </PermissionSet>
Step 4: Organization-Wide Defaults (OWD)
// Check current OWD settings via SOQL (metadata) // Setup > Sharing Settings > Organization-Wide Defaults // Recommended OWD for common objects: const recommendedOWD = { Account: 'Private', // Sales teams see only their accounts Contact: 'Controlled by Parent', // Follows Account access Opportunity: 'Private', // Revenue data is sensitive Case: 'Private', // Customer support data Lead: 'Public Read/Write', // Sales team shares leads }; // When OWD is Private, use Sharing Rules to open access: // Setup > Sharing Settings > Sharing Rules > New // Example: "Share all Accounts where Industry = 'Technology' with 'Engineering' Role"
Step 5: SSO Integration
SAML 2.0 SSO with Salesforce: Setup > Single Sign-On Settings > Enable SAML Setup > Single Sign-On Settings > New Configuration: - Issuer: https://idp.yourcompany.com/saml/metadata - Entity ID: https://login.salesforce.com - Certificate: Upload IdP signing certificate - SAML User ID Type: "Username" - SAML User ID Location: "Subject" element Identity Provider Configuration: - ACS URL: https://login.salesforce.com?so=00Dxxxxxxxxxxxx - Entity ID: https://saml.salesforce.com - Name ID: user.email (must match Salesforce username) Setup > My Domain > Authentication Configuration: - Enable SAML as authentication option - Optionally disable username/password login
Step 6: Verify Access Programmatically
// Check if current user can access a specific record async function canAccessRecord(objectType: string, recordId: string): Promise<boolean> { try { await conn.sobject(objectType).retrieve(recordId); return true; } catch (error: any) { if (error.errorCode === 'INSUFFICIENT_ACCESS_OR_READONLY') { return false; } throw error; } } // Check object-level permissions async function getObjectPermissions(objectType: string) { const describe = await conn.sobject(objectType).describe(); return { queryable: describe.queryable, createable: describe.createable, updateable: describe.updateable, deletable: describe.deletable, }; }
Output
- Profiles configured with least-privilege for integration users
- Permission Sets created for modular access control
- OWD set appropriately for each sObject
- SSO configured with SAML 2.0
- Programmatic access verification implemented
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Missing object/field permission | Check Profile + Permission Sets |
| Trigger/Flow denied by sharing | Check OWD and Sharing Rules |
| SSO loop | Wrong ACS URL | Verify My Domain + ACS URL match |
| User can't see records | OWD is Private, no sharing rule | Add appropriate Sharing Rule or Role Hierarchy |
Resources
Next Steps
For major migrations, see
salesforce-migration-deep-dive.