---
title: Integrate with third-party services
description: The Add-on SDK includes the ability for a custom plugin to integrate with external, third-party services using HTTP.
component: pingaccess
version: 9.0
page_id: pingaccess:agents_and_integrations:pa_integrate_with_third_party_services
canonical_url: https://docs.pingidentity.com/pingaccess/9.0/agents_and_integrations/pa_integrate_with_third_party_services.html
revdate: March 27, 2024
section_ids:
  section_dlt_t1j_fdb: Obtaining the HTTP client instance
  section_kfb_t1j_fdb: Obtaining a handle to a third-party service
  section_bpn_5cz_4mb: Administrator-configured third-party services
  section_jzv_vcz_4mb: Third-party services for the OAuth authorization server and OIDC provider
  section_gx4_s1j_fdb: Making a HTTP call to a third-party service
  section_rj3_s1j_fdb: Base classes
  section_grb_s1j_fdb: Sample plugins
---

# Integrate with third-party services

The Add-on SDK includes the ability for a custom plugin to integrate with external, third-party services using HTTP.

This section provides a high-level overview of utilizing this functionality from a custom plugin:

* [Obtaining the HTTP client instance](#section_dlt_t1j_fdb)

* [Obtaining a handle to a third-party service](#section_kfb_t1j_fdb)

* [Making a HTTP call to a third-party service](#section_gx4_s1j_fdb)

* [Base classes](#section_rj3_s1j_fdb)

* [Sample plugins](#section_grb_s1j_fdb)

## Obtaining the HTTP client instance

PingAccess provides access to a HTTP client utility interface, HttpClient, through dependency injection. Plugins are expected to obtain an instance of this interface using an approach like the following.

```
public class DocumentationPlugin // interfaces and base classes omitted for brevity
{
    private HttpClient httpClient;

    // ... other code omitted ...

    @Inject
    public void setHttpClient(HttpClient httpClient)
    {
        this.httpClient = httpClient;
    }

    // ... other code omitted ...
}
```

## Obtaining a handle to a third-party service

Given a HttpClient instance, a plugin will also need a handle to a third-party service to make an outbound HTTP call to the service represented by the Third-Party Service administrative configuration object. This handle is an instance of the ThirdPartyServiceModel class and is specified to the HttpClient in its send method.

There are two different ways to obtain a ThirdPartyServiceModel instance:

* [Administrator-configured third-party services](#section_bpn_5cz_4mb)

* [Third-party services for the OAuth authorization server and OIDC provider](#section_jzv_vcz_4mb)

## Administrator-configured third-party services

The PingAccess Administrative UI and application programming interface (API) *(tooltip: \<div class="paragraph">
\<p>A specification of interactions available for building software to access an application or service.\</p>
\</div>)* allow administrators to define the communication configuration for an external service by defining a third-party service. These configuration objects can then be associated with custom plugins through their configuration.

To enable a plugin's configuration to reference a third-party service, it should define a field in the configuration with the type of ThirdPartyServiceModel.

```
    private static class Configuration extends SimplePluginConfiguration
    {
        // ... other code omitted ...

        @UIElement(order = 30,
                type = ConfigurationType.SELECT,
                label = "Risk Authorization Service",
                modelAccessor = ThirdPartyServiceAccessor.class,
                required = true)
        @NotNull
        private ThirdPartyServiceModel riskAuthzService;

        // ... other code omitted ...

        public ThirdPartyServiceModel getRiskAuthzService()
        {
            return riskAuthzService;
        }

        public void setRiskAuthzService(ThirdPartyServiceModel riskAuthzService)
        {
            this.riskAuthzService = riskAuthzService;
        }
    }
```

The important items in this example:

* The `modelAccessor` attribute of the UIElement must be set to `ThirdPartyServiceAccessor`.

* The field in the plugin configuration class must be of type `ThirdPartyServiceModel`.

## Third-party services for the OAuth authorization server and OIDC provider

In addition to providing a way for an administrator to configure a plugin to use an arbitrary third-party service, PingAccess allows a plugin to use a third-party service that represents the OAuth *(tooltip: \<div class="paragraph">
\<p>A standard framework that enables an application (OAuth client) to obtain access tokens from an OAuth authorization server for the purpose of retrieving protected resources on a resource server.\</p>
\</div>)* Authorization Server or OpenID Connect (OIDC) *(tooltip: \<div class="paragraph">
\<p>An authentication protocol built on top of OAuth that authenticates users and enables clients (relying parties) of all types to request and receive information about authenticated sessions and users. OIDC is extensible, allowing clients to use optional features such as encryption of identity data, discovery of OpenID Providers (OAuth authorization servers), and session management.\</p>
\</div>)* provider. The benefit of leveraging this functionality is that a plugin can require access to either of these services without requiring the administrator to configure the plugin to use those services.

Similar to the previous section, the plugin obtains a ThirdPartyServiceModel instance that is a handle to the OAuth Authorization Server or OIDC provider by indicating this requirement in its plugin configuration class. However, the mechanism is a bit different, as shown in the following example.

```
    private static class Configuration extends SimplePluginConfiguration
    {
        // ... other code omitted ...

        private ThirdPartyServiceModel oidcProvider;

        // ... other code omitted ...

        public ThirdPartyServiceModel getOidcProvider()
        {
            return oidcProvider;
        }

        @Inject
        @OidcProvider
        public void setOidcProvider(ThirdPartyServiceModel oidcProvider)
        {
            this.oidcProvider = oidcProvider;
        }
    }
```

The setter for the oidcProvider field is annotated with the `@OidcProvider` annotation.

If the `@OidcProvider` annotation includes a parameter, that parameter specifies a required endpoint defined by the OIDC provider metadata of the current token provider. When the plugin is instantiated, the validation for the `@OidcProvider` parameter will pass only if the specified endpoint is a valid HTTP Uniform Resource Identifier (URI) *(tooltip: \<div class="paragraph">
\<p>Identifies a web resource with a string of characters conforming to a specified format.\</p>
\</div>)* in the OIDC provider metadata. For example, the following annotation will require the `backchannel_authentication` URI.

```
@OidcProvider("backchannel_authentication")
```

## Making a HTTP call to a third-party service

With an instance of HttpClient and an instance of ThirdPartyServiceModel in hand, a plugin can make a HTTP call to the external service represented by the ThirdPartyServiceModel. Here is an example method that makes a GET request to a resource on the external service with a path of `/data` and a query string of `page=1`.

```
private static CompletionStage<ClientResponse> sendRequest(HttpClient httpClient,
                                                           ThirdPartyServiceModel model)
{
    Headers headers = ClientRequest.createHeaders();
    headers.setAccept(Collections.singletonList("application/json"));

    ClientRequest request = new ClientRequest(Method.GET,
                                              "/data?page=1",
                                              headers);

    return httpClient.send(request, model);
}
```

The result of the `HttpClient send` method is a CompletionStage. A CompletionStage is returned because PingAccess is performing the HTTP call asynchronously and as a result, handling of the result of the call needs to be performed by callbacks registered with the CompletionStage.

You can use the `getRequestUri()` method to stand in for the endpoint *(tooltip: \<div class="paragraph">
\<p>One end in a communication channel, typically a URI.\</p>
\</div>)*. This can be useful if the endpoint is not known during development.

```
    ClientRequest request = new ClientRequest(Method.GET,
                                              model.getRequestUri().get(),
                                              headers);
```

The `RequestUri` is set by the `@OidcProvider("RequestUri")` annotation, and is unset if the `@OidcProvider("RequestUri")` annotation is not present.

For a more complete example of using the HttpClient to make an external HTTP call, see the sample SDK plugins packaged with the PingAccess distribution.

## Base classes

The SDK provides the following base classes to make it easier to implement a plugin that leverages the HttpClient interface. They all provide access to a HttpClient instance using a getHttpClient method:

* `AsyncRuleInterceptorBase`

* `AsyncSiteAuthenticatorInterceptorBase`

* `AsyncIdentityMappingPluginBase`

* `AsyncLoadBalancingPluginBase`

## Sample plugins

The use of the HttpClient and ThirdPartyServiceModel classes are demonstrated in the following samples provided in the PingAccess distribution:

* RiskAuthorizationRule

  A rule that obtains a risk score from an external, risk service as well as leveraging the OAuth authorization server to obtain an OAuth access token *(tooltip: \<div class="paragraph">
  \<p>A data object by which a client authenticates to a resource server and lays claim to authorizations for accessing particular resources.\</p>
  \</div>)* used to access the risk service.

* MetricBasedPlugin

  A load balancing strategy that obtains host capacity metadata from an external service.
