Skip to main content

Integrating PingID & PingFederate with Salesforce: OAuth 2.0, SSO & Apex Guide

In plain words: PingID (Ping Identity) is an enterprise identity and multi-factor authentication (MFA) provider. Integrating Ping Identity with Salesforce allows users to authenticate into custom applications or verify their credentials securely using modern protocols like OpenID Connect (OIDC) and OAuth 2.0. In Salesforce, this can be done natively via Auth. Providers (Single Sign-On) or programmatically using Apex REST controllers.

Enterprise identity management requires unified authentication across cloud platforms, mobile applications, and internal tools. Rather than managing separate sets of credentials inside Salesforce, organizations use central Identity Providers (IdPs) like Ping Identity (PingFederate / PingOne / PingID). This guide explains how OAuth 2.0 authorization code flows work between Ping Identity and Salesforce, complete with step-by-step Apex and UI implementations.

1. Understanding the OAuth 2.0 Code Flow with Ping Identity

Connecting Salesforce to Ping Identity programmatically follows the standard OAuth 2.0 Authorization Code Grant pattern:

  • Authorization Request: The user initiates the flow from a Salesforce UI, redirecting their browser to Ping's /as/authorization.oauth2 endpoint with your Client ID and redirect URI.
  • User Authentication & MFA: The user verifies their identity and completes PingID MFA on the identity provider login screen.
  • Authorization Code Callback: Ping redirects the user back to the Salesforce callback URL with a temporary, single-use authorization code.
  • Token Exchange: An Apex backend service executes a server-to-server POST request to Ping's /as/token.oauth2 endpoint, exchanging the code for an access_token and identity claims.
360 Ping Identity Architecture Card:
  • Protocols Supported: OAuth 2.0, OpenID Connect (OIDC), SAML 2.0.
  • Core Endpoints: Authorization (/as/authorization.oauth2) and Token (/as/token.oauth2).
  • Declarative Option: Salesforce Auth. Providers (OpenID Connect type) with a custom Registration Handler.
  • Programmatic Option: Apex HTTP callouts secured via Named Credentials / External Credentials.

2. Step-by-Step Configuration in Salesforce

