Skip to main content

Salesforce SSO: SAML 2.0 vs OpenID Connect Explained

Updated Add a comment
💬 In plain words: Single Sign-On (SSO) lets users log in once with a trusted provider and enter connected applications without re-entering credentials. Security Assertion Markup Language (SAML 2.0) is an established XML-based standard commonly used for corporate workforce directories like Microsoft Entra ID or Okta. OpenID Connect (OIDC) is a modern JSON-based identity layer built on OAuth 2.0, suited for mobile apps and consumer portals such as "Login with Google." Both protocols verify identity and establish a valid Salesforce session.
📌 Illustrative Dual-SSO Architecture: Picture a company running a single Salesforce org for both staff and customers. Internal employees authenticate through corporate Microsoft Entra ID using SAML 2.0 SSO on the org's My Domain login page—one employee credential covers their daily tools. Meanwhile, external users on the Experience Cloud customer portal sign in via "Login with Google," powered by an OpenID Connect Auth. Provider. The same Salesforce org supports both protocols simultaneously, tailored to each user population.

🔑 Key Points

  • Externalized Authentication: Both SAML 2.0 and OpenID Connect delegate password verification and Multi-Factor Authentication (MFA) to an external Identity Provider (IdP), keeping passwords out of Salesforce.
  • Protocol Format and Transport: SAML 2.0 exchanges digitally signed XML assertions over browser HTTP POST or Redirect bindings. OpenID Connect uses RESTful HTTP endpoints and returns a signed JSON Web Token (JWT) called an id_token alongside an OAuth 2.0 access token.
  • Salesforce Configuration Paths: SAML 2.0 is configured under Single Sign-On Settings in Setup. OpenID Connect is configured under Auth. Providers and relies on an Apex Registration Handler class to map and create users.
  • Identity Matching Stability: Matching users on mutable fields like email address or username causes isolated login failures whenever names or domains change. Using a dedicated, immutable FederationIdentifier (Federation ID) prevents these disruptions.
  • Flow Direction Matters: Service Provider (SP)-initiated SSO starts at your Salesforce My Domain URL, preserving deep links and binding the response to a specific request ID. IdP-initiated SSO starts at a corporate app launcher tile, sending an unsolicited assertion that requires careful RelayState handling to maintain target URLs.
🧠 Core Rule: SAML 2.0 uses signed XML assertions and dominates enterprise workforce SSO; OpenID Connect layers JSON identity tokens on top of OAuth 2.0 and excels in consumer portals, mobile apps, and modern API ecosystems.

🔍 Concept: How SAML 2.0 and OpenID Connect Compare in Salesforce

When you configure Single Sign-On in Salesforce, you separate the system that stores and checks credentials—the Identity Provider (IdP)—from the application the user wants to access—the Service Provider (SP), or Relying Party (RP) in OpenID Connect terminology. Generally available across standard Salesforce editions, My Domain is a foundational prerequisite for both approaches because it provides a dedicated org URL to route authentication requests and receive callbacks.

SAML 2.0: The Enterprise XML Standard

In a SAML 2.0 flow, trust is established ahead of time by exchanging metadata between Salesforce and your corporate IdP (such as Okta, PingFederate, or Microsoft Entra ID). The metadata includes an Entity ID (a unique name for the system), redirect endpoints, and an X.509 public certificate used to verify digital signatures.

When an employee tries to access Salesforce, Salesforce redirects their browser to the IdP with a <samlp:AuthnRequest> message. After the user authenticates at the IdP, the IdP sends an HTTP POST back to the Salesforce Assertion Consumer Service (ACS) URL containing a signed <saml:Assertion> XML document. Salesforce checks the digital signature against the uploaded X.509 certificate, verifies the validity timestamps (NotBefore and NotOnOrAfter), confirms the Audience matches your Salesforce Entity ID, and extracts the subject identifier (NameID) or custom attributes to locate the matching User record.

Salesforce also supports SAML Just-In-Time (JIT) Provisioning directly through configuration or a custom Auth.SamlJitHandler Apex class. When enabled, if an assertion arrives for a user who does not yet exist in Salesforce, the platform reads attributes such as profile, email, and last name from the XML payload and creates or updates the user record during login.

OpenID Connect (OIDC): Identity Built on OAuth 2.0

OAuth 2.0 was originally built for authorization—granting an application permission to access data on a user's behalf via an access_token. Because an access token does not standardize how to tell an application who just logged in, OpenID Connect adds an authentication layer directly on top of the OAuth 2.0 Authorization Code flow.

