Making authenticated web service callouts from Salesforce to IBM Cast Iron using SSL/certificates–Part IV

Introduction

This article is the fourth in the five part article series on making authenticated web service callouts from Salesforce to IBM WebSphere Cast Iron using SSL/certificates. Web Service callouts is a powerful feature and the IBM WebSphere Cast Iron provides great integration capabilities. We discussed the basics of the authenticated callouts and the problem scenario in the first part and implemented a solution without the SSL/certificates in the second part. We also discussed about securing the web service with one-way SSL/certificate authentication in the third part. In this part, we will continue to add two-way SSL/certificates that demonstrates the concept of both the parties proving their identities.

Understanding the two-way SSL

As explained in the third part, the one-way SSL/certificates based authentication allows one of the parties (read ‘server’) to prove its identity to the client(s) based on the PKI mechanism such that the client and the server can exchange communication on a secure medium. This is the most commonly found scenario which is widely implemented by most web sites such as amazon.com, ebay.com, etc. Sometimes, this arrangement is not enough and the server needs to know whom it is talking to. This is particularly relevant when you integrate cloud based services with on-premise or other cloud based systems.

Let’s consider a real scenario. You want to integrate the information from your salesforce platform to your on-premise system – assume you have infrastructure as described in the architecture diagram in Part-2. You can secure your IBM WebSphere Cast Iron server with certificates signed by public CA. You may even put firewall rules to restrict access that allows inbound calls only from salesforce.com servers. (adding *.salesforce.com to firewall will not work. Salesforce has a set of IP ranges and the request may arrive from any of these IP addresses. There is no distinction on the requests to indicate the salesforce organization from where the request originated [the salesforce does send the organization name if it is outbound SOAP message based web service callout]. These IP address ranges has to be added to your firewall to restrict the access to salesforce.com servers). But still there is a gaping hole. If someone knows your endpoint who also is a salesforce user (from a different company; for that matter, it can be an individual from salesforce DE user), then he can very well invoke your web services, provided, you do not have other forms of authentication, built into your orchestration. You can always build such other forms of authentication into your orchestrations, but it may not be versatile.

There’s a better solution available which is the two-way SSL/certificates based authentication. In this method, the client, as well, provides its identity to the server to prove it’s identity. This is much better, because, in most cases, this is just a configuration task, especially on the IBM WebSphere Cast Iron side. On the client side, it depends on the platform you use – Salesforce does provide both configuration only and code based approaches. This is definitely better than user name/password based authentication, because, if the user name/password is compromised somehow, then the attacker can easily gain access to your systems. Sure, if the attacker gain access to your client’s public key, then it is still a high risk with two-way SSL/certificates approach as well; but for all practical scenarios, this is highly difficult, if not impossible. But the same is not true with user name/password based approach, for e.g. if the attacker uses brute force method and your password is not strong enough to resist it. There’s much more to this and it is out of scope for this article to discuss elaborately and I’ll write more about the security in a future article series.

To summarize, in two-way SSL/certificates based authentication, both the server and the client(s) prove their identities respectively using SSL certificates. As explained in the Part-3, Salesforce will accept only certificates signed by public CA, when it acts as a client and makes a callout to the server. On the contrary, you can use either self-signed certificates, provided you import this certificate into the Key Store of your IBM WebSphere Cast Iron runtime appliance, or you can use certificates signed by public CA (you don’t need to do any thing special on IBM WebSphere Cast Iron side for this). We are going to see this in action in the remainder of this article.

Tutorial-3: Setting up two-way SSL/certificate authentication

The basic concept here is to add the SSL/certificate authentication to the client side. The concept of two-way SSL/certificate authentication is generic to all platforms and technologies, though the implementation could slightly differ. From Salesforce perspective, there are two ways to accomplish this. They are as follows:

  • Certificate generated from non-Salesforce

  • Certificate generated from Salesforce

In both the scenarios, we can either use self-signed certificates or certificates signed by public CA. This article will explain both these approaches for the above two scenarios.

Certificate generated from non-Salesforce

This is also called the ‘Legacy’ method by Salesforce. In this scenario, we generate the CSR from non-Salesforce system, such as Windows Active Directory Services or Open SSL. This involves some coding work on the Salesforce side which will be explained later.

Self-Signed Certificates

With the self-signed certificates, we can have our own CA installed in our infrastructure and can generate the CSR and sign it. Self-signed certificates may not work in all occasions; for e.g. if the other end can accept only certificate signed by public CA. Usually, this may happen with SaaS vendors or with any third-party services. For our tutorial, we will use the Open SSL to get the self-signed certificates.

Step # 1: Setting up Open SSL and generating root certificate

Download the Open SSL from www.openssl.org for linux. This tutorial uses the windows distribution of Open SSL.  Open a command prompt, and execute the following commands:

set OPENSSL_CONF=E:\openssl-win32\bin\openssl.cfg
path=%path%;E:\openssl-win32\bin
set RANDFILE=E:\openssl-win32\myca\.rnd