Step 1: Whitelist Ping Identity Endpoints
Navigate to Setup > Security > Remote Site Settings and add your Ping Identity Base URL (e.g., https://auth.pingidentity.com or your company's dedicated PingFederate domain) to enable outbound HTTP callouts.
Step 2: Apex Controller for Authorization and Token Exchange
Create an Apex controller to construct the redirect URL and handle the token exchange securely:
public with sharing class PingAuthenticationController {

    // Store sensitive keys in Custom Metadata or Named Credentials in production
    private static final String CLIENT_ID = 'YOUR_PING_CLIENT_ID';
    private static final String CLIENT_SECRET = 'YOUR_PING_CLIENT_SECRET';
    private static final String BASE_URL = 'https://auth.pingidentity.com';

    // Generates the login redirect URL
    public PageReference initiatePingLogin() {
        String redirectUri = getCallbackUrl();
        String stateToken = EncodingUtil.urlEncode(Crypto.getRandomInteger().format(), 'UTF-8');

        String authUrl = BASE_URL + '/as/authorization.oauth2?' +
            'response_type=code' +
            '&client_id=' + EncodingUtil.urlEncode(CLIENT_ID, 'UTF-8') +
            '&redirect_uri=' + EncodingUtil.urlEncode(redirectUri, 'UTF-8') +
            '&scope=' + EncodingUtil.urlEncode('openid profile email', 'UTF-8') +
            '&state=' + stateToken;

        return new PageReference(authUrl);
    }

    // Handles the OAuth callback and exchanges code for access token
    public PageReference handleCallback() {
        String authCode = ApexPages.currentPage().getParameters().get('code');
        String error = ApexPages.currentPage().getParameters().get('error');

        if (String.isNotBlank(error) || String.isBlank(authCode)) {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Authentication error: ' + error));
            return null;
        }

        HttpRequest req = new HttpRequest();
        req.setEndpoint(BASE_URL + '/as/token.oauth2');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');

        String body = 'grant_type=authorization_code' +
            '&code=' + EncodingUtil.urlEncode(authCode, 'UTF-8') +
            '&client_id=' + EncodingUtil.urlEncode(CLIENT_ID, 'UTF-8') +
            '&client_secret=' + EncodingUtil.urlEncode(CLIENT_SECRET, 'UTF-8') +
            '&redirect_uri=' + EncodingUtil.urlEncode(getCallbackUrl(), 'UTF-8');

        req.setBody(body);

        Http http = new Http();
        HttpResponse res = http.send(req);

        if (res.getStatusCode() == 200) {
            Map<String, Object> tokenPayload = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
            String accessToken = (String) tokenPayload.get('access_token');
            String idToken = (String) tokenPayload.get('id_token');

            // Process user session or redirect to home dashboard
            PageReference targetPage = new PageReference('/apex/PingAuthSuccess');
            targetPage.setRedirect(true);
            return targetPage;
        } else {
            ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Token request rejected: ' + res.getBody()));
            return null;
        }
    }

    private String getCallbackUrl() {
        return URL.getOrgDomainUrl().toExternalForm() + '/apex/PingCallback';
    }
}
Step 3: User Interface & Callback Visualforce Pages
Create the initiation page and the corresponding callback receiver page.
<!-- PingLogin.page -->
<apex:page controller="PingAuthenticationController">
    <apex:form>
        <apex:pageBlock title="Enterprise SSO Portal">
            <p>Sign in securely using your organization's PingID credentials.</p>
            <apex:commandButton value="Authenticate with PingID" action="{!initiatePingLogin}" />
        </apex:pageBlock>
    </apex:form>
</apex:page>
<!-- PingCallback.page -->
<apex:page controller="PingAuthenticationController" action="{!handleCallback}">
    <apex:pageMessages />
    <apex:outputPanel>
        <p>Validating credentials with Ping Identity, please wait...</p>
    </apex:outputPanel>
</apex:page>

3. Programmatic Apex vs. Declarative Auth. Providers

While custom Apex controllers offer fine-grained control for specific app pages, Salesforce provides native declarative Single Sign-On (SSO) tools:

  • Salesforce Auth. Providers: Go to Setup > Auth. Providers and choose OpenID Connect. Point the authorization and token endpoints to Ping Identity. Salesforce automatically handles token exchange, user registration, and login screen integration with zero custom Apex HTTP code.
  • Named Credentials for Outbound APIs: When calling external APIs secured by Ping Identity, configure an External Credential with OAuth 2.0 authentication to automate token storage and token refreshes.

4. Common Traps & Security Best Practices

Security Trap: Hardcoding Client Secrets and Missing State Parameters
Hardcoding Client Secrets in Apex source code exposes private keys to sandbox clones and version control systems. Additionally, omitting the state parameter during authorization leaves authentication flows vulnerable to Cross-Site Request Forgery (CSRF) attacks.
Core Rule: Use Salesforce's native Auth. Providers (OpenID Connect) for user Single Sign-On (SSO) whenever possible. If building custom Apex authentication, always store secrets in Protected Custom Metadata and validate unique state tokens.
  • Validate State Parameters: Generate a cryptographically random state token during login initiation and verify it upon callback to prevent CSRF attacks.
  • Always URL-Encode Parameters: Wrap every query parameter in EncodingUtil.urlEncode() to avoid malformed redirect URI errors.
  • Mock Callouts in Unit Tests: Write HttpCalloutMock classes to simulate Ping token responses and achieve test coverage without calling live identity servers.

Summary

Integrating PingID and Ping Identity with Salesforce enhances enterprise security by centralizing authentication and enforcing robust multi-factor policies. Whether deploying declarative OpenID Connect Auth. Providers for user login or implementing custom Apex OAuth code exchanges, teams can deliver seamless, single-sign-on experiences across the entire Salesforce ecosystem.