When you configure an OpenID Connect Auth. Provider in Salesforce, you supply a Consumer Key (Client ID), Consumer Secret, Authorize Endpoint URL, and Token Endpoint URL. When a user clicks "Login with Google" or a custom OIDC button on an Experience Cloud site, Salesforce redirects the browser to the IdP's authorization endpoint with the openid scope. Once authenticated, the IdP redirects the browser back to the Salesforce callback URL with a short-lived authorization code.

Behind the scenes, Salesforce exchanges that code at the IdP's token endpoint over a direct back-channel HTTPS call. The IdP returns a JSON payload containing an id_token (a Base64Url-encoded JSON Web Token containing claims like sub for subject, iss for issuer, and email) and an access_token. Salesforce optionally queries the IdP's UserInfo endpoint for additional profile attributes and then invokes an Apex class implementing the Auth.RegistrationHandler interface. This handler gives you programmatic control in Apex to match existing users, deduplicate contacts, and assign permission sets.

Architecture comparison diagram showing SAML 2.0 XML assertions for enterprise workforce SSO versus OpenID Connect JSON JWT id_tokens for consumer and mobile authentication in Salesforce

🎬 Scenario Walkthrough: The Matching Key That Changed

Consider a realistic enterprise scenario where an organization enables SAML SSO for 4,000 internal employees. At launch, everything appears to work smoothly. Six months later, helpdesk tickets begin trickling in: individual employees are suddenly locked out of Salesforce with SAML assertion errors, one person at a time, with no system-wide outage.

The Flawed Approach: During initial setup, the administrator configured SAML to match Salesforce users on their corporate email address or Salesforce Username because the email attribute was already included in the IdP's default assertion template.

Why This Breaks: People's names and email addresses change over time due to marriages, legal name updates, departmental transfers, or domain rebranding after a corporate acquisition. When HR updates a user's primary email in Active Directory, the IdP immediately begins sending the new email in the SAML assertion. Unless the Salesforce key was updated at the exact same moment, the handshake fails for that specific user. Because these failures happen one by one over months, they are frustrating to diagnose.

The Resilient Approach: Configure SAML to match against the Salesforce Federation ID (FederationIdentifier field on the User object), mapped to an immutable directory key such as an employee ID number or an object GUID.

The Payoff: Employee name and email updates flow cleanly without breaking authentication. Always choose an identity matching key that is immutable by design rather than an attribute that merely happens to be convenient.

🛠️ Worked Example: Writing an OpenID Connect Registration Handler

While SAML SSO can match a FederationIdentifier purely through declarative Setup options, OpenID Connect Auth. Providers require an Apex class that implements the Auth.RegistrationHandler interface to link the incoming OIDC payload to a Salesforce User record.

Below is an illustrative, runnable Apex skeleton showing how to match an internal user by a stable subject identifier stored in FederationIdentifier rather than relying solely on a mutable email address. Note that this example requires testing and adaptation in a sandbox environment to match your specific profile names, community requirements, and error-handling policies before deployment.

Prerequisites and Context

  • Where it runs: Select this class in the Registration Handler field of your OpenID Connect Auth. Provider configuration in Salesforce Setup, and specify an active administrative user in the Execute Registration As field.
  • Security & Permissions: The handler executes in system context under the designated "Execute Registration As" user. Always enforce strict checks so unverified external accounts cannot match high-privilege internal profiles.
public class OidcFederationIdRegHandler implements Auth.RegistrationHandler {

    // Custom exception for clear login error reporting
    public class RegHandlerException extends Exception {}

    /**
     * Called when no existing ThirdPartyAccountLink is found for the OIDC subject,
     * or when matching an incoming user for the first time.
     */
    public User createUser(Id portalId, Auth.UserData data) {
        // data.identifier holds the immutable 'sub' (subject) claim from the OIDC id_token
        if ( data == null || String.isBlank(data.identifier) ) {
            throw new RegHandlerException('Missing unique subject identifier from Identity Provider.');
        }

        // Look up an existing active Salesforce user by immutable FederationIdentifier
        List<User> matchedUsers = [
            SELECT Id, FirstName, LastName, Email, IsActive
            FROM User
            WHERE FederationIdentifier = :data.identifier
            AND IsActive = true
            LIMIT 1
        ];

        if ( !matchedUsers.isEmpty() ) {
            // Return the matched User record to establish the session and link accounts
            return matchedUsers[0];
        }

        // If you do not want automatic user creation, block unknown users explicitly:
        throw new RegHandlerException(
            'No active Salesforce user found matching Federation ID: ' + data.identifier
        );
    }

