← All posts
· 5 min read ·
SalesforceSecurityIdentityOAuthSAMLSSO

Salesforce Identity Deep Dive: SSO, OAuth 2.0, and SAML for Enterprise Architects

A practical guide to Salesforce identity and access management - choosing between SAML and OAuth, implementing named credentials, Connected App security, and service account patterns.

Digital identity and authentication concept

Identity is the front door to everything in Salesforce. Getting it wrong - whether that’s misconfigured Connected Apps, overly permissive OAuth scopes, or SAML assertions that bypass MFA - creates vulnerabilities that no amount of Shield or OWASP hardening downstream can compensate for. Here’s the architecture that I apply on enterprise implementations.

SAML vs OAuth: Choosing the Right Protocol

The question comes up on every implementation: SAML or OAuth for SSO?

SAML 2.0 is the right choice when:

  • Your IdP is enterprise (Okta, Azure AD, PingFederate, ADFS)
  • Users are internal employees authenticating to Salesforce UI
  • You need attribute-based access control (ABAC) passing department, role, or clearance level
  • You need to enforce session duration from the IdP side

OAuth 2.0 is the right choice when:

  • Machine-to-machine integration (server → Salesforce API)
  • Mobile or SPA applications
  • API access where the user context doesn’t need a full browser session

In practice, most enterprise implementations use both: SAML for human users, OAuth for integrations.

SAML Configuration: What Actually Matters

When configuring Salesforce as a Service Provider (SP) in a SAML flow:

User ──► IdP (Okta/AAD) ──► SAML Assertion ──► Salesforce SP ──► Access

Critical settings:

  • NameID Format: use emailAddress or persistent - never transient if you need consistent user identity across sessions
  • Attribute mapping: map IdP groups to Salesforce Permission Set Groups, not profiles. Profiles are coarse; PSGs let you grant granular access based on IdP group membership
  • Just-in-Time (JIT) provisioning: auto-create Salesforce users on first SSO login. Reduces admin overhead but requires careful field mapping - especially Profile and FederationIdentifier
  • SAML Assertion validity: keep it short (2–5 minutes). A stolen assertion is valid for its entire validity window

JIT provisioning SAML attribute map example:

<saml:AttributeStatement>
  <saml:Attribute Name="sf_profile">
    <saml:AttributeValue>Standard User</saml:AttributeValue>
  </saml:Attribute>
  <saml:Attribute Name="sf_role">
    <saml:AttributeValue>Sales Rep</saml:AttributeValue>
  </saml:Attribute>
  <saml:Attribute Name="email">
    <saml:AttributeValue>user@company.com</saml:AttributeValue>
  </saml:Attribute>
</saml:AttributeStatement>

OAuth 2.0 Flows for Salesforce Integrations

Salesforce supports multiple OAuth flows. Which one to use:

JWT Bearer Token flow - the correct choice for server-to-server integrations with no user interaction:

Integration ──► Sign JWT with private key ──► POST to /token ──► Access Token

The private key never leaves your server. Salesforce validates the signature against the certificate uploaded to the Connected App. No user interaction required, no refresh token needed (just re-request with a new JWT).

Client Credentials flow (added in Summer ‘22) - simpler than JWT for M2M:

Integration ──► POST client_id + client_secret ──► Access Token

Easier to implement than JWT but the client_secret must be protected as carefully as a private key. Don’t use this for integrations where the credentials might be exposed in client-side code.

Authorization Code + PKCE - for user-facing applications:

App ──► Redirect to /authorize ──► User consents ──► Code ──► Exchange for token

PKCE (Proof Key for Code Exchange) is mandatory for public clients (SPAs, mobile). Without it, the auth code is interceptable.

Device flow - for IoT or CLI tools authenticating on behalf of a user without a browser.

Connected App Security Hardening

Every OAuth integration requires a Connected App. The default settings are not secure. After creation, always:

  1. Restrict access by IP - add the IP ranges of your integration servers in “IP Relaxation” → “Enforce IP restrictions”
  2. Scope minimisation - only grant the OAuth scopes actually needed. full scope is never appropriate for a production integration
  3. Permitted Users - set to “Admin approved users are pre-authorised” for service accounts; never “All users may self-authorise” for sensitive APIs
  4. Refresh token policy - set an expiry. Unlimited refresh tokens are a persistent credential that outlasts employee tenures
  5. Session policy - enforce a short session timeout for high-privilege Connected Apps
Recommended scopes for a read-only integration:
  api, refresh_token - NOT: full, web, visualforce, chatter_api

Service Account Architecture

A common bad pattern: using a named human user’s credentials for integrations. When that person leaves, everything breaks.

Service accounts for Salesforce integrations should be:

  • Dedicated users with no UI login permitted (set UserType = 'Standard' but block UI login via Login Hours = 0 hours in their Profile)
  • Minimum permissions - create a dedicated Permission Set for the integration with only the objects and fields it needs
  • Named appropriately - svc-mulesoft-crm@company.com, svc-sfcc-oms@company.com
  • MFA exempt via service account policy - create a Policy that exempts service account logins from MFA (they use OAuth, not password)

For Connected App JWT flow, no password is ever set on the service account - the only authentication mechanism is the JWT signed by the integration’s private key.

Single Org vs Multi-Org SSO

Multi-org Salesforce estates (common in M&A or multi-brand architectures) add identity complexity. Options:

Hub-and-spoke - one “hub” org handles authentication; users are redirected to spokes with a SAML assertion from the hub. Centralised user management but adds a hop.

Federated SSO to all orgs from IdP - the IdP issues separate SAML assertions to each Salesforce org. Simpler architecture but user provisioning must be managed per-org (unless you use a provisioning tool like SCIM).

Identity Connect - Salesforce’s LDAP/AD synchronisation tool. Syncs Active Directory users to Salesforce on a schedule. Useful for orgs that can’t fully federate via SAML but want centralised user management.

Common Vulnerabilities to Avoid

Overly permissive Connected Apps: scan your org for Connected Apps with full scope - SELECT Id, Name, (SELECT Scope FROM OAuth2UserConsents) FROM ConnectedApplication

Unmonitored refresh tokens: query AuthSession regularly for sessions with SessionType = 'OauthToken' and unusually old LastModifiedDate - these may be stale tokens from decommissioned integrations

SAML response replay: ensure your SP validates the NotOnOrAfter attribute and maintains a cache of used assertion IDs. Salesforce does this natively but custom SP implementations often skip it

Insecure redirect_uri: for Authorization Code flows, always register exact redirect URIs in the Connected App. Wildcard or broad URIs enable open redirect attacks

Auditing Identity Configuration

Run this SOQL quarterly to surface identity risks:

-- Connected Apps with excessive scope
SELECT Name, StartUrl, Description
FROM ConnectedApplication
WHERE (ConsumerSecret != null OR ContactEmail != null)

-- Users with API-only profiles logging in via UI
SELECT Username, LastLoginDate, UserType, Profile.Name
FROM User
WHERE Profile.Name LIKE '%API%'
AND LastLoginDate != null
AND UserType = 'Standard'

And check for users with both PermissionsModifyAllData and API access - that combination grants complete org read/write via API with no record-level restrictions.

← All posts