In my workstation, I have installed it under E:\OpenSSL-Win32\. Please replace the drive where you have installed in your workstation.

Now that we have setup the Open SSL, let’s generate the root certificate that will be used to sign the certificate that we will generate in the next step. Before proceeding, let’s cover some basics. A digital certificate is verified using a chain of trust. It is formed as a tree structure and the first node of this tree structure is issued by the Root Certificate Authority and may contain intermediate certificates in the tree structure. The private key of the root certificate is used to sign the other certificates. Each certificate in the certificate chain inherits the trust worthiness of it’s parent certificate which goes all the way up to the root certificate. This is why we need a root certificate before creating the actual certificate, since the private key of the root certificate will be used to sign our certificate. IBM WebSphere Cast Iron normally (like most servers) doesn’t allow a certificate to be imported if the chain of trust is not present, though it does provide an option to bypass it, but this is not a recommended practice.

To generate the root certificate, execute the following command:

openssl req -new -x509 -extensions v3_ca -keyout keys\cakey.pem -out certs\cacert.pem -days 730 -newkey rsa:2048

This command generates a new root certificate with new key which is 2048 bits long.

A1-P4-OS-01-GenerateRootCA

Figure 4a. Generate root certificate

Step # 2: Creating the CSR for client

The Certificate Signing Request (CSR) contains the information about your organization and the public key which the CA validates it before signing it. In this case, we have our own CA which will be used to sign this certificate.

Here is the command to generate the CSR.

openssl req -new -nodes -out certs\contoso.csr -key keys\cakey.pem

A1-P4-OS-02-GenerateCSR

Figure 4b. Create CSR using Open SSL (for self-signed certificate)

This will generate the CSR file under certs\contoso.csr. An important thing to note is that the common name should either exactly match your domain name or should match your domain name with wild card. Wild card is used if you want to use the same certificate for the sub domains. For e.g. the same certificate can be used for the URLs secure.contoso.com, docs.contoso.com, contoso.com, if you use ‘*.contoso.com’ in the common name.  If you use IP address, then note that your clients can access the web service only by IP address, the exception being, if your subjectAlternateName has your DNS name in it (same as common name).

Step # 3: Sign the certificate

Now that we have the CSR generated, it needs to be signed which can be done by the following command.

openssl ca -policy policy_anything -cert certs/cacert.pem -in certs/contoso.csr -keyfile keys/cakey.pem -days 730 -out certs/contoso.cer

A1-P4-OS-03-SignCertificateWithRootCA

Figure 4c. Sign the certificate using Open SSL

The above command instructs to sign the CSR using the root certificate that we generated in step # 1 using the private key and set the certificate to expire in 2 years.

IBM WebSphere Cast Iron can accept only PKCS#12 formatted certificates and hence we need to convert our PEM formatted certificate to PKCS#12 format. This can be accomplished by the following command:

openssl pkcs12 -export -out certs/contoso.p12 -in certs/contoso.cer -inkey keys/cakey.pem

A1-P4-OS-04-ConvertPEM2PKCS12

Figure 4d. Convert the PEM encoded certificate to PKCS#12 format

Step # 4: Import the root certificate and self-signed certificate into IBM WebSphere Cast Iron runtime appliance

Most servers including IBM WebSphere Cast Iron ships with root certificates for most of the vendors such as Verisign, Thawte, etc. But since we are using the self signed certificates which is signed by our own CA that we setup in the step # 1, we first need to import the root certificate into the Trust Store.

To do this, click ‘Import’ under the ‘Trust Store’ section of Security->Certificates. This will open up a dialog box. You can either select the file or paste the content from the certificate file. Click ‘Browse’ and select the file and click ‘Open’. Click ‘Import’ and the certificate should be imported into your Trust Store now.

To import the self signed certificate, click ‘Import’ under the ‘Key Store’ section of Security->Certificates. This will open up a dialog box. You can either select the file or paste the content from the certificate file. Click ‘Browse’ and select the file and click ‘Open’. Enter the password that you used to generate the self signed certificate. Click ‘Import’ and the certificate should be imported into your Key Store now.

Step # 5: Update the code to embed the certificate in the web service callout

The web service callout code needs to be updated to include the certificate in the call for the two-way authentication. The certificate that we have now is in PKCS12 format which is a binary format and we need the text version (PEM) of it to embed it into the code. To get this, execute the following command:

openssl base64 -in certs/contoso.p12 -out certs/contoso.pem

Open the contoso.pem file in a text editor and copy the content. Now, update the UserStatusClient file on the Salesforce side by clicking ‘Edit’ against ‘UserStatusClient’ under Setup->Develop->Apex Classes.

string key = ''; // paste the content that you copied from the contoso.pem file.
updateStatusInstance.clientCert_x = key;
updateStatusInstance.clientCertPasswd_x = 'xxxxxx'; // enter the password that you put when you generated the certificate.

Test it by updating the test user’s status and you should see that it has made a web service callout with two-way authentication.

