- Architecting secure Single Sign-On (SSO) using SAML 2.0 in Federated Identity environments.
- Configuring Salesforce as both a Service Provider (SP) and Identity Provider (IdP).
- Harnessing OAuth 2.0 flows for mobile apps, single-page applications, and server-to-server APIs.
- Customising authentication behaviour using SAML JIT (Just-In-Time) provisioning and Auth Providers.
- Debugging complex SSO handshakes, signature mismatches, and certificate expirations.
SAML 2.0 vs OAuth 2.0 in the Enterprise Identity Stack
In enterprise environments, managing identity and access control across a complex landscape of applications requires robust architectures. The two primary protocols used for this purpose are SAML 2.0 (Security Assertion Markup Language) and OAuth 2.0. To build a secure environment, architects must understand the different roles, strengths, and use cases of these protocols.
SAML 2.0 is an XML-based federated identity standard designed for Single Sign-On (SSO). It operates by exchanging XML-based assertions between an Identity Provider (IdP), which stores and verifies user credentials, and a Service Provider (SP), which hosts the application. SAML is designed for authentication, sharing secure user identity and profile attributes across web browsers.
OAuth 2.0, on the other hand, is a token-based authorization framework. It does not natively handle authentication. Instead, it is designed to grant third-party applications secure, limited access to HTTP resources using JSON Web Tokens (JWT) or opaque access tokens.
To support authentication on top of OAuth, the industry developed OpenID Connect (OIDC). OIDC introduces an identity layer on top of OAuth 2.0, using an ID Token (a structured JWT) alongside the standard access token. OIDC is highly suited for modern single-page web applications and mobile apps, where parsing large XML SAML payloads can be inefficient.
| Feature | SAML 2.0 | OAuth 2.0 / OIDC |
|---|---|---|
| Primary Focus | Federated Web SSO (Authentication) | API Authorization & Identity Layer |
| Payload Format | XML (Cryptographically Signed) | JSON (Signed JWT Tokens) |
| Transport Channel | Browser Redirects & POST Requests | Direct HTTP API calls & Headers |
| Best For | Enterprise Web Portals, Desktop SSO | Mobile apps, REST APIs, SPAs |
Selecting the right protocol helps ensure that web portals, API integrations, and mobile applications are secured with the appropriate authentication controls.
Configuring Salesforce as a Service Provider (SP)
When Salesforce acts as a Service Provider (SP), users authenticate through an external Identity Provider (such as Okta, Azure AD, or Ping Identity) before accessing the CRM. This is the standard configuration for enterprise environments, allowing organisations to manage identity policies in a central system.
The authentication handshake can be initiated in two ways:
- Service Provider (SP)-Initiated: The user attempts to access a deep link directly within Salesforce (e.g.
https://mycompany.my.salesforce.com/lightning/page/home). Finding no active session, Salesforce redirects the user's browser to the IdP's login page with a signedSAMLRequestparameter. Once authenticated, the IdP redirects the browser back to the Salesforce assertion consumer service (ACS) URL with aSAMLResponsecontaining a signed XML assertion. - Identity Provider (IdP)-Initiated: The user logs into their central application portal (e.g. Okta dashboard) and clicks the Salesforce icon. The IdP generates the
SAMLResponseand posts it directly to the Salesforce ACS URL via the browser. Salesforce validates the signature, maps the user, and instantiates the session.
To configure Salesforce as an SP, you must import the IdP's metadata XML file, upload the IdP's SAML signing certificate, and set your user mapping strategy. Standardise on mapping the IdP's NameID attribute to the Salesforce Username or a custom FederationIdentifier field on the User record.
Deploying Salesforce as an Identity Provider (IdP)
Salesforce can also act as the Identity Provider (IdP) for external applications. In this setup, Salesforce manages user credentials, and users can log into external systems (such as Workday or a custom internal app) using their Salesforce sessions.
To configure Salesforce as an IdP, navigate to identity settings and enable Identity Provider capabilities. This generates a metadata XML document and an IdP certificate. For each external application, you must create a corresponding Connected App inside Salesforce.
Within the Connected App configuration, you will specify:
- Entity ID: The unique identifier provided by the external application.
- ACS URL: The endpoint where the external application receives and processes SAML responses.
- Subject Type: Define how the user is identified in the SAML assertion (e.g. Username, Federation ID, or User ID).
- SAML Issuer: The Salesforce My Domain URL that signs the assertion.
By deploying Salesforce as an IdP, you can leverage native security features, such as login flows and transaction policies, to protect access to external systems across your corporate network.
Extending Authentication with SAML Just-In-Time (JIT) Provisioning
In large enterprise environments, manually creating and updating user records in Salesforce can introduce administrative overhead. SAML Just-in-Time (JIT) Provisioning addresses this by automatically creating or updating Salesforce User records when a user logs in via SSO.
To implement custom logic for JIT provisioning, you must write an Apex class that implements the Auth.SamlJitHandler interface. This interface requires implementing two methods: createUser and updateUser.
The following complete Apex class demonstrates how to parse a SAML assertion to automatically provision and update User records:
global class CustomSAMLJitHandler implements Auth.SamlJitHandler {
private void populateUserData(User u, Map<String, String> attributes) {
u.Email = attributes.get('User.Email');
u.FirstName = attributes.get('User.FirstName');
u.LastName = attributes.get('User.LastName');
u.Alias = (attributes.get('User.FirstName').substring(0, 1) + attributes.get('User.LastName').substring(0, 4)).toLowerCase();
// Map division and department to help determine the user profile
String dept = attributes.get('User.Department');
u.Department = dept;
// Determine Profile assignment based on department attribute
if ('Sales'.equalsIgnoreCase(dept)) {
u.ProfileId = [SELECT Id FROM Profile WHERE Name = 'Standard Sales User' LIMIT 1].Id;
} else {
u.ProfileId = [SELECT Id FROM Profile WHERE Name = 'Standard User' LIMIT 1].Id;
}
}
global User createUser(Id samlProviderId, Id communityId, Id portalId,
String federationId, Map<String, String> attributes, String assertion) {
User u = new User();
u.FederationIdentifier = federationId;
u.Username = federationId + '@sfvedas.com';
u.TimeZoneSidKey = 'Europe/London';
u.LocaleSidKey = 'en_GB';
u.EmailEncodingKey = 'UTF-8';
u.LanguageLocaleKey = 'en_US';
populateUserData(u, attributes);
return u;
}
global void updateUser(Id userId, Id samlProviderId, Id communityId, Id portalId,
String federationId, Map<String, String> attributes, String assertion) {
User u = [SELECT Id, Email, FirstName, LastName, Alias, ProfileId, Department FROM User WHERE Id = :userId];
populateUserData(u, attributes);
update u;
}
}
Deploying a custom JIT handler automates user administration, reduces provisioning delays, and ensures that user profile and role assignments are synchronised with your central identity repository.
Troubleshooting and Hardening SSO Deployments
SSO deployments can experience issues due to cryptographic errors, configuration drift, or network latency. Architects should be familiar with common failure modes and their resolutions:
- SAML Assertion Validation Failures: Use the native Salesforce SAML Assertion Validator. Paste the raw XML assertion into the validator to check for signature mismatches, expired certificates, or incorrect NameID mapping.
- Clock Skew Mismatch: If the IdP and Salesforce system times are out of sync by more than three minutes, the assertion is rejected. Ensure your IdP synchronises with standard Network Time Protocol (NTP) servers.
- Expired Certificates: Set reminders to rotate certificates before they expire. Update the new certificate in both the IdP and the Salesforce Single Sign-On settings to prevent login outages.
To secure your SSO configuration, apply these hardening best practices:
- Disable direct login access via standard passwords for SSO-enabled users by assigning them a secure Login Policy.
- Enforce the use of HTTPS for all login and metadata exchange endpoints.
- Establish a backup login URL (such as the default Salesforce login page with MFA) for system administrators to prevent being locked out if the IdP experiences an outage.
By systematically troubleshooting authentication issues and applying these security hardening best practices, you can build a stable, secure Single Sign-On deployment that protects your enterprise CRM environments.
Key Takeaways
- Distinguish between SAML 2.0 for federated browser authentication and OAuth 2.0 for API-centric authorization.
- Map external identity attributes to standard Salesforce fields like Username or FederationIdentifier to verify identities.
- Implement the Auth.SamlJitHandler interface in Apex to automate the creation and update of User records at login.
- Utilise the native SAML Assertion Validator to debug signature, expiration, and formatting errors in XML payloads.
- Configure secure administrator backdoors and enforce HTTPS to prevent lockout events during IdP outages.
- Rotate SSO certificates before expiration to avoid sudden login failures across your user base.
Checkpoint: Test Your Understanding
Question 1: What interface must an Apex class implement to customise the creation and update of User records during a SAML Just-In-Time login flow?
Question 2: In a Service Provider (SP)-Initiated SAML SSO flow, where does the user's browser navigate first when attempting to log in?
Question 3: What is the primary utility of the Salesforce SAML Assertion Validator during deployment?
Discussion & Feedback