    /**
     * Called on subsequent logins after a ThirdPartyAccountLink is established.
     */
    public void updateUser(Id userId, Id portalId, Auth.UserData data) {
        if ( data == null ) {
            return;
        }

        User u = new User(Id = userId);
        Boolean needsUpdate = false;

        // Safely sync changed email or last name without breaking the FederationIdentifier link
        if ( String.isNotBlank(data.email) ) {
            u.Email = data.email;
            needsUpdate = true;
        }
        if ( String.isNotBlank(data.lastName) ) {
            u.LastName = data.lastName;
            needsUpdate = true;
        }

        if ( needsUpdate ) {
            update u;
        }
    }
}

How to Verify and Troubleshoot

  1. Inspect the Test-Only Initialization URL: Every Auth. Provider in Salesforce Setup generates a Test-Only Initialization URL. Open this URL in an incognito browser window before wiring up the login page. After authenticating at your IdP, Salesforce returns an XML page displaying the exact Auth.UserData attributes received from the id_token and UserInfo endpoint.
  2. Validate SAML Payloads: For SAML 2.0 implementations, navigate to Single Sign-On Settings and click SAML Assertion Validator. When a user login fails, Salesforce automatically captures the last failed assertion so you can inspect whether the signature, timestamp skew, Recipient URL, or FederationIdentifier lookup caused the rejection.

🧭 360 Card — SSO: SAML 2.0 vs OpenID Connect

Rule: Workforce SSO should align with whatever standard your enterprise IdP manages best—typically SAML 2.0 (or enterprise OIDC). Customer-facing Experience Cloud portals and mobile applications should use OpenID Connect.

Benefit: Users log in with a single credential, security policies and MFA are enforced in one central system, and user passwords are never stored inside Salesforce.

Tradeoff: You delegate your front door to an external identity system. If the corporate IdP suffers an outage or its signing certificate expires unannounced, users cannot log into Salesforce.

Boundaries & Limits: SAML 2.0 relies on browser redirects and XML assertions; OpenID Connect uses REST/JSON and returns a JWT id_token. Salesforce can act as a Service Provider for either protocol and can also act as an Identity Provider for downstream apps. My Domain is mandatory. Note that standard UI SSO settings do not automatically stop a user from authenticating directly against the SOAP/REST API with a password unless you enable the Is Single Sign-On Enabled permission on their Profile or Permission Set.

IdP-Initiated SAML Caution: Launching Salesforce from an IdP portal tile sends an unsolicited assertion with no originating request ID (InResponseTo) to validate against, and deep links to specific Salesforce records will fail unless RelayState is explicitly passed.

Lifecycle Reality: Choosing SAML versus OIDC is rarely the hardest part of an architecture review. Managing the user lifecycle around it—provisioning new hires, maintaining immutable matching keys, and immediately deactivating leavers via System for Cross-domain Identity Management (SCIM) or automated flows—determines long-term stability.

⚠ ARCHITECT & INTERVIEW TRAP: Never match SSO users on email address in an enterprise environment, and remember that FederationIdentifier is case-sensitive by default unless you enable Make Federation ID case-insensitive in Single Sign-On Settings. Emails change during name updates or domain migrations, causing silent, single-user login failures that are slow to trace. Map FederationIdentifier to an immutable employee number or directory UUID.

❓ Core Q&A and Architecture Scenarios

Q: Corporate wants workforce SSO from their enterprise IdP, and the customer community needs to log in using consumer social identities. How do you architect both in a single org?
🎯 Say this first: Split the authentication architecture by user population. Route internal workforce users through SAML 2.0 (or enterprise OIDC) against the corporate IdP via My Domain, and configure OpenID Connect Auth. Providers with an Apex Registration Handler for Experience Cloud customer logins.

