---
title: Enable SSL pinning
description: Applies to:
component: sdks
version: latest
page_id: sdks:sdks:sdkconfiguration/ssl-pinning
canonical_url: https://docs.pingidentity.com/sdks/latest/sdks/sdkconfiguration/ssl-pinning.html
revdate: Mon, 3 Jul 2023 18:00:37 +0100
keywords: ["PingOne Advanced Identity Cloud", "PingAM", "Journeys", "Setup &amp; Configuration", "Source Code", "SDK"]
section_ids:
  get_a_hash_of_the_public_key_from_your_server: Get a hash of the public key from your server
  configure-ssl-pinning-android: Configure SSL pinning in Android
  override_default_implementation_of_ssl_pinning_for_android: Override default implementation of SSL pinning for Android
  configure-ssl-pinning-ios: Configure SSL pinning in iOS
  override_default_implementation_of_ssl_pinning_for_ios: Override default implementation of SSL pinning for iOS
---

# Enable SSL pinning

***Applies to***:

* [icon: check-square-o, set=fa]Ping (ForgeRock) SDK for Android

* [icon: check-square-o, set=fa]Ping (ForgeRock) SDK for iOS

* [icon: square-o, set=fa]Ping (ForgeRock) SDK for JavaScript

The Ping (ForgeRock) SDKs support *SSL pinning*, sometimes referred to as *certificate pinning*. SSL pinning is the security practice of validating the certificates presented by the server against known values.

When the SDK attempts to make an HTTPS connection to your authorization server, it first verifies that a hash of the server's public key (obtained from the server's SSL certificate) matches a set of hashes defined within your app. This SSL pinning reduces the chance of a man-in-the-middle (MITM) attack, improving the security of your app.

If the hash does not match, your app does not connect to the authorization server, and an error is returned instead. Note that if your public key changes, you will need to rebuild and re-release your app with the new hash included.

## Get a hash of the public key from your server

To enable SSL pinning you need a hash of your server's public key. You can use the `openssl` tool to extract this from your server's SSL certificate and create the hash value.

In the following command, replace `<tenant-env-fqdn>` with the fully-qualified domain name of your server, for example, `my-company.forgeblocks.com`:

```shell
echo | openssl s_client -servername <tenant-env-fqdn> -connect <tenant-env-fqdn>:443 | openssl x509 -pubkey -noout | openssl rsa -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
```

The command outputs a hash of the public key extracted from the certificate:

`S4kZuhQQ1DPcXBSWFQXD0gG+UW7usdbVx6roNWpRl65I=`

Use this value in the next steps to configure SSL pinning.

[icon: android, set=fab, size=3x]

#### [Ping (ForgeRock) SDK for Android](#configure-ssl-pinning-android)

Configure SSL pinning in your Android application.

[icon: apple, set=fab, size=3x]

#### [Ping (ForgeRock) SDK for iOS](#configure-ssl-pinning-ios)

Configure SSL pinning in your iOS application.

## Configure SSL pinning in Android

To enable SSL pinning in the Ping (ForgeRock) SDK for Android, add the hash of the public keys for any PingAM authorization servers your application will contact to your app's configuration.

Add the hashes to an array named `forgerock_ssl_pinning_public_key_hashes` in your `strings.xml` file:

```xml
<string-array name="forgerock_ssl_pinning_public_key_hashes">
   <item>S4kZuhQQ1DPcXBSWFQXD0gG+UW7usdbVx6roNWpRl65I=</item>
</string-array>
```

If the public key you use to obtain SSL certificates for the PingAM servers change, you can [update this property programmatically](configure-sdk-android.html#_ssl_pinning).

### Override default implementation of SSL pinning for Android

You can override how the Ping (ForgeRock) SDK for Android performs SSL pinning by registering your own implementation.

To override the default SSL pinning, you create your own implementation of `checkServerTrusted()`:

```java
try {
    final TrustManager myCustomTrustManager = new X509TrustManager() {
        @Override
        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {}

        @Override
        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
            // Provide custom SSL Pinning handling
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }
    };
    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, new TrustManager[] { myCustomTrustManager }, new java.security.SecureRandom());
    Config.getInstance().reset();
    Config.getInstance().init(this, null);
    Config.getInstance().setBuildSteps(Collections.singletonList(builder1 -> {
        builder1.sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) myCustomTrustManager);
        builder1.hostnameVerifier((s, sslSession) -> true);
    }));

} catch (NoSuchAlgorithmException | KeyManagementException e) {
    runOnUiThread(() -> content.setText(e.getMessage()));
}
```

Alternatively, you can override the SDK's SSL pinning functionality:

```kotlin
val myCustomTrustManager: TrustManager = object : X509TrustManager {
    override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
    override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
        // Provide custom SSL Pinning handling
    }
    override fun getAcceptedIssuers(): Array<X509Certificate> {
        return arrayOf()
    }
}
val sslContext = SSLContext.getInstance("SSL")
sslContext.init(null, arrayOf(myCustomTrustManager), SecureRandom())

val option = FROptionsBuilder.build {
    server {
        forgerock_url = "https://custom.example.com"
        forgerock_realm = "prod"
    }
    sslPinning {
        buildSteps = listOf(object: BuildStep<OkHttpClient.Builder> {
            override fun build(builder1: OkHttpClient.Builder) {
                builder1.sslSocketFactory(
                    sslContext.socketFactory,
                    myCustomTrustManager as X509TrustManager
                )
                builder1.hostnameVerifier { s, sslSession -> true }
            }
        })
        forgerock_ssl_pinning_public_key_hashes = emptyList()
    }
}
```

## Configure SSL pinning in iOS

To enable SSL pinning in the Ping (ForgeRock) SDK for iOS, add the hash of the public keys for any PingAM authorization servers your application will contact to your app's configuration.

Add the hashes to an array named `forgerock_ssl_pinning_public_key_hashes` in your `FRAuthConfig.plist` file:

```xml
<key>forgerock_ssl_pinning_public_key_hashes</key>
<array>
    <string>S4kZuhQQ1DPcXBSWFQXD0gG+UW7usdbVx6roNWpRl65I=</string>
</array>
```

If the public key you use to obtain SSL certificates for the PingAM servers change, you can [update this property programmatically](configure-sdk-ios.html#_ssl_pinning).

### Override default implementation of SSL pinning for iOS

You can override how the Ping (ForgeRock) SDK for iOS performs SSL pinning by registering your own implementation.

To override the default SSL pinning, create a new `CustomPinningHandler` subclass of the default `FRURLSessionSSLPinningHandler` class. Override the implementation of the `urlSession` functions:

```swift
class CustomPinningHandler: FRURLSessionSSLPinningHandler {
    override func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // Provide Custom SSL Pinning handling
    }

    override func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // Provide Custom SSL Pinning handling
    }
}
```

Add your new custom handler as part of the configuration:

```swift
let customPinningHandler = CustomPinningHandler(frSecurityConfiguration: nil)
RestClient.shared.setURLSessionConfiguration(config: nil, handler: customPinningHandler)
```
