Skip to content

Identity & SSO: Quick Reference

Fast-track reference for identity and SSO — know the protocols, flows, and when to use each before you walk into a mock board.

Protocol Cheat Sheet

ProtocolPurposeToken/AssertionUse When
SAML 2.0Web SSO (authentication)XML assertionEnterprise SSO with existing IdP
OAuth 2.0API authorizationAccess token + refresh tokenIntegrations needing API access
OpenID ConnectAuthentication + authorizationID token (JWT) + access tokenModern web/mobile apps needing both login and API

One-Line Decision

Enterprise web SSO = SAML. API access = OAuth. Modern app needing both = OIDC. Legacy bridge = SAML Bearer.

IdP vs SP Decision

flowchart TD
    Q1{"Does the customer have\nan existing corporate IdP?"} -->|"Yes (Okta, Azure AD,\nADFS, Ping)"| SP["Salesforce = SP\nCorporate IdP authenticates"]
    Q1 -->|No| Q2{"Is Salesforce the\nuser system of record?"}
    Q2 -->|Yes| IdP["Salesforce = IdP\n(common for portals)"]
    Q2 -->|No| NewIdP["Recommend dedicated IdP\nSalesforce = SP"]

    style SP fill:#1565c0,color:#fff
    style IdP fill:#2e7d32,color:#fff
    style NewIdP fill:#e65100,color:#fff
ScenarioSalesforce RoleProtocol
Corporate IdP existsService ProviderSAML 2.0 or OIDC
SF is user SOR (portals, small company)Identity ProviderSAML/OIDC via Connected Apps
Multi-org architectureOne org = IdP, others = SPSAML 2.0
No IdP anywhereRecommend Okta/Azure AD; SF = SPSAML 2.0

SAML SSO Key Decisions

DecisionOptionsBoard-Ready Answer
User matchingFederation ID, Username, CustomFederation ID — survives username changes
SP vs IdP initiatedSP-initiated, IdP-initiatedSupport both. SP for bookmarks, IdP for portal
JIT provisioningStandard JIT, Custom JIT (Apex)Custom JIT when profile/role/PS must be dynamic
Single LogoutEnabled, DisabledEnable for security-sensitive environments
MFAIdP handles, SF handlesIdP-based MFA preferred; satisfies SF MFA requirement

OAuth Flow Selection (The Big Table)

FlowUser InteractionSecret/CertRefresh TokenUse For
Authorization CodeYesClient secret (server)YesWeb apps with backend
Auth Code + PKCEYesNo secret neededYesMobile apps, SPAs
JWT BearerNoCertificateNoServer-to-server, middleware
Client CredentialsNoClient secretNoService accounts (API v56.0+; Winter ‘23, broadly GA Spring ‘23)
SAML BearerNoSAML assertionNoSAML-to-OAuth bridge
DeviceYes (separate device)NoYesIoT, CLI tools

OAuth Flow Decision Tree

flowchart TD
    Start["App needs API access"] --> Q1{"Human user\ninvolved?"}
    Q1 -->|Yes| Q2{"App has\nbackend server?"}
    Q1 -->|No| Q3{"Has certificate?"}

    Q2 -->|Yes| AC["Auth Code\n+ PKCE recommended"]
    Q2 -->|No| PKCE["Auth Code + PKCE\nREQUIRED"]

    Q3 -->|Yes| JWT["JWT Bearer"]
    Q3 -->|No| CC["Client Credentials"]

    Q1 -.->|"Has SAML\nassertion"| SB["SAML Bearer"]

    style AC fill:#2e7d32,color:#fff
    style PKCE fill:#2e7d32,color:#fff
    style JWT fill:#1565c0,color:#fff
    style CC fill:#1565c0,color:#fff
    style SB fill:#e65100,color:#fff

Deprecated Flow

The Username-Password flow is deprecated. Never recommend it. If the scenario has a legacy system using it, recommend migrating to JWT Bearer or Client Credentials.

