How to enable multiple delegated authentication service in one Salesforce Organisation ?


How can we enabled multiple delegated authentication service in one Salesforce Organisation ?


As you may noticed, we can configure only one Delegated Authentication URL Service in the Single Sign On Setting of your Org. Now what’s happened if you have multiple different portal (with their own security mechanism) to integrate with Salesforce when you have only one Org instance and want to benefit from the delegated authentication Service provided by Salesforce ?


We can derive the facade pattern to implement this service. This service can be located anywhere in your network and must be publicly available (HTTPS is recommended here). You can even host this service in your Salesforce’s Org by exposing this service as a SOAP Service.

The delegated authentication Service

Please refer to the following documentation to understand the delegated authentication service:

Salesforce provide top-down approach by providing the WSDL interface for this service. It is available in your Org (Setup| Develop | API | Download Delegated Authentication WSDL).

Multiple Authentication Service - SE - Delegated Authentication SOAP Request-Response (1)

Proof of Concept

Let’s validate this by mocking a SOAPUI Service based on the WSDL provided by Salesforce, and use Groovy scripting functionality to route dynamically the request to the real implementation of this delegated service. For the purpose of this demo, I will used the sourceIp element in my SOAP request to identify the caller of this service. I would recommend to use either SOAP Header or HTTP header to store this “routing” information.

Below the screensot of my SOAPUI Settings:

Below groovy code i have used to this purpose. I have used the groovy-wslite as a WS client (just download the JAR and put it in your SOAPUI library extension to made to available: C:\Program Files\SmartBear\SoapUI-5.1.3\bin\ext\groovy-wslite-1.1.2.jar).

import wslite.soap.*
import wslite.http.*
import wslite.soap.SOAPClient
import wslite.http.HTTPClientException
import wslite.http.HTTPRequest
import wslite.http.HTTPResponse
import wslite.soap.SOAPClient
import wslite.soap.SOAPFaultException
import wslite.soap.SOAPResponse "context=" + context
def groovyUtils = new context )  "groovyUtils=" +groovyUtils  "mockRequest.requestContent=" + mockRequest.requestContent

// create XmlHolder for request content
def holder = new mockRequest.requestContent )
def _username = holder["//*:username"]
def _password = holder["//*:password"]
def _sourceip = holder["//*:sourceIp"] "_username=" + _username "_password=" + _password "_sourceip=" + _sourceip
def DELEGATED_AUTH_URL_PORTAL2 = "https://PORTAL2/IMS-IdentityManager/services/AuthenticationService"
def DELEGATED_AUTH_URL_PORTALDEFAULT = "https://PORTALDEFAULT/services/AuthenticationService"

switch (_sourceip) {
        case ~/^PORTAL1$/:
   "Routing to PORTAL1 Portal Delegated AuthN Service"          
            context.myContentResponse = call_DelegatedAuthenticationFacade(DELEGATED_AUTH_URL_PORTAL1, _username, _password, _sourceip)   
        case ~/^PORTAL2$/:
   "Routing to PORTAL2 Portal Delegated AuthN Service"          
            context.myContentResponse = call_DelegatedAuthenticationFacade(DELEGATED_AUTH_URL_PORTAL2, _username, _password, _sourceip)   
   "Routing to DEFAULT Portal Delegated AuthN Service"          
            context.myContentResponse = call_DelegatedAuthenticationFacade(DELEGATED_AUTH_URL_PORTALDEFAULT, _username, _password, _sourceip)   

String call_DelegatedAuthenticationFacade(String serviceLocationUrl, String _username, String _password, String _sourceip) {
	def String defaultResponse = '''
<soap:Envelope xmlns:soap="" xmlns:xsi="" xmlns:xsd="">
      <AuthenticateResult xmlns="">
	try {
		SOAPClient client = new SOAPClient(serviceLocationUrl)
	  	def response = client.send(SOAPAction:'') {  
	      body {
	          Authenticate('xmlns':'') {
	  	HTTPRequest myRequest = response?.httpRequest
	  	HTTPResponse myResponse = response?.httpResponse
	  	return debug(defaultResponse, myRequest, myResponse)
	} catch (SOAPFaultException soapEx) {
	    return debug(defaultResponse, soapEx.httpRequest, soapEx.httpResponse)
	} catch (HTTPClientException httpEx) {
	    return debug(defaultResponse, httpEx.request, httpEx.response)
	} catch (Exception Ex) {
	    return debug(defaultResponse, Ex.request, Ex.response)

String debug(String defaultResponse, HTTPRequest request, HTTPResponse response) {"*****************************************************************************************************")"HTTPRequest $request with formatted content:\n${request?.contentAsString}")"HTTPResponse $response with formatted content:\n${response?.contentAsString}")
  defaultResponse = "${response?.contentAsString}""RETURNED RESPONSE TO FACADE\n${defaultResponse}")
  return defaultResponse

The script response content SOAP response generated by the groovy SCRIPT.


Thanks for reading.