A: Running two SSO protocols in the same Salesforce org is standard practice because employees and external customers have different lifecycle requirements:

  • For the Internal Workforce: Configure SAML 2.0 with Salesforce acting as the Service Provider (SP). Enforce SP-initiated login flows via your My Domain URL so emailed record links (deep links) take users straight to the record after authentication. Provision users ahead of time via SCIM (using standard REST APIs from Okta or Entra ID) or use SAML JIT provisioning to map directory roles to Salesforce profiles and permission sets. Enforce the Is Single Sign-On Enabled user permission on employee profiles to disable Salesforce passwords completely, while keeping a dedicated System Administrator profile exempt for emergency break-glass access. Centralize MFA enforcement at the corporate IdP.
  • For the Customer Community (Experience Cloud): Configure OpenID Connect Auth. Providers (such as Google, Apple, or a consumer CIAM like Auth0/Okta Customer Identity). Pair the Auth. Provider with a custom Auth.RegistrationHandler Apex class that verifies the incoming email claim, checks for an existing Contact and User to prevent duplicates, and assigns the Customer Community license profile. Expose these Auth. Providers on the Experience Cloud Workspace Login & Registration page.
Q1: IdP-initiated vs. SP-initiated SAML — why do security and architecture teams strongly prefer SP-initiated flows?

A1: The difference comes down to request verification and user navigation:

  • No Request-Response Binding in IdP-Initiated Flows: In an IdP-initiated flow, the user clicks a Salesforce tile inside their corporate portal (like Okta or MyApps), and the IdP sends an unsolicited SAML response directly to Salesforce. Because Salesforce never issued an initial <samlp:AuthnRequest>, the assertion lacks an InResponseTo attribute. Without that correlation ID, the Service Provider cannot verify that the assertion is answering a fresh request initiated by that specific browser session, increasing exposure to assertion-replay or cross-site request forgery (CSRF) login attacks.
  • Deep-Linking Friction: When a colleague clicks a link to a specific Salesforce Opportunity in Slack or email, an SP-initiated flow starts at Salesforce, captures the target Opportunity URL, sends the user to the IdP, and returns them directly to that Opportunity. IdP-initiated flows always land on the default home page unless custom RelayState parameters are hardcoded into the portal tile.
  • Compensating Controls: If business users insist on keeping their IdP app-launcher tile, configure short assertion validity windows (for example, 3 to 5 minutes), enforce strict Audience and Recipient checks, and require signed assertions.
Q2: SSO goes down at 9:00 AM on Monday. What did your architecture pre-decide before launch, and what does your recovery playbook look like?

A2: Resilient SSO design separates pre-incident preparation from live recovery steps:

  • Pre-Decisions Built into the Architecture:
    • Break-Glass Administrator Access: Maintain at least two System Administrator accounts on a profile that does not enforce Is Single Sign-On Enabled, protected by native Salesforce MFA. Keep the standard login option available via the ?login query parameter on the My Domain URL or by not hiding the native login form completely until fallback procedures are verified.
    • Password Rotation Discipline: A frequent failure during an outage is discovering that nobody knows the break-glass account password or its MFA authenticator device was lost when a previous admin left. Test break-glass logins quarterly.
    • Certificate Expiration Monitoring: Schedule calendar alerts and automated monitoring 60, 30, and 7 days before both the IdP signing certificate and the Salesforce SP certificate expire.
  • Live Recovery Playbook:
    1. Log in via the break-glass administrator account and open Login History and the SAML Assertion Validator to determine the exact failure cause.
    2. Distinguish between a global IdP outage and a Certificate Expiry. Monday morning outages frequently happen because an IdP team rotated an expired X.509 signing certificate over the weekend without giving the new public .cer file to the Salesforce team.
    3. If the certificate changed, upload the new IdP certificate in Single Sign-On Settings—recovery is immediate.
    4. If the IdP itself is experiencing a prolonged outage and business operations are halted, temporarily re-enable standard login on the My Domain page and uncheck Is Single Sign-On Enabled on critical operational profiles, keeping native Salesforce MFA active.
Q3: Walk me through implementing SAML 2.0 SSO in Salesforce, end to end.

