PingFederate Adapter Development involves creating custom modules to extend the authentication capabilities of PingFederate for specific use cases. Whether you need to integrate with a legacy system or support a unique authentication flow, building custom adapters allows you to tailor PingFederate to your organization’s needs.

What is PingFederate Adapter Development?

PingFederate Adapter Development is the process of creating custom authentication and identity resolution modules that extend PingFederate’s functionality. By developing these modules, you can integrate with various systems and protocols, handle specific authentication requirements, and ensure seamless user experiences.

Why develop custom authentication modules?

Developing custom authentication modules is crucial when you need to address specific business requirements that aren’t met by out-of-the-box PingFederate features. This could include integrating with proprietary systems, implementing unique authentication workflows, or supporting specific protocols not natively supported by PingFederate.

How do I start developing custom authentication modules?

To start developing custom authentication modules, you need to set up your development environment and familiarize yourself with PingFederate’s documentation and SDK.

Setting up the development environment

  1. Install JDK: Ensure you have the correct version of the Java Development Kit (JDK) installed. PingFederate typically requires JDK 8 or later.
  2. Download PingFederate SDK: Obtain the PingFederate SDK from the official Ping Identity website or your PingFederate installation directory.
  3. Set up an IDE: Use an Integrated Development Environment (IDE) like IntelliJ IDEA, Eclipse, or NetBeans for coding.

Familiarize with PingFederate SDK

The PingFederate SDK provides the necessary tools and documentation to develop custom adapters. Key components include:

  • API Documentation: Detailed documentation on PingFederate APIs and classes.
  • Sample Code: Example code to help you get started.
  • Development Tools: Utilities for testing and debugging your adapters.

Extending PingFederate’s Java Classes

Custom authentication modules are built by extending PingFederate’s Java classes. The primary classes you’ll work with are:

  • AuthenticationAdapterV2: For creating authentication adapters.
  • IdentityResolutionAdapterV2: For creating identity resolution adapters.

Implementing AuthenticationAdapterV2

Here’s a basic example of implementing AuthenticationAdapterV2:

package com.example.pingfederate.adapters;

import org.sourceid.saml20.adapter.attribute.AttributeValue;
import org.sourceid.saml20.adapter.conf.Configuration;
import org.sourceid.saml20.adapter.gui.AdapterConfigurationGuiDescriptor;
import org.sourceid.saml20.adapter.gui.TextFieldDescriptor;
import org.sourceid.saml20.adapter.idp.authn.AuthnAdapterResponse;
import org.sourceid.saml20.adapter.idp.authn.AuthenticationAdapterV2;
import org.sourceid.saml20.adapter.idp.authn.AuthenticationPolicy;
import org.sourceid.saml20.adapter.idp.authn.SSOAuthnAdapterResponse;
import org.sourceid.saml20.adapter.idp.authn.SSOAuthenticationPolicy;
import org.sourceid.saml20.adapter.idp.authn.web.SSOAuthenticationPolicy.WebForm;
import org.sourceid.saml20.adapter.idp.authn.web.SSOAuthenticationPolicy.WebForm.Field;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

public class CustomAuthAdapter extends AuthenticationAdapterV2 {

    private static final String USERNAME_FIELD = "username";
    private static final String PASSWORD_FIELD = "password";

    @Override
    public String getAdapterId() {
        return "CustomAuthAdapter";
    }

    @Override
    public String getAdapterName() {
        return "Custom Authentication Adapter";
    }

    @Override
    public void init(Configuration config) throws Exception {
        // Initialization logic here
    }

    @Override
    public void destroy() {
        // Cleanup logic here
    }

    @Override
    public AuthenticationPolicy getAuthenticationPolicy(HttpServletRequest request) {
        SSOAuthenticationPolicy policy = new SSOAuthenticationPolicy();
        WebForm form = policy.getWebForm();
        form.addField(new Field(USERNAME_FIELD, "Username"));
        form.addField(new Field(PASSWORD_FIELD, "Password").setMasked(true));
        return policy;
    }

    @Override
    public AuthnAdapterResponse authenticate(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String username = request.getParameter(USERNAME_FIELD);
        String password = request.getParameter(PASSWORD_FIELD);

        // Validate credentials
        if (isValidCredentials(username, password)) {
            Map<String, AttributeValue> attributes = new HashMap<>();
            attributes.put("username", new AttributeValue(username));
            return new SSOAuthnAdapterResponse(attributes);
        } else {
            return new SSOAuthnAdapterResponse(AuthnAdapterResponse.Status.FAILURE, "Invalid credentials");
        }
    }