Public CA Signed Certificates

The biggest advantage of getting the certificate signed by public CA is that you there is no need to import the certificate in the target server, as in the case of self-signed certificates, as the web/application server(s) trust the certificates signed by public CA’s. This will really helpful where the user doesn’t have control or a way to import the self-signed certificates into the target server’s Trust/Key Store.

In this scenario, we will see how to get the certificate signed by public CA using CSR generated from Open SSL.

Step # 1: Creating the CSR for client

To create the CSR, you can follow the same steps as described in the step # 2 of the previous section.

Step # 2: Get the certificate signed from public CA

Submit the CSR to your preferred public CA (should be supported by Salesforce) and get it signed.

Step # 3: Update the code to embed the certificate in the web service callout

Follow the same steps as described in the step # 5 of the previous section to update the wrapper class in Salesforce to include the certificate when making the web service callout.

Test it by updating the user’s status and you should see that it has made a web service callout with two-way authentication. And as described above, you don’t need to import the certificate into IBM WebSphere Cast Iron runtime appliance as the server can accept the certificate passed by the salesforce since it is signed by public CA.

Certificate generated from Salesforce

Salesforce provides the option to generate the Certificate from its platform and this is the suggested method by Salesforce. The biggest advantage is that the private key is not shared outside of the Salesforce and the caveat is that you will not be able to use this certificate from any other system, other than the Salesforce, since you cannot get the private key when you download the certificate from Salesforce. This section will also cover both the scenarios; self-signed certificates and certificate signed by public CA, but this time the Certificate is generated from the Salesforce.

Self-Signed Certificates

Step # 1: Creating self-signed certificate the CSR for client

To generate the certificate from Salesforce, login into your Salesforce organization and click ‘Create Self-Signed Certificate’ under Setup->Security Controls (under Administration Setup)->Certificate and Key Management. Enter the information as below.

A1-P4-SF-01-GeneratedSelfSignedCSR

Figure 4e. Create self-signed certificate from Salesforce.

Click ‘Save’ and it should show you the screen as below.

A1-P4-SF-01-GenerateSelfSignedCSR

Figure 4f. Self-signed certificate generated in Salesforce.

Step # 2: Update the code to reference the certificate in the web service callout

Since the certificate is now residing within Salesforce, we don’t need to embed the certificate in the web service callout; instead, we can just reference the certificate name in the code and Salesforce runtime automatically embeds the certificate in the callout. Update the UserStatusClient file on the Salesforce side by clicking ‘Edit’ against ‘UserStatusClient’ under Setup->Develop->Apex Classes

updateStatusInstance.clientCertName_x = 'Contoso_SF';
updateStatusInstance.clientCertPasswd_x = 'test';

Public CA Signed Certificates

Step # 1: Creating the CSR for client

To get the certificate signed by public CA that is generated from Salesforce, click ‘Create CA-Signed Certificate’ under Setup->Security Controls-> (under Administration Setup)->Certificate and Key Management. Enter the information as below.

A1-P4-SF-01-GenerateCSR-PublicCA

Figure 4g. Create CSR from Salesforce.

Click ‘Save’.

Step # 2: Get the certificate signed from public CA and Upload to Salesforce

Download the CSR by clicking ‘Download Certificate Signing Request’ button and submit this CSR to your preferred public CA and get it signed. Once you receive the signed certificate, upload it by clicking ‘Upload Signed Certificate’ button.

Step # 3: Update the code to reference the certificate in the web service callout

This is similar as described in the previous section; i.e., since the certificate is residing within Salesforce, we don’t need to embed the certificate in the web service callout; instead, we can just reference the certificate name in the code and Salesforce runtime automatically embeds the certificate in the callout. Update the UserStatusClient file on the Salesforce side by clicking ‘Edit’ against ‘UserStatusClient’ under Setup->Develop->Apex Classes

updateStatusInstance.clientCertName_x = 'Contoso_SF_PCA';
updateStatusInstance.clientCertPasswd_x = 'test';

Summary

In this article, we saw how to make two-way authenticated calls using SSL/certificates including some of the fundamentals about the certificates and how they work. In Part-5, which is also the final piece of this article series, we will see some common issues and how to fix them.

Tagged: , , , , , ,

