DEV Community

Avi Dalal
Avi Dalal

Posted on • Edited on

Safeguarding Third-Party Integrations: Secure HTTP Calls in AEM as a Cloud

Introduction:
In today's digital landscape, integrating with third-party systems is crucial for delivering seamless and personalized experiences. However, ensuring the security of these integrations is paramount. In this blog post, we will explore a robust solution that allows Adobe Experience Manager (AEM) as a Cloud users to make secure third-party HTTP calls using certificates, safeguarding sensitive data and maintaining the integrity of their AEM deployments.

Section 1: The Challenge of Secure Third-Party Integrations
Integrating third-party systems into AEM as a Cloud brings numerous benefits, but it also introduces security concerns. Unsecured HTTP calls can expose sensitive data and compromise the integrity of the entire system. Therefore, a comprehensive security mechanism is crucial to protect against potential vulnerabilities.

Section 2: Introducing the Solution: Creating Service Users and Keystores
To establish secure integrations, we need to start by creating a service user in AEM as a Cloud. The service user acts as a bridge between AEM and the third-party API. Follow these steps to create the service user:

  • Create the file in the following directory structure:

path:
../ui.config/src/main/content/jcr_root/apps/[your-project-name]/osgiconfig/config

  • Name the file with the following convention:

org.apache.sling.jcr.repoinit.RepositoryInitializer~[generic-name].cfg.json

  • Open the file and add the necessary configurations. For example, you can include the OSGi configuration JSON object that we discussed earlier:
{
    "scripts": [
        "create path (sling:OrderedFolder) /content/dam/[folder-name]",
        "create path (nt:unstructured) /content/dam/[folder-name]/jcr:content",
        "set properties on /content/dam/[folder-name]/jcr:content\n  set cq:conf{String} to /conf/[folder-name]\n  set jcr:title{String} to \"[folder-name]\"\nend",
        "create service user [your-service-user-name]\n set ACL for [your-service-user-name]\n allow jcr:read on /content \nend"
    ]
}

Enter fullscreen mode Exit fullscreen mode

In the above code, replace [folder-name] with a generic folder name and [your-service-user-name] with a generic service user name.

  • add config file to map the user service

user.mapping=["[project-name].core:[your-service-user-name]\=[[your-service-user-name]]"]

name the file somthing like that:

org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended-[project-name-service-user-name].config

Section 3: Storing Certificates in Keystores
Once the service user is created, we need to store the certificates in keystores within AEM as a Cloud. To accomplish this, follow these steps:

  • Extract the necessary information, list the aliases in a PFX keystore, it will prompt for the keystore password. Run the following command in a command prompt or terminal:
keytool -v -list -keystore certificatename.pfx
Enter fullscreen mode Exit fullscreen mode

Replace certificatename.pfx with the actual filename of your PFX file. Enter the password for the PFX file when prompted.

  • You can access the trust store by going to Tools -> Security -> Users

Image description

the complete guide of uploading the pfx : here

  • create a class to get the keystore
package [your-project-name].core.utils;

import java.io.IOException;
import java.security.KeyPair;
import java.security.KeyStore;

import javax.security.auth.login.LoginException;

import org.apache.sling.api.SlingIOException;
import org.apache.sling.api.resource.ResourceResolver;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;

import com.adobe.granite.keystore.KeyStoreNotInitialisedException;
import com.adobe.granite.keystore.KeyStoreService;

@Component(service = PrivateKeyCertificate.class)
public class PrivateKeyCertificate {

    @Reference
    private KeyStoreService keyStoreService;

    public KeyStore getKeyStore(ResourceResolver resourceResolver) throws SlingIOException, SecurityException, KeyStoreNotInitialisedException, LoginException, org.apache.sling.api.resource.LoginException, IOException {
        KeyStore keyStore = keyStoreService.getKeyStore(null, "[service-user-name]");
        return keyStore;
    }
}

Enter fullscreen mode Exit fullscreen mode
  • With the extracted alias and password, use the following code snippet to generate the SSL socket factory:
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.KeyManagementException;
import java.security.UnrecoverableKeyException;

public class SSLFactoryUtil {

    public static SSLSocketFactory setKeyStoreSSLFactories(KeyStore keyStore, String keystoreType, char[] keyStorePassword) throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, UnrecoverableKeyException {

        KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());

        keyFactory.init(keyStore, keyStorePassword);

        KeyManager[] keyManagers = keyFactory.getKeyManagers();

        SSLContext sslContext = SSLContext.getInstance("SSL");

        sslContext.init(keyManagers, null, null);
        SSLContext.setDefault(sslContext);

        return sslContext.getSocketFactory();
    }
}

Enter fullscreen mode Exit fullscreen mode

Replace [your-project-name] with the appropriate name for your project or module. Customize the code according to your specific requirements.

Section 4: Applying Secure HTTP Calls in AEM as a Cloud
Now that we have the necessary components, let's utilize them to establish secure HTTP calls in AEM as a Cloud. Use the following code snippet as an example:

import [your-project-name].core.utils.PrivateKeyCertificate;
import javax.inject.Inject;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.HttpsURLConnection;
import java.io.InputStream;
import java.net.URL;

public class YourServlet {

    @Inject
    PrivateKeyCertificate privateKeyCertificate;

    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) {
        try {
            ResourceResolver resourceResolver = request.getResourceResolver();
            KeyStore keyStore = privateKeyCertificate.getKeyStore(resourceResolver);
            char[] keyStorePassword = "your_keystore_password".toCharArray(); // Replace with your keystore password
            SSLSocketFactory sslSocketFactory = SSLFactoryUtil.setKeyStoreSSLFactories(keyStore, "JKS", keyStorePassword);

            // URL of the target resource
            URL targetUrl = new URL("https://www.example.com");

            // Open HTTPS connection
            HttpsURLConnection connection = (HttpsURLConnection) targetUrl.openConnection();
            connection.setSSLSocketFactory(sslSocketFactory);

            try (InputStream is = connection.getInputStream()) {
                // Process the input stream
            }

            // Rest of your servlet code...
        } catch (Exception e) {
            // Handle exception
        }
    }
}

Enter fullscreen mode Exit fullscreen mode

Customize the code to fit your specific requirements, including the project name, keystore password, target URL, and processing of the input stream.

Conclusion: Advancing Integrations with Enhanced Security
In this blog post, we explored a comprehensive solution for making secure third-party HTTP calls from AEM as a Cloud using certificates. By following the step-by-step instructions, AEM users can strengthen the security of their integrations, protecting sensitive data and maintaining the trust of their users. Secure integrations are vital in today's digital landscape, and by implementing this solution, organizations can confidently connect with third-party systems while ensuring data confidentiality and integrity.

We hope this blog post equips you with the knowledge and tools to secure your AEM as a Cloud integrations. If you have any questions or would like to share your experiences, feel free to leave a comment below. Secure integrations await!

Top comments (0)