    private boolean isValidCredentials(String username, String password) {
        // Implement your validation logic here
        return "admin".equals(username) && "password".equals(password);
    }
}

Implementing IdentityResolutionAdapterV2

Here’s a basic example of implementing IdentityResolutionAdapterV2:

package com.example.pingfederate.adapters;

import org.sourceid.saml20.adapter.attribute.AttributeValue;
import org.sourceid.saml20.adapter.conf.Configuration;
import org.sourceid.saml20.adapter.gui.AdapterConfigurationGuiDescriptor;
import org.sourceid.saml20.adapter.gui.TextFieldDescriptor;
import org.sourceid.saml20.adapter.idp.provision.IdentityResolutionAdapterV2;
import org.sourceid.saml20.adapter.idp.provision.IdentityResolutionPolicy;
import org.sourceid.saml20.adapter.idp.provision.IdentityResolutionResponse;
import org.sourceid.saml20.adapter.idp.provision.SSOIdentityResolutionAdapterResponse;
import org.sourceid.saml20.adapter.idp.provision.SSOIdentityResolutionPolicy;
import org.sourceid.saml20.adapter.idp.provision.SSOIdentityResolutionPolicy.WebForm;
import org.sourceid.saml20.adapter.idp.provision.SSOIdentityResolutionPolicy.WebForm.Field;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;

public class CustomIdentityAdapter extends IdentityResolutionAdapterV2 {

    private static final String USERNAME_FIELD = "username";

    @Override
    public String getAdapterId() {
        return "CustomIdentityAdapter";
    }

    @Override
    public String getAdapterName() {
        return "Custom Identity Resolution Adapter";
    }

    @Override
    public void init(Configuration config) throws Exception {
        // Initialization logic here
    }

    @Override
    public void destroy() {
        // Cleanup logic here
    }

    @Override
    public IdentityResolutionPolicy getIdentityResolutionPolicy(HttpServletRequest request) {
        SSOIdentityResolutionPolicy policy = new SSOIdentityResolutionPolicy();
        WebForm form = policy.getWebForm();
        form.addField(new Field(USERNAME_FIELD, "Username"));
        return policy;
    }

    @Override
    public IdentityResolutionResponse resolveIdentity(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String username = request.getParameter(USERNAME_FIELD);

        // Resolve identity
        if (isUserExists(username)) {
            Map<String, AttributeValue> attributes = new HashMap<>();
            attributes.put("username", new AttributeValue(username));
            return new SSOIdentityResolutionAdapterResponse(attributes);
        } else {
            return new SSOIdentityResolutionAdapterResponse(IdentityResolutionResponse.Status.FAILURE, "User not found");
        }
    }

    private boolean isUserExists(String username) {
        // Implement your identity resolution logic here
        return "admin".equals(username);
    }
}

Configuring the custom adapter in PingFederate

After developing your custom adapter, you need to configure it in the PingFederate admin console.

  1. Log in to the Admin Console: Access the PingFederate admin console.
  2. Navigate to Adapters: Go to the “Adapters” section.
  3. Add New Adapter: Click “Add New Adapter” and select your custom adapter.
  4. Configure Settings: Enter any required settings and save the configuration.

Testing the custom adapter

Testing your custom adapter is crucial to ensure it works as expected.

Unit Testing

Write unit tests to verify the functionality of your adapter. Use JUnit for testing Java classes.

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class CustomAuthAdapterTest {

    @Test
    public void testIsValidCredentials() {
        CustomAuthAdapter adapter = new CustomAuthAdapter();
        assertTrue(adapter.isValidCredentials("admin", "password"));
        assertFalse(adapter.isValidCredentials("user", "pass"));
    }
}

Integration Testing

Perform integration testing to ensure your adapter works with PingFederate.

  1. Start PingFederate: Ensure PingFederate is running.
  2. Deploy Adapter: Deploy your adapter JAR file to the PingFederate server.
  3. Test Authentication: Use a tool like Postman or a web browser to test the authentication flow.

Security Considerations

Security is paramount when developing custom authentication modules. Follow these best practices:

Secure Credential Handling