A3: A clean implementation follows nine ordered steps:

  1. Verify My Domain: Confirm your org's My Domain is deployed and active. Your My Domain URL defines the endpoints your IdP will trust.
  2. Collect IdP Metadata: Obtain the XML metadata file or configuration values from your identity team: the IdP Issuer (Entity ID), the IdP Single Sign-On Login URL, and the X.509 public signing certificate.
  3. Create the SAML Configuration in Salesforce: In Setup, go to Single Sign-On Settings, check SAML Enabled, and click New (or New from Metadata File). Upload the IdP certificate, set the Issuer, and specify your Salesforce Entity ID (always use your My Domain URL, such as https://yourcompany.my.salesforce.com).
  4. Select Identity Location and Matching Key: Set SAML Identity Type to Assertion contains the Federation ID from the User object, and specify whether that ID sits in the NameIdentifier element or a custom Attribute.
  5. Register Salesforce in the IdP: Download the Salesforce SP Metadata XML from your Single Sign-On setting page and hand it to the IdP administrator, or give them the generated Login URL (Assertion Consumer Service / ACS URL) and Entity ID so they can configure attribute mappings.
  6. Populate Matching Keys or Configure Provisioning: Populate the FederationIdentifier field on existing Salesforce users via Data Loader or a SCIM integration, or enable SAML JIT Provisioning to create users on first login.
  7. Validate Assertions: Attempt a test login with a pilot user and inspect the result in the SAML Assertion Validator. It highlights exact pass/fail status for timestamps, audience restrictions, signatures, and subject lookups.
  8. Test Both Initiation Directions: Test clicking the Salesforce tile from the IdP dashboard (IdP-initiated) and pasting a direct link to a Salesforce record in a fresh browser window (SP-initiated deep link).
  9. Enforce Gradually by Profile: Enable the IdP on the Authentication Configuration section of your My Domain page. Roll out enforcement profile-by-profile using the Is Single Sign-On Enabled permission, leaving break-glass admins on direct login with native MFA.
Q4: Why should you match users on Federation ID rather than Salesforce Username or Email?
🎯 Say this first: Because usernames and email addresses change during normal business events, whereas an authentication matching key must remain immutable across the user's entire employment lifecycle.

A4: Matching on email or username introduces three specific operational weaknesses:

  • Silent Single-User Lockouts: When an employee changes their last name or transfers to a subsidiary with a different email domain, Active Directory updates their email address immediately. If Salesforce matches on email or username, that individual's next login fails until an admin manually updates Salesforce.
  • Multi-Org and Sandbox Collisions: A Salesforce Username must be globally unique across all Salesforce production and sandbox instances worldwide. In sandboxes, Salesforce appends the sandbox name (for example, user@company.com.uat) to every username. If your IdP sends user@company.com and you match on Username, sandbox SSO immediately breaks. By contrast, FederationIdentifier only needs to be unique within a single org, so the exact same Employee ID works across production and every refreshed sandbox without reconfiguring the IdP.
  • Audit Stability: Mapping FederationIdentifier to an immutable HR employee number or directory GUID decouples human-readable contact details from cryptographic identity resolution.

🧪 Self-Check Question: You refresh a Full Copy Sandbox from Production. In Production, SAML SSO works for all employees. In the freshly copied Sandbox, after updating the SAML certificate and ACS URL, every employee receives an "Invalid User" error during login. Why did this happen if the configuration matches Production?

Answer & Explanation: Your SAML configuration is likely set to Assertion contains the User's Salesforce username instead of Federation ID. When you refresh a sandbox, Salesforce automatically appends .sandboxname to every user's Username field, while the corporate IdP continues sending their normal production username (user@company.com). Switching the SAML Identity Type to match on Federation ID resolves this permanently because FederationIdentifier values are copied intact during sandbox refreshes without suffixes.

🔗 Next Concept Follow-Up: From Authentication to Automated Deprovisioning

Follow-Up Q: Once SAML 2.0 or OpenID Connect SSO is live with Just-In-Time (JIT) provisioning, what happens when an employee leaves the company—and how should you handle deprovisioning?

A: Here is the crucial limitation: JIT provisioning only runs when a user successfully logs in. When an employee is terminated and deactivated in your corporate IdP (Okta or Microsoft Entra ID), they can no longer log into Salesforce through SSO, which protects the front door. However, because they never log in again, JIT never fires to deactivate their Salesforce User record.

Leaving terminated users active in Salesforce poses three problems: they continue consuming paid user licenses, they still receive scheduled reports or workflow emails, and any active OAuth refresh tokens or API sessions they previously authorized may remain valid until revoked. To close this gap, pair your SSO setup with outbound SCIM (System for Cross-domain Identity Management) provisioning from your IdP to Salesforce's REST API, or build an automated HR termination integration that sets IsActive = false and revokes active sessions the moment an employee leaves.

📚 Official Salesforce Documentation

To verify current release details or dive deeper into protocol parameters, consult these primary Salesforce resources:

Was this article helpful?

Have a question or spotted a mistake? Ask here about this article

Found this guide useful? Buy me a coffee (opens in a new tab)

Comments

Questions, corrections and your own experience are all welcome.