← Back to Blog

How to clear stuck secure storage data using Capacitor on iOS?

Published August 28, 2025 Updated December 27, 2025 2 min read
iOS Capacitor Security Mobile Keychain

When building mobile apps with Capacitor, storing tokens and secrets securely is critical. localStorage is unsafe, and even secure HTTPS-only cookies are not always reliable, as they are not persisted across app reloads or terminations (if you use CapacitorCookies).

Most developers use secure storage solutions that utilise the system’s secure storage. One common option is Capacitor Secure Storage.

If you’re debugging or releasing an app that suddenly breaks because of stuck secure storage data, here are ways to fix and prevent it.

Cover

The Problem: Why iOS is Different

During development, some values can be mistakenly added or removed in the app. On Android, the solution is straightforward - clear app data and reopen the app. All stored data will be cleared.

How iOS Secure Storage Really Works

On iOS, the situation is much more complex. Since the secure storage plugin uses Apple Keychain underneath, you cannot delete the app’s Keychain data outside the app unless you have a jailbroken device (which is strongly not recommended). Even worse, if you have iCloud Keychain enabled, the data can persist even after a full device erasure. Fortunately, this is not the case for the simulator, where you can always select Device -> Erase All Content and Settings....

On real devices, if a user ends up with corrupted secure storage, the app might be completely broken — and simply reinstalling won’t help.

Fixing It: Options for Developers

Update the app

Ship an app update that clears all data on load. This is the most reliable solution, but also the slowest. It fixes the problem permanently.

Quick Fix with Safari DevTools

If the app is inspectable with Safari (and you have access to the device from macOS), you can launch Safari DevTools’s console and access Secure Storage, as every plugin is accessible from window.Capacitor.Plugins.

In that case, you can trigger a manual wipe of secure storage and reload the app like this:

window.Capacitor.Plugins.SecureStoragePlugin.clear().then(() =>
  window.location.reload()
);

How to prevent such events?

Use @capacitor/preferences, which uses UserDefaults underneath, to create a flag hasLaunchedBefore. This checks if the app is launched for the first time since installation.

Detect the first launch after install so the app knows if it’s freshly installed. On first launch, clear the secure storage.

Note: If used in an already deployed app, this approach will:

  • Delete existing tokens (treating the app as fresh install)
  • In production, mitigate this by:
    • Shipping two updates (first add Preferences, then clear), or
    • Validating stored tokens with your backend before clearing
import { Preferences } from "@capacitor/preferences";
import { SecureStoragePlugin } from "capacitor-secure-storage-plugin";

/** Ensures corrupted tokens are cleared after fresh install. Can be launched only for iOS */
const onAppLaunch = async () => {
  const hasLaunchedBefore = await Preferences.get({ key: "hasLaunchedBefore" });
  if (hasLaunchedBefore.value !== "true") {
    // First launch after install
    await SecureStoragePlugin.clear();
    Preferences.set({ key: "hasLaunchedBefore", value: "true" });
  }
};

Why use @capacitor/preferences instead of localStorage?

localStorage is usually more heavily used and more volatile than @capacitor/preferences. This data should not be altered or cleared until the app is uninstalled.

Takeaway

  • Use secure storage for tokens and secrets
  • On iOS, secure data survives app deletion
  • For development, Safari DevTools can help
  • In production, add a first-launch detector to automatically reset storage on a fresh install