Never store or log credentials in plain text. Use encryption and secure storage mechanisms.

private boolean isValidCredentials(String username, String password) {
    // Encrypt and compare hashed passwords
    String encryptedPassword = encryptPassword(password);
    return "encryptedHashedPassword".equals(encryptedPassword);
}

private String encryptPassword(String password) {
    // Implement encryption logic here
    return "encryptedHashedPassword";
}

Input Validation

Always validate and sanitize all inputs to prevent injection attacks.

private boolean isValidCredentials(String username, String password) {
    if (username == null || password == null || username.isEmpty() || password.isEmpty()) {
        return false;
    }
    // Further validation logic
    return true;
}

Logging

Avoid logging sensitive information. Use logging frameworks that support obfuscation and filtering.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

private static final Logger logger = LoggerFactory.getLogger(CustomAuthAdapter.class);

private boolean isValidCredentials(String username, String password) {
    logger.info("Authenticating user: {}", username);
    // Authentication logic
    return true;
}

Troubleshooting common issues

Error: Class not found

Ensure your adapter JAR file is correctly deployed to the PingFederate server and that all dependencies are included.

Error: Invalid credentials

Check your credential validation logic and ensure that credentials are being handled securely.

Error: Adapter configuration failed

Verify that all required settings are correctly configured in the PingFederate admin console.

Best Practices

Follow these best practices to ensure your custom adapters are robust and maintainable.

Modular Design

Break down your adapter into modular components to improve readability and maintainability.

Version Control

Use version control systems like Git to manage your codebase and track changes.

Documentation

Document your code and provide user guides for configuring and using your adapters.

Continuous Integration

Set up continuous integration pipelines to automate testing and deployment.

Conclusion

Building custom authentication modules for PingFederate allows you to extend its capabilities and meet specific business requirements. By following best practices and thoroughly testing your adapters, you can create secure and reliable solutions.

💜 Pro Tip: Always validate inputs and handle credentials securely to protect against common vulnerabilities.

🎯 Key Takeaways

  • Extend PingFederate's Java classes to create custom authentication and identity resolution modules.
  • Configure and test your adapters in the PingFederate admin console.
  • Follow security best practices to protect sensitive data and prevent vulnerabilities.
ApproachProsConsUse WhenCustom AdapterHigh flexibility, tailored solutionsRequires development expertiseSpecific business requirementsOut-of-the-Box AdapterEasy to set up, minimal developmentLimited customization optionsStandard integration scenarios

📋 Quick Reference

  • extends AuthenticationAdapterV2 - Create authentication adapters.
  • extends IdentityResolutionAdapterV2 - Create identity resolution adapters.
  • init(Configuration config) - Initialize adapter settings.
  • destroy() - Perform cleanup actions.
  • getAuthenticationPolicy(HttpServletRequest request) - Define authentication policy.
  • authenticate(HttpServletRequest request, HttpServletResponse response) - Handle authentication logic.

Set up the development environment

1. Install JDK. 2. Download PingFederate SDK. 3. Set up an IDE.

Familiarize with PingFederate SDK

1. Review API documentation. 2. Study sample code. 3. Use development tools.

Implement custom adapters

1. Extend Java classes. 2. Define policies. 3. Handle authentication logic.

Configure and test adapters

1. Deploy JAR files. 2. Configure in admin console. 3. Test integration.
⚠️ Warning: Always validate inputs and handle credentials securely to protect against common vulnerabilities.
Best Practice: Follow modular design principles to improve code readability and maintainability.
💡 Key Point: Use version control systems like Git to manage your codebase and track changes.
🚨 Security Alert: Avoid logging sensitive information to prevent data leaks.
Terminal
$ mvn clean install [INFO] Building CustomAuthAdapter 1.0-SNAPSHOT [INFO] Installing /path/to/target/CustomAuthAdapter-1.0-SNAPSHOT.jar to /home/user/.m2/repository/com/example/pingfederate/adapters/CustomAuthAdapter/1.0-SNAPSHOT/CustomAuthAdapter-1.0-SNAPSHOT.jar
99.9%
Uptime
< 1s
Latency
10x
Faster

v2.0 NEW v1.5 DEPRECATED

  • Java Development Kit installed - completed
  • PingFederate SDK downloaded - completed
  • IDE set up - pending
💜 Pro Tip: Use continuous integration pipelines to automate testing and deployment.