41 thoughts on “Making authenticated web service callouts from Salesforce to IBM Cast Iron using SSL/certificates–Part IV

  1. Shail July 19, 2012 at 8:06 pm Reply

    Thanks Hari, It was a very well written & detailed articles. Really very useful. Just wanted to quickly check with you on one point though.
    Salesforce.com offers to generate certificate for outbound messages from Setup>Develop>API>Generate Client Certificate. If we generate it from here it does not ask for any details(Like it asks when you generate from Setup>Security Controls>Certificate & Key Management which you have highlighted in your article) and offer to download a certificate. Is this certificate different from what we generate from Security Controls ? Is it a generic certificate which is not specific to any org & in that case is it advisable to use this certification for 2 way SSL.
    Can I use certificate generated from Security Controls in my outbound messages ? Your help is greatly appreciated

    • Hari Krishnan July 20, 2012 at 7:07 pm Reply

      Hi Shail,
      The certificate that you generate from Setup->Develop->API->Generate Client Certificate is used when you want 2-way SSL authentication on the Salesforce side, so that your client which is calling the web service hosted in Salesforce can authenticate itself. The certificate that you generate from Setup->Security Controls->… is a server certificate that your web service in Salesforce uses it to provide identity to its clients.

      I believe the client certificate should be specific to an org, as otherwise, anybody who has the possession of the certificate can call the web service, which is a huge security risk. The outbound messages will automatically use the client certificate if you register with Salesforce (In Apex, you have two options: you can either embed the certificate details or chose to use the name of the certificate that you register in the settings section. But with outbound messaging, you cannot embed the certificate details, as there’s no way to hook your code).

      • Vasu Pulipati July 24, 2015 at 2:26 am Reply

        Hi Hari,
        The certificate you create from Setup-> Secuirty Controls-> Certificate & Key Management is what you send with your request to external service so that the external service can authenticate to ensure that the request is coming from Salesforce. Isn’t that right?
        Isn’t outbound message just like a callout (calling an external service from Salesforce)? What’s confusing is Salesforce uses client certificate (from Setup-> Develop-> API-> Generate Client certificate) for outbound messages, and for callouts it uses the one created from Certificate & Key management. Do you know why?

        The issue with client certificate is that it needs to be imported into external service (where the service is hosted) and it’s hard to explain to customers why it is that way. The one created from Certificate & Key management doesn’t need to be imported if it’s signed by trusted CA.

        • Vatsala July 28, 2015 at 9:27 pm Reply

          Hi Hari – Thanks for the detailed explanation. I refer this article everytime I implement security. Can you please clarify the following?

          Does Outbound Messaging support token based authentication? If yes how can we cache the token?

  2. jinesh August 21, 2012 at 3:39 pm Reply

    Hi Hari,

    We are displaying web application in an Iframe and passing parameters to it.Now the problem is anybody who sees these parameters through view source or some other tools will be able to see and use it.

    So we thought the solution is using salesforce client certificate.However,we are not using web services. So how do we do with the rest based link displayed in an IFrame.
    Thanks,
    Jinesh

    • Karlheinz August 26, 2014 at 9:35 pm Reply

      I know the question is kind of old, but I am currently facing the same challenge. So Jinesh, maybe you already received an answer, or somebody can shed some light here? Scenario is using generating a URL with parameters in SF to call an external web application (mashup or new browser window). To validate that the request is coming from SF and not a random source which copied the URL, we want to use a client certificate. Is this possible, and what does the called application need to support?

  3. Arul October 12, 2012 at 8:45 am Reply

    Hi Hari,

    We are trying to display images in a VF page from a Sharepoint Server. Will this method work ? And if it does

    a. If it just try to access the image via “https://servername.com/path/image.jpg” will the certificate be passed along with the request or how do i exlicitly pass the certificate as part of the request .

    Thanks,

    • Hari Krishnan October 12, 2012 at 4:25 pm Reply

      If you want to use plain HTML with no scripting, then you can display images from any links, provided, the images are accessible without any authentication. If you secure your sharepoint with windows authentication, then I guess you need to program in Apex to authenticate, but I’m not sure how it’s going to work, as I have never tried it. Regarding the certificate question, you do not need to send any certificate, if it is one-way SSL authentication. You need to provide your certificate only in the case of two-way SSL authentication.

  4. rotnelson October 31, 2012 at 7:18 am Reply

    Hi,
    Thanks for a great and detailed article!
    Just want to make sure I have now understood everything.

    When you create a self signed certificate as explained in “Self-Signed Certificates
    Step # 1” from within Salesforce. Will you not be required to import this certificate in Cast Iron’s key store to get two way SSL?

    • Hari Krishnan November 1, 2012 at 5:44 pm Reply

      Yes, that’s right. And I have described that in Step # 4.

      • Charles August 6, 2013 at 4:27 pm Reply

        Do you not have to import a ‘Root Certificate’ from SF as well? I wish you had gone more into this process in the article.

  5. […] Making authenticated web service callouts from Salesforce to IBM Cast Iron using SSL/certificates–…. […]

  6. rkbatthula January 16, 2013 at 6:26 pm Reply

    Hi Hari,Thanks for the detailed article. This really helps a lot. Will you please provide more information on Legacy Method i.e Certificate generated from non-Salesforce? I am more interested to learn the way we use the certificate in salesforce.

    • Hari Krishnan January 17, 2013 at 2:47 am Reply

      In the legacy method, as referenced by Salesforce, you generate a certificate from Windows Active Directory or some other tool like OpenSSL and you sign the certificate by using your own CA. Once again you can use either Windows Active Directory Certificate Services or OpenSSL. I have covered this in detail in this article. This should work as we have implemented this successfully.

  7. Babu Mannem September 12, 2013 at 4:43 pm Reply

    Hari,

    This is a great article with tonnes of useful info. Right now we are planning to integrate with our corporate enterprise web services with salesforce and planning to use mutual ssl (two way). In Salesforce we have 6 data centers and 150 servers with different IP addresses and also don’t have load balance server with single point to connect. In this scenario we need 150 certificates to install or we can use one certificate on both salesforce and our corporate load balance servers.

    Thanks in advance for your suggestions

    Thanks
    Babu

    • Hari Krishnan September 12, 2013 at 11:24 pm Reply

      Babu,
      Certificates can be issued and signed based on either domain names or IP addresses. If you buy a wild card certificates based on the domain names, then one certificate is enough as far as all the 150 IP addresses are sub domains of the main domain. For e.g. if you get a wild card certificate for ‘*.walgreens.com’, then this same ceriticate is valid for ‘dev1.walgreens.com’, ‘dev2.walgreens.com’, ‘qa1.walgreens.com’, ‘rx.dev.walgreens.com’, etc. You can use the ‘Subject Alternative Names’ to register your domain if it is different, for e.g. ‘dev.walgreens.org’ (note the ‘org’ instead of ‘com’), but I think this may not work if you do not have domain names and go with only IP addresses. I suggest to check with your certificate issuer to see you can get one single certificate for all your servers if it has only IP addresses and no domain names.

      Regards,
      Hari K.

  8. Babu Mannem September 13, 2013 at 3:25 pm Reply

    Thanks Hari for quick and detailed response.

  9. Prasad October 18, 2013 at 6:38 pm Reply

    Hello Hari
    this is a wonderful article. Please shed some light on our issue here. Our use case is:
    1. we fire an outbound from salesforce when a case is closed.
    2. Once we receive the call on our websphere app, we try to connect to salesforce to download more information, and attachments.
    So , the first part works fine. however we are running into ssl issues while connecting to salesforce [https] from websphere. Here is the error:

    [10/18/13 12:04:33:807 MDT] 00000052 SystemErr R Caused by: java.security.cert.CertPathBuilderException: PKIXCertPathBuilderImpl could not build a valid CertPath.; internal cause is:
    java.security.cert.CertPathValidatorException: The certificate issued by OU=Class 3 Public Primary Certification Authority, O=”VeriSign, Inc.”, C=US is not trusted; internal cause is:
    java.security.cert.CertPathValidatorException: Certificate chaining error

    Please advise. Thanks again
    Prasad

    • Hari Krishnan October 27, 2013 at 9:54 pm Reply

      Hi Prasad,
      To me, the error message looks like it originates from your trust store and I guess your certificate chain is not completely signed and trusted. You may have to check with your certificate provider or use one of the tools to troubleshoot it. You can check using digicert.com/help or the open ssl tool.

      Regards,
      Hari K.

      • PRASAD EADARA October 28, 2013 at 2:43 am Reply

        Thank you Hari. wer resolved the issue now. looks like we have to download verisign root certificate chain into WebSphere. thank you

        Thank you Prasad 810-373-2224

  10. narendhar January 15, 2014 at 5:20 pm Reply

    Hi Hari
    Thanks for explaining in details, we have requirement to call the external web service call whenever an opportunity is created in salesforce,we are planning to use two way SSLt\CA signed certificated authentication,shall we need to upload the CA signed certificate in salesforce and external web application repository.correct me if i am wrong.
    Thanks in advance.

    • Hari Krishnan January 16, 2014 at 1:07 am Reply

      Yes, you need to upload certificates on both side. On Salesforce side, you have the option of using certificate directly in your apex code as well. On your web application repository, you need to upload all the intermediary certificates along the root certificate.

  11. ravi March 18, 2014 at 6:37 pm Reply

    Hi Hari.. thanks for wonderful write up, saved lot of time…We are implementing SFDC – Oracle Fusion 2 way SSL…please correct me if i’am wrong in following assumptions..

    1. SFDC – Oracle Fusion : We are sending accounts using SFDC call out
    We received verisigned siigned certificate from Oracle Fusion team, but we did not received password for variable “clientCertPasswd_x “… is this something they should provide?..if so should i ask them to send password used while generating CSR or Password used when put signed certificate in keystore?.. i’am not clear about..if you could answer this, that will be great…

    2. Say When we downloaded Saesforce CA signed certificate and got verisigned signed,, i can upload signed certicate to SFDC and assign certificate name to “clientCert_x”…. But what should I pass for variable “clientCertPasswd_x ” ?

    3. Oracle Fusion to SFDC sERVICE: (Fusion calls Custom SFDC webservice)
    In this case should I provide another signed certificate to Oracle Fusion team or, can we use same certicate we obtained in STEP 2 above…?.. Because in salesforce there is no option to IMPORT Oracle Fusion certicates and store in keystore like… can you Please clarify if iam missing something here…

    thanks much again..

    Ravi C

    • Hari Krishnan March 19, 2014 at 5:37 pm Reply

      1. In one-way SSL, you don’t need the password or the certificate to be embedded in your call. It’s just a plain HTTPS callout – depending on the authentication set up in Oracle Fusion, you may need to embed the user name and password in your callout. For e.g. if Oracle fusion uses basic authentication, then you would set the header ‘Authorization’ with base64 encoded value of user name and password. You need to embed the certificate and password, only if you need two-way SSL. You need to speak with your teams to determine if it is one-way or two-way SSL.
      2. I’m not sure if I understand your question.
      3. Once again, if you use one-way SSL, then Oracle Fusion doesn’t need to embed any certificates/certificate password in the callout. If you do use two-way SSL, then you can generate the certificate in Salesorce and use that on the Oracle Fusion callout.

      • ravi March 19, 2014 at 6:22 pm Reply

        Hi Hari..thanks for reply,

        for your response:

        1. we are doing two way SSL .. question was should i request oracle fusion team to send me password to assign it to “clientCertPasswd_x” variable in SFDC call out header..

        2. Say if we proceed with SFDC generated CA signed approach… i will have certificate name (verisigned and uploaded to SFDC).., but what will be password that i should assign to “clientCertPasswd_x” variable in SFDC call out header..

        3. we are using 2 way SSL.. Here Oracle Fusion initiates call..

        thanks for your time..

        Ravi C

  12. ravi March 19, 2014 at 6:37 pm Reply

    In
    ” Step # 3: Update the code to reference the certificate in the web service callout” in above article… we have the certicate name to assign in header variable …. but from where will i get the password?

    //////- i have this certicate loaded to SFDC, so i’am able to make this step
    updateStatusInstance.clientCertName_x = ‘Contoso_SF_PCA’; –/

    /// Not sure from where does this password come from…we got only certificate from verisigned..
    updateStatusInstance.clientCertPasswd_x = ‘test’;

    thanks
    Ravi C

  13. Nitin Jain July 11, 2014 at 10:22 am Reply

    First of all Thanks a lot for these valuable articles.

    I am having a same scenaio of TWO way SSL, for which I am done these things so far, still getting error like:

    System.CalloutException: IO Exception: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    As of now we had created a CA cert, which we had put in keystore in WMC and given the alias name in the CI webservice endpoint in orchestration. In Salesforce we have created a self signed certificate and we have given the reference in the APEX class.

    In this scenario, do we need to put the certificate in CastIron truststore, which is created in Salesforce (self-sighed)?

    Please reply asap

  14. Guna October 1, 2014 at 5:47 am Reply

    Thank you Hari. you have explained such a confusing topic with simple words and in amzing detail. Wonderful article.

  15. Jason January 21, 2015 at 6:43 pm Reply

    Someone on the SFDC forums pointed me to your article. There’s a lot of good information here but I’m having trouble applying it our problem regarding Outbound Messages. Do you know if Outbound Messages require you to import a purchased certificate (from GoDaddy in our case) in to the SFDC “Certificate and Key Management” page?

    Here is my thread which shows the specific error/exception we are getting.
    javax.net.ssl.SSLPeerUnverifiedException

    https://developer.salesforce.com/forums/ForumsMain?id=906F0000000Au7Z

  16. Max February 16, 2015 at 11:56 am Reply

    Hello, Hari. Thanks for the useful article.
    I have a question about making callouts to servers that have untrusted certificates.
    You say:
    “As explained in the Part-3, Salesforce will accept only certificates signed by public CA, when it acts as a client and makes a callout to the server. On the contrary, you can use either self-signed certificates…”. Does this mean that the server may not have certificate signed by a public CA? Or the server still MUST have one?

    So I have a client certificate from my third party service. I’ve successfully imported it into SF’s. But when I make a callout I get the following error:

    sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

    I suppose that this happens because of server certificate that is not signed by a public CA. Am I right?

    I mean no matter two-way or one-way auth is used, server that is requested by SF via https MUST have a certificate signed by a public trusted CA. Right?

    Thanks.

    • Hari Krishnan February 25, 2015 at 6:06 am Reply

      Max,
      Yes, that’s right. A server should always have a certificate, preferably signed by public CA, because ideally external systems will not accept self-signed certificates. Self-signed certificates are better used within organizations.

  17. Shashi April 16, 2015 at 3:47 pm Reply

    Hi Hari,
    Really really good information here. I have a question, I’m using client certificate generated from API menu. I have given that certificate to Tomcat servers to configure so that when i make REST call, i can use that certificate to authenticate. However, when i want to wrap that certificate in my code in apex, i don’t know how to give a name to this certificate? i mean i can use the whole certificate in the request but how to give this certificate a name and wrap in my request ? I don’t see any place to do it. Also i have see your response that we can name in settings. Please advise. Your help is greatly appreciated.

    thanks

  18. Srini July 6, 2015 at 2:16 pm Reply

    Hi Hari,

    Thanks for the detailed article. This helps lot understanding implementation of certificates.

    My requirement is around WS security.I have to integrate to a third party SOAP based WSDL from Salesforce with signed request. How this can be achieved? My third party system team says, they are receiving the request but not signed. I have implemented as follows:
    – Generated Apex classes using WSDL2Apex from the WSDl provided by third party company.
    – Generated a self signed certificate from Salesforce and passed to third party company to store that in their key store.
    – Passed that certificate name in the webservice request like how we normally configure in Salesforce.

    Salesforce support says WS secutiry is not supported with Salesforce currently. Is there any work around for this?

    Your help will be highly appreciated.

    Thanks,
    Srini

    • Hari Krishnan July 10, 2015 at 8:13 pm Reply

      Hello Srini,
      As you said, Salesforce doesn’t support WS Security. So, here are your options, that I can think of:
      1. Modify the SOAP header to include the security info. This link will give you more details (http://salesforce.stackexchange.com/questions/7587/forming-soap-header-through-apex-class-if-the-wsdl-provided-has-no-information-r)..
      2. Check with your third party company, if they support SSL/Certificate instead of WS Security and use that.
      3. Host a web services either in your on-prem server or in cloud (Heroku/AWS/…) and build a web service proxy which you can call from SF and this proxy can do a WS security with the third party service.

      Obviously, the first option would be your best bet, in my opinion.

      Regards,
      Hari Krishnan.

  19. Srini July 13, 2015 at 10:59 am Reply

    Hi Hari,

    Thanks for your reply.

    I am working on option-1 but meantime, i want to explore option-2 incase, i am not successful with option-1. Can you advise me How to accomplish the integration with SSL/Certificate instead of WS Security? How do i explain in more technical terms to my third party on what changes they have to do in-order to work on option-2.

    Option-3 seems bit expensive and involves bit of procedure but will explore where required.

    Thanks for the options described and appreciate your help.

    Thanks,
    Srini

  20. Hari Krishnan July 14, 2015 at 6:03 am Reply

    If you need to use option #2, then you need to ask your third party vendor first if they support SSL/Certificate based authentication. If they do support, then they need to get a certificate signed by public CA and send that to you (PEM format). If you generate the CSR from Salesforce, then all you need to do is to update your apex code to include the certificate name and the password. On the other hand, if your third party vendor generates their own CSR (most likely this will be the case), then you need to update your apex code to include the certificate (PEM) and the password. Your third party vendor may require to install the intermediate certificates into their key store, but they should be able to take care of this, if they support it. Please follow this article series to understand the rest of the steps.

  21. Gunaranjan October 1, 2015 at 8:10 am Reply

    Hi Hari,

    We are trying to call a Web service from other application (SSL enabled).After setting up in Remote Site, when tested using developer console. we faced error – “System.CalloutException: Web service callout failed: Unexpected element. Parser was expecting element ‘http://schemas.xmlsoap.org/soap/envelope/:Envelope’ but found ‘:html’ “. We are not sure where the problem is. Do we need to install SSL certificate of that application into Salesforce KeyStore. Other application Web Service is working fine as it is being called out from a different web application, there is no way, the provider has issue. Could you please advice. Thank You in advance.

  22. vgcloudblog March 1, 2016 at 5:57 pm Reply

    Hi Hari,

    Thanks for the right up. I had to implement 2-Way SSL authentication for salesforce-Onpremise system integration. I have followed below steps to configure that

    1.Download CA signed certificate request from certificate & Key Management in salesforce
    2.Gave the .csr file to the CA to get it signed
    3.Got the Signed certificate in .p7b format imported into salesforce
    4.This activated the certificate in salesforce.

    Now do i need to download the signed certificate from salesforce and provide it to Web service team so that they can add it to their trust store?

    and also now the webservices are available only within client network and not from salesforce so to mimic the connection
    1.i have exported the all the certificates from salesforce in .jks format and converted it to .p12 format.
    2.Imported the certificate into browser(chrome and IE) and try to hit the service but it is now working and throwing ssl error.

    is it because that i havent provided the signed certificate from salesforce to the webservice team to add it to trust keystore?

    Any help would be appreciated!!

    Thanks,
    Vishnu

  23. Jitendra Kawale May 2, 2016 at 7:25 am Reply

    Hi Hari,

    I am trying to connect two salesforce Instances using JWT. while generating JWT I have created self signed certificate in my provider org, but I am not able to use this certificate in consumer org.

    Below is the code I am using to generate JWT token in consumer org, but I am not sure how to use certificate here.

    JWT class

    r(String alg) {
    this.alg = alg;
    }
    }

    private class Body {
    String iss;
    String sub;
    String aud;
    String exp;
    Body(String iss, String sub, String aud, String exp) {
    this.iss = iss;
    this.sub = sub;
    this.aud = aud;
    this.exp = exp;
    }
    }

    private class JwtException extends Exception {
    }

    private Configuration config;

    public Jwt(Configuration config) {

    this.config = config;
    }

    public String requestAccessToken() {

    Map m = new Map();
    m.put(‘grant_type’, ‘urn:ietf:params:oauth:grant-type:jwt-bearer’);
    system.debug(‘createToken==>’+createToken());
    m.put(‘assertion’, createToken());
    m.put(‘assertion_type’, ‘urn:oasis:names:tc:SAML:2.0:profiles:SSO:browser’);
    m.put(‘client_secret’,’91830275823838914′);
    m.put(‘format’, ‘json’);

    HttpRequest req = new HttpRequest();
    req.setHeader(‘Content-Type’,’application/x-www-form-urlencoded’);
    req.setEndpoint(‘https://’ + config.jwtHostname +’/services/oauth2/token’);
    req.setMethod(‘POST’);
    req.setTimeout(60 * 1000);
    SYSTEM.DEBUG(‘formEncode==>’+formEncode(m));
    req.setBody(formEncode(m));
    system.debug(‘req==>’+req);

    HttpResponse res = new Http().send(req);
    system.debug(‘res ==>’+res.getbody());
    if (res.getStatusCode() >= 200 && res.getStatusCode() < 300) {
    return extractJsonField(res.getBody(), 'access_token');
    } else {
    throw new JwtException(res.getBody());
    }
    }

    private String formEncode(Map m) {

    String s = ”;
    for (String key : m.keySet()) {
    if (s.length() > 0) {
    s += ‘&’;
    }
    s += key + ‘=’ + EncodingUtil.urlEncode(m.get(key), ‘UTF-8’);
    }
    return s;
    }

    private String extractJsonField(String body, String field) {

    JSONParser parser = JSON.createParser(body);
    while (parser.nextToken() != null) {
    if (parser.getCurrentToken() == JSONToken.FIELD_NAME
    && parser.getText() == field) {
    parser.nextToken();
    return parser.getText();
    }
    }
    throw new JwtException(field + ‘ not found in response ‘ + body);
    }

    private String createToken() {

    String alg = ‘RS256’;

    String iss = ‘3MVG9ZL0ppGP5UrBhQ7kJ65NCCt.qeZDWy9brMjm2h4_8VnD47EeFimxMzRJKjD8j5ByFs3mbqe_Cil2q53go’;//config.jwtConnectedAppConsumerKey;
    String sub = ‘jituepractice@org.com’;//config.jwtUsername;
    String aud = ‘https://’ + config.jwtHostname;
    String exp = String.valueOf(System.currentTimeMillis() + 60 * 60 * 1000);

    String headerJson = JSON.serialize(new Header(alg));
    String bodyJson = JSON.serialize(new Body(iss, sub, aud, exp));
    system.debug(‘bodyJson==>’+bodyJson);
    String token = base64UrlSafe(Blob.valueOf(headerJson))
    + ‘.’ + base64UrlSafe(Blob.valueOf(bodyJson));
    String signature = base64UrlSafe(Crypto.signWithCertificate(
    ‘RSA-SHA256’,
    Blob.valueOf(token),
    config.jwtSigningCertificateName
    ));
    token += ‘.’ + signature;
    system.debug(‘signature==>’+signature);
    return token;
    }

    private String base64UrlSafe(Blob b) {

    return EncodingUtil.base64Encode(b).replace(‘+’, ‘-‘).replace(‘/’, ‘_’);
    }
    }

    ********************
    test code
    Jwt.Configuration config = new Jwt.Configuration();
    config.jwtUsername = ‘myorg@org.com’;
    config.jwtSigningCertificateName = ‘JWT_certificate’;
    config.jwtHostname = ‘login.salesforce.com’;
    config.jwtConnectedAppConsumerKey = ‘3MV9ZL0ppGP5UrBhQ7kJ65NCCt.qeZWy9brMjm2h4_8VnD47EeFimxMzRJKjD8j5ByFs3mbqe_Cil2q53go’;

    String accessToken = new Jwt(config).requestAccessToken();
    system.debug(‘accessToken==>’+accessToken);

    Please help me if you have any Idea how to use certificate in client org.

  24. Olek January 26, 2017 at 1:08 pm Reply

    Basically i have simple two questions :
    1. If i use clientCertName_x in my callout i would have to make a reference to the Unique Name of the CA signed certificate uploaded into salesforce. CA has to be Salesforce recognized?
    2. If i use clientCert_x and clientCertPasswd_x i need to add a base64 of the .p12 file . Does this p12 also have to be signed by a Salesforce recognized CA ?

  25. Sarfraz Ahmed March 14, 2017 at 9:54 pm Reply

    Hi Hari,

    Thanks for the article.
    I am new to the cast Iron and need your help in the below scenario.

    We have a webservice which get called from out side the network by the vendor and currently it is getting authenticate using userid and password. Now the requirement is to validate the vendor by certificate instead of basic userid and password. we have multiple vendor using the same environment with different orchestration.
    Need your help to achieve the scenario. Pls let me know the steps for the setup.

    Appreciate your help.

    Thanks,
    Sarfraz

Leave a reply to Hari Krishnan Cancel reply