Ping SDKs

Token and key security

The Ping SDKs handle and store keys and tokens based on the security best practices of each platform.

Token storage

Depending on the authentication use case, the SDKs will potentially have to store and be able to retrieve the session cookie, ID tokens, access tokens, and refresh tokens.

Each token is serving a different use case, and as such how the SDKs handle them can be different.

The following sections cover how the SDKs handle different types of tokens.

Session tokens and cookies

  • On Android and iOS, the session tokens are stored in either the Android keystore or iOS keychain after authentication completes. The tokens are encrypted using a hardware-backed security key when possible and can be retrieved by the SDK on request.

  • When using the Ping SDK for JavaScript, cookies are stored in the browser’s cookie storage. The cookie name matches the one provided by PingAM (such as iPlanetDirectoryPro) and its value is the actual session token. When making requests to PingAM, the value is passed as an authentication cookie. This cookie is configured with the HTTPOnly and Secure attributes, which provide additional layers of security.

ID, access, and refresh tokens

  • On Android and iOS when authorization is completed any OAuth 2.0-related tokens are stored securely locally, encrypted using a hardware-backed security key when possible and can be retrieved by the SDK on request. Tokens are not configured as cloud sharable by default.

  • When using the Ping SDK for JavaScript, the OAuth 2.0 Tokens are stored by using one of the web storage APIs provided by the browser. By default, this uses the browser’s localStorage, but the SDK also supports sessionStorage.

    If required, app developers can provide a custom storage mechanism that can be passed to the SDK.

    We recommend that JavaScript single-page applications do not use refresh tokens or any other long-running authorization elements due to the potentially unsecure nature of the storage mechanisms provided by browsers.

Token lifecycle

The session and OAuth 2.0-related tokens the SDKs handle all have associated expiry times. When a token reaches its expiry time it becomes unusable.

A feature of the SDKs is that they manage the refresh of OAuth 2.0 tokens. The timing of the refresh is based on a threshold value to improve the end-user experience. The SDKs refresh tokens automatically when the token is requested from storage to be used in your application and its expiry is within the threshold.

In the case of access tokens, if a refresh token is present, then the Android and iOS SDKs will use it to obtain a new access token. If the refresh token cannot be used, is not present, or if it has expired, then the SDKs fall back to using the session token to start a new OAuth 2.0 flow.

The SDKs do not handle the refresh of session tokens. If a session token has expired, the app needs to re-authenticate the user.

When an OAuth 2.0 or session token expires, the SDK removes any respective tokens from the secure storage and performs a cleanup. The Android and iOS SDKs also check if the current session token is the same one used to obtain the OAuth 2.0 tokens. In case of a mismatch, then these orphaned tokens are cleaned.

When using SDK logout methods to perform a Logout event, the SDKs revoke existing OAuth 2.0 tokens, revoke the session, and perform a local cleanup. If the SDKs are unable to revoke the session at the server—​for example the network is unavailable—​then the SDKs remove the tokens from local storage.

When using the Ping SDK for JavaScript, if an access token expires within the threshold limit or returns an HTTP 401 Unauthorized error, the SDK attempts to renew it using the same session cookie that was performing the authorization code flows.

The Ping SDK for JavaScript calls the endSession and session?action=logout endpoints during logout, as well as calling revoke whenever you use FRUser.logout. This ensures that the server invalidates the session cookie.

The Ping SDK for JavaScript has no direct control over the session cookie; it can only make requests to the browser that may or may not be acted upon. Instead, it must rely on the server to manage the cookie removal.

Encryption key storage

On supported platforms and devices, the Ping SDKs generate Hardware-Backed encryption keys, and uses them to encrypt and store tokens. This provides an extra level of security against attacks.

  • The Ping SDK for iOS uses the kSecKeyAlgorithmECIESEncryptionCofactorX963SHA256AESGCM encryption algorithm. The key is stored in the Secure Enclave.

    On unsupported devices, the SDK cannot not enforce hardware-backed encryption and will save the tokens in the iOS keychain.

  • The Ping SDK for Android uses a number of different algorithms, depending on the OS version and device functionality. It supports the following encryptors:

    • AndroidLEncryptor: RSA

    • AndroidMEncryptor: AES

    • AndroidNEncryptor: Similar to M, with the addition of setting setInvalidatedByBiometricEnrollment to true

    • AndroidPEncryptor: Similar to N, with the addition of using Android Strongbox

Hardware-backed key storage and encryption

Both the Android and iOS SDKs use platform-provided methods to create hardware-backed encryption keys.

  • On iOS the SDK creates keys within the SecuredKey.swift class. If SecuredKey generation fails, the KeychainManager generates the KeychainService with no SecuredKey. The values in this case will be added to the iOS keychain as kSecClassGenericPassword types.

    If SecuredKey creation is successful then the value is encrypted before being stored. The SecuredKey.swift class provides an isAvailable() public method that validates whether creation of the SecuredKey using Secure Enclave is available on the device or not.

    The SDKs also support devices that do not have Secure Enclave or other hardware-backed encryption functionality.
  • On Android, the SDK uses DefaultTokenManager and DefaultSingleSignOnManager for storing tokens, in addition to SecuredSharedPreferences.java on supported devices.

    Depending on the Android version, the SDK can use more specific encryptors. For more information, see getEncryptor. For information about the different encryptor classes, see the auth folder in GitHub.