For the complete documentation index, see llms.txt. You can also append .md to any page URL to get its markdown version.
Skip to main content
For the complete documentation index, see llms.txt.

For the complete documentation index, see llms.txt

Security best practices

For the complete documentation index, see llms.txt

To maintain compliance with PSD2 (Payment Services Directive 2) and ensure robust application security, it is important that you properly manage how sensitive data is handled in memory.

On this page, you can learn about:

  • The different types of data handled by the SDK.
  • The classification of data handled by the SDK.
  • How you should manage data in your application's memory lifecycle.

How does it work?

For the complete documentation index, see llms.txt

When handling authentication and user verification, sensitive data is temporarily loaded into the mobile device's memory.

To prevent this data from being exposed in the event of a memory dump or a device-level compromise, we recommend that you overwrite secrets as early as possible after use, so that they are completely erased from memory.

Classification definitions

For the complete documentation index, see llms.txt

To learn about the different data classifications, see the table below:

ClassificationDescription
SECRETThis data is highly sensitive.

You should overwrite it in memory immediately after it is no longer required.
NOT SECRETThis data is not considered highly sensitive.

You do not need to overwrite it after use, although doing so is safe and acceptable.

Data classification and handling

You can learn about the specific data types, their security classification, and the reasoning behind their memory management requirements in the tables below.

User inputs and codes (API changes in this SDK version)

User inputs and codes (best practices)

Authorisation token

Want to learn more?

To learn how the authorisation token is used for recovery operations, see the iOS Account recovery feature documentation.

Memory management in Swift

When handling PINs, activation codes, and recovery codes in Swift, you should not store the values as String or NSString objects. This is because they are both immutable, which leaves the sensitive data vulnerable to memory dumping and analysis.

What does this mean?

Once a String or NSString is created, its value cannot be modified or overwritten; it remains in memory until the runtime decides to clean them up.

This is why the SDK requires NSMutableString for PIN, activation code, and recovery code parameters; it enables you to make a best-effort attempt to overwrite the data with setString("") immediately after use.

Memory erasure limitations

Although NSMutableString.setString("") performs best-effort clearing of the string's content, Foundation does not guarantee that previous in-memory copies or underlying buffers are securely overwritten.

What does this mean?

Sensitive data may persist in allocator caches, runtime copies, or other memory regions.

This risk is why the entire chain of your code through to the SDK must use NSMutableString rather than String, so that you minimise the number of immutable copies in memory.

However, neither setString("") nor the SDK's internal zeroing should be considered a cryptographic guarantee of memory erasure.

Migration paths

If you are updating an existing integration to work with this version of the SDK, there are two approaches. These are presented as Option A and Option B in the sections below.

Option A: Full PSD2 compliance

Our recommendation

This is the option that we recommend.

For this option, you adopt NSMutableString as the native type for credentials throughout your own codebase.

This means that wherever the end-user's PIN or recovery code is stored, passed between screens, or held in a view model, you should use NSMutableString instead of String. You must ensure that you zero the values after passing them to the SDK.

Example

Full compliance: Storing and zero as NSMutableString
// Store as NSMutableString, not String
var pinCode = NSMutableString()

// Pass directly — SDK will zero it after use
encapController.finishActivation(withAuthMethod: .pin(value: pinCode), ...) { result in
// Optionally zero your own reference too
pinCode.setString("")
}

Option B: Lightweight wrapper for fast shipping

For this option, you keep your existing String code unchanged and wrap the value at the point of calling the SDK.

Example

Lightweight wrapper: Convert at call site
// Existing code stays as-is
let pin: String = self.pinField.text ?? ""

// Wrap immediately before the SDK call
encapController.finishActivation(withAuthMethod: .pin(value: NSMutableString(string: pin)), ...)

Option comparison

For a comparison of the two migration path options, see the table below:

Client-side pattern: best-effort clearing of NSMutableString

Since the SDK requires NSMutableString for PIN and recovery code parameters, you should adopt this pattern in your client code.

After passing the secret to the SDK, you must immediately perform best-effort clearing of your own reference using the defer statement.

The defer block ensures the clearing attempt happens regardless of whether the API call succeeds or returns an error.

Note

This is a best-effort approach, not a cryptographic guarantee.

Example: Client code should attempt to clear its copy of the secret
func handlePinActivation(pin: NSMutableString) {
defer {
// Best-effort clearing: attempt to overwrite the content
pin.setString("")
}

// Pass the NSMutableString to the SDK
encapController.finishActivation(withAuthMethod: .pin(value: pin), ...) { result in
// Handle result
}
// defer block runs here, attempting to clear the string
}