PingFederate plugin developer guide
This guide is to help developers build a PingFederate plugin using the Software Development Kit (SDK). It explains what a plugin is, how the pieces fit together, what a plugin project looks like on disk, and how to unit test one. It’s meant to be read alongside example plugins in the <pingfed-install>/pingfederate/sdk/examples/ directory. Pick the example closest to what you want to build and follow along.
What is a plugin?
A PingFederate plugin is a Java class that implements one of the interfaces the SDK defines, such as PasswordCredentialValidator, IdpAuthenticationAdapterV2, and TokenGenerator. Each interface represents an extension point, which is a place where PingFederate calls out to your code instead of, or in addition to, its built-in behavior.
You compile your class into a jar, tell PingFederate which class implements which interface, and drop the jar into the server. PingFederate discovers it at startup and makes it available in the admin console alongside its built-in options.
Two things make this simpler than it sounds:
- The SDK is provided, not bundled
-
Your
pom.xmldepends onpingfederate-sdkwithprovidedscope. That means the interfaces and helper classes are available while you’re writing code, but they’re not packaged into your jar. The running server already has them. Your jar only needs to contain your own classes. - Discovery is just a text file
-
PingFederate finds your plugin class through a small file under
PF-INF/in your jar, named after the plugin type, containing the fully-qualified class name that implements it. Nothing more elaborate than that.
How the pieces fit together
Building a plugin involves five steps:
-
Pick the extension point.
Choose the SDK interface matching what you want to add, such as a password validator, an identity provider (IdP) adapter, a token generator, or a data store. Each subdirectory in
examples/is a working implementation of one extension point. Find the closest match and use it as your starting point. -
Implement the interface.
Every plugin type requires two methods no matter what it does:
-
configure(Configuration): Where PingFederate hands you the admin settings. -
getPluginDescriptor(): Where you describe the plugin back to PingFederate.Beyond these, you implement whatever methods the specific interface requires, plus any optional companion interfaces for extra capabilities, such as a password validator that also supports password reset.
-
-
Describe the admin GUI.
Inside
getPluginDescriptor(), build aGuiConfigDescriptorwith text fields such asTextFieldDescriptororCheckBoxFieldDescriptor. This declares the attribute contract, the set of attribute names your plugin promises to produce for whatever consumes them downstream. It also allows an admin to configure your plugin from the admin console. -
Add the deployment descriptor.
Create the
src/main/resources/PF-INF/file described above as a static resource. -
Build and deploy.
mvn clean installproduces the jar. Copy the jar to<pingfed_install>/pingfederate/server/default/deployand restart the server. Your plugin now shows up in the admin console under the display name your gave it ingetPluginDescriptor().
Project layout
Every example plugin in the <pingfed-install>/pingfederate/sdk/examples/ directory follows the same layout.
The following is the layout for the dynamic-client-registration plugin, which also includes unit tests:
dynamic-client-registration/
├── pom.xml # internal build, used only inside this source tree
├── pom-example.xml # the build customers actually use; renamed to
│ # pom.xml when the SDK distribution is assembled
├── README-example.md # build/deploy instructions for this example
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/pingidentity/clientregistration/
│ │ │ └── SoftwareStatementValidatorPlugin.java
│ │ │ # the plugin class — implements an SDK interface
│ │ └── resources/
│ │ └── PF-INF/
│ │ └── dynamic-client-registration
│ │ # the deployment descriptor: one line, the
│ │ # implementing class's fully-qualified name.
│ │ # Checked in and hand-maintained — see "The
│ │ # deployment descriptor" below
│ └── test/
│ ├── java/
│ │ └── com/pingidentity/clientregistration/
│ │ ├── SoftwareStatementValidatorPluginTest.java
│ │ │ # a JUnit test for the plugin
│ │ └── TestTrustedCAAccessorService.java
│ │ # a test-only service implementation — see
│ │ # "Unit testing" below
│ └── resources/
│ └── META-INF/
│ └── services/
│ └── com.pingidentity.sdk.internal.services.interfaces.TrustedCAAccessorService
│ # registers the test implementation above
└── target/ # build output — jar, compiled classes; not checked in
A plugin with no unit tests is simpler. Those include only pom.xml, pom-example.xml, README-example.md, the plugin class, and its PF-INF/ descriptor. The src/test directory only appears when an example ships with test.