PKCE Flow — How It Works

What PKCE solves: Public clients (mobile apps, SPAs) cannot securely store a client secret. Without PKCE, an attacker who intercepts the authorization code can exchange it for an access token. PKCE (RFC 7636) binds the authorization request to the token request using a one-time cryptographic proof that only the original client possesses.

sequenceDiagram
    participant App as Mobile / SPA
    participant SF as Salesforce
    participant User

    App->>App: Generate random code_verifier (43-128 chars)
    App->>App: code_challenge = BASE64URL(SHA256(code_verifier))
    App->>SF: GET /authorize (client_id, code_challenge, method=S256, redirect_uri)
    SF->>User: Login page + consent screen
    User->>SF: Authenticate + approve
    SF->>SF: Store code_challenge with auth code
    SF->>App: 302 Redirect with authorization code
    App->>SF: POST /token (code + code_verifier, NO client secret)
    SF->>SF: Compute SHA256(code_verifier), compare to stored code_challenge
    SF->>App: Access token + refresh token

Board Q&A — PKCE

“Why can’t an attacker intercept the auth code and use it?” — They don’t have the code_verifier. The code alone is useless without the original random value that produced the challenge.

“Why not just use a client secret?” — Public clients (mobile, SPA) ship code to the user’s device. A secret embedded there can be extracted. PKCE replaces the static secret with a per-request cryptographic proof.

“When is PKCE required vs optional in Salesforce?” — Required for mobile/SPA (uncheck “Require Secret for Web Server Flow” on the Connected App). Recommended for all authorization code flows per OAuth 2.1.

JWT Bearer Flow — How It Works

What JWT Bearer solves: Server-to-server integrations (middleware, ETL, scheduled jobs) need API access without a human present. JWT Bearer (RFC 7523) lets the server prove its identity with a digitally signed token instead of user credentials, running as a pre-authorized Salesforce user.

sequenceDiagram
    participant Srv as Integration Server
    participant SF as Salesforce

    Srv->>Srv: Build JWT: iss=client_id, sub=sf_username, aud=login.salesforce.com, exp=now+3min
    Srv->>Srv: Sign JWT with private key (RS256)
    Srv->>SF: POST /services/oauth2/token (grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer, assertion=signed_JWT)
    SF->>SF: Look up Connected App by iss (client_id)
    SF->>SF: Retrieve stored X.509 public certificate
    SF->>SF: Validate signature, check exp ≤ 5 min, verify aud + sub
    SF->>Srv: Access token (NO refresh token)

Board Q&A — JWT Bearer

“Why no refresh token?” — The private key IS the long-lived credential. When the access token expires, just sign and send a new JWT. No refresh dance needed.

“What happens if the certificate expires?” — All integrations using that Connected App fail silently. You must rotate the certificate and upload the new public cert to the Connected App before expiry. Monitor cert expiry dates proactively.

“JWT Bearer vs Client Credentials — when?” — JWT Bearer when you need to act as a specific named user (sub claim controls which user’s permissions apply). Client Credentials when the integration runs as a generic service account with its own execution user.

Connected App Key Settings

SettingWhat It ControlsCTA Guidance
Permitted UsersWho can use the appSet to “Admin approved” for sensitive integrations
IP RelaxationIP enforcementRelax for mobile apps that roam networks
Refresh Token PolicyToken expiration/rotationSet expiration; rotate for compromised tokens
ScopesAPI access breadthMinimum required scopes only — never “full” unless justified
Callback URLToken delivery endpointMust match exactly; HTTPS only
Digital SignaturesCertificate for JWT BearerRequired for JWT Bearer flow
Run AsExecution user (Client Credentials)Integration user with minimum access

JIT Provisioning Comparison

FeatureStandard JITCustom JIT (Apex SSOJitHandler)
User creationYesYes, with custom logic
Profile assignmentStatic (one per SSO config)Dynamic (based on attributes)
Permission Set assignmentNoYes
Role assignmentStaticDynamic
Related record creationNoYes (Contact, Account)

Use Custom JIT when you need to assign profiles/roles/permission sets dynamically based on SAML attributes or external data.

MFA Quick Reference

When SSO is configuredWho handles MFA
Corporate IdP has MFAIdP handles it — no SF MFA config needed
SSO without IdP MFAMust add MFA at IdP or SF level (IdP preferred)
Salesforce as IdPSF handles MFA
Direct login fallbackSF MFA always required

Breakglass Accounts

Always configure 2-3 admin accounts that bypass SSO for emergency access. If the IdP goes down, you need a way in. These accounts must have MFA enabled for direct login.

Named Credentials (Modern Architecture)

Legacy ModelEnhanced Model (Current)
Single Named Credential = endpoint + authNamed Credential = endpoint URL
Auth config embeddedExternal Credential = auth config (separate)
Per-user or named principalPermission Set controls who can use it
N/AMultiple Named Credentials share one External Credential

Always use Named Credentials for callouts. Never hardcode credentials in Apex, Custom Settings, or Custom Metadata.

Scenario 1: Enterprise SSO + API Integration

Situation: Financial services company. 10,000 internal users on Okta. MuleSoft middleware connects Salesforce to core banking. Mobile app for field agents. Regulatory requirement for MFA.

What you’d present:

  • Salesforce = SP, Okta = IdP, protocol = SAML 2.0
  • User matching via Federation ID (decoupled from SF username)
  • Custom JIT provisioning (Apex handler assigns profile/PS based on Okta group attributes)
  • MFA handled by Okta (satisfies Salesforce MFA requirement)
  • MuleSoft to Salesforce: JWT Bearer flow (server-to-server, certificate-based, no user interaction)
  • Mobile app: Authorization Code + PKCE (public client, cannot store secrets)
  • Single Logout enabled (regulatory compliance)
  • 2 breakglass admin accounts with direct login + SF MFA

Why not Client Credentials for MuleSoft: JWT Bearer lets MuleSoft impersonate specific integration users with different permission levels per flow. Client Credentials runs as a single execution user.

Scenario 2: Multi-Org with Customer Portal

Situation: Retail company with 2 Salesforce orgs (Sales, Service). Customer self-service portal on the Service org. 50,000 portal users. No corporate IdP.

What you’d present:

  • Service org = IdP (system of record for customer users)
  • Sales org = SP (trusts Service org for internal user SSO via SAML)
  • Portal users authenticate directly against Service org (Salesforce login)
  • Social Sign-On enabled for portal (Google, Apple) to reduce friction
  • Standard JIT provisioning for internal users logging into Sales org from Service org IdP
  • Portal API access: Auth Code + PKCE (customer-facing mobile app)
  • Named Credentials for org-to-org callouts (Service —> Sales for order data)

Why Salesforce as IdP: No corporate IdP exists, and Salesforce is the user SOR for both internal and portal users. Recommending a dedicated IdP (Okta) would add cost and complexity that the scenario does not justify.

Scenario 3: Legacy System Bridge

Situation: Manufacturing company with on-prem SAP system that uses SAML-based SSO. A new middleware layer needs to call Salesforce APIs on behalf of users who are already authenticated via SAML.

What you’d present:

  • SAML Bearer flow — exchanges the existing SAML assertion for a Salesforce OAuth access token
  • No re-authentication required (user already proved identity to SAP’s IdP)
  • Connected App configured with SAML assertion settings
  • Named Credentials on the Salesforce side for any callouts back to SAP
  • Plan to migrate toward JWT Bearer as the middleware modernizes

Why SAML Bearer: The middleware already has a valid SAML assertion. SAML Bearer avoids re-authentication and bridges the existing SAML infrastructure to OAuth-based API access.

Deep Dive References

Sources