ionic-enterprise-sdk-migration ยท diff
git:20260501.ed3e92e to git:20261011.86834d4
98 added, 53 removed. Audit A to B.
---
name: ionic-enterprise-sdk-migration
- description: Guides the agent through migrating Capacitor apps from Ionic Enterprise SDK plugins to Capgo and Capacitor alternatives. Covers dependency detection, API replacement, local storage changes, and platform cleanup. Do not use for generic Capacitor version upgrades or Capgo live updates.
+ description: Migrates Capacitor apps off Ionic Enterprise SDK plugins - @ionic-enterprise/auth (Auth Connect), @ionic-enterprise/identity-vault (Identity Vault), and @ionic-enterprise/secure-storage (Secure Storage) - to @capgo/capacitor-social-login (OAuth2/OIDC for Azure AD, Auth0, Okta, Cognito, plus Google/Apple), @capgo/capacitor-native-biometric (biometric-protected Keychain/Keystore credential vault), and @capgo/capacitor-fast-sql or @capgo/capacitor-data-storage-sqlite (encrypted storage). Use when package.json has @ionic-enterprise/* packages, code imports AuthConnect, BrowserVault/Vault/DeviceSecurityType, or SQLite from secure-storage, or the user needs to move stored tokens without logging users out. Do not use for Ionic Appflow live updates or builds (ionic-appflow-migration), generic SQLite plugin swaps (sqlite-to-fast-sql), Capacitor version upgrades (capacitor-app-upgrades), or Capgo live updates (capgo-live-updates).
allowed-tools:
- Bash(node -e *)
- Bash(rg *)
- Bash(npm *)
- Bash(npx cap *)
---
# Ionic Enterprise SDK Migration
- Migrate Capacitor apps away from Ionic Enterprise SDK plugins and onto open alternatives.
+ Replace Ionic Enterprise plugins with open Capgo plugins one at a time, preserving login sessions and stored data.
- ## When to Use This Skill
+ Context: Ionic stopped selling its commercial products (including the Enterprise SDK) in February 2025 and is winding down maintenance; plan migrations before the license or support window ends.
- - User is replacing `@ionic-enterprise/*` plugins
- - User wants to remove Ionic Enterprise dependencies from an app
- - User needs a migration path for auth, biometric unlock, or secure local storage
+ ## When to Use
+ TRIGGER when:
+ - `package.json` contains `@ionic-enterprise/auth`, `@ionic-enterprise/identity-vault`, or `@ionic-enterprise/secure-storage`.
+ - Code imports `AuthConnect`, `ProviderOptions`, `Vault`, `BrowserVault`, `VaultType`, `DeviceSecurityType`, or Secure Storage's `SQLite` / `KeyValueStorage`.
+ - The user asks how to replace Auth Connect, Identity Vault, or Secure Storage without forcing re-login.
+
+ Do not use for:
+ - Appflow Live Updates / builds -> `ionic-appflow-migration`.
+ - Community or other SQLite plugins -> `sqlite-to-fast-sql`.
+ - Biometric UX or general security review -> `capacitor-security`.
+
## Live Project Snapshot
Detected Ionic Enterprise and replacement packages:
- !`node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@ionic-enterprise/')||name.startsWith('@capgo/')||name==='@capacitor/preferences')out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"`
+ !`node -e "const fs=require('fs');if(!fs.existsSync('package.json'))process.exit(0);const pkg=JSON.parse(fs.readFileSync('package.json','utf8'));const out=[];for(const section of ['dependencies','devDependencies']){for(const [name,version] of Object.entries(pkg[section]||{})){if(name.startsWith('@ionic-enterprise/')||name.startsWith('@capgo/')||name==='@capacitor/preferences'||name==='@capacitor/core')out.push(section+'.'+name+'='+version)}}console.log(out.sort().join('\n'))"`
## Replacement Map
- | Ionic Enterprise plugin | Typical use | Replacement path |
- | ----------------------- | ----------- | ---------------- |
- | Auth Connect | Social or OIDC login | `@capgo/capacitor-social-login` and its OAuth/OIDC compatibility flow |
- | Identity Vault | Biometric gate + protected session state | `@capgo/capacitor-native-biometric` plus app-managed session storage |
- | Secure Storage | Encrypted local data | `@capgo/capacitor-fast-sql` for encrypted local storage and structured persistence |
-
- If the app only needs non-sensitive key-value storage, use `@capacitor/preferences`. For encrypted local storage or structured local persistence, prefer `@capgo/capacitor-fast-sql`.
-
- ## Agent Behavior
-
- - Auto-detect Ionic Enterprise dependencies in `package.json` before asking questions.
- - Migrate one plugin at a time when the app uses multiple Ionic Enterprise packages.
- - Preserve behavior: same redirect URIs, same scopes, same session rules, and same stored keys whenever possible.
-
- ## Procedures
-
- ### Step 1: Detect Ionic Enterprise Dependencies
+ | Ionic Enterprise | Replacement | Covers | Not covered (rebuild in app) |
+ |---|---|---|---|
+ | Auth Connect | `@capgo/capacitor-social-login` (`provider: 'oauth2'` for OIDC/OAuth2 IdPs; `google`, `apple`, `facebook`, etc.) | Authorization code + PKCE, token refresh (`refreshToken`), logout, native Apple/Google sign-in | Token storage policy (store tokens with Native Biometric or encrypted SQL) |
+ | Identity Vault | `@capgo/capacitor-native-biometric` | Save/read/delete credentials in Keychain/Keystore; `accessControl: BIOMETRY_CURRENT_SET` or `BIOMETRY_ANY` makes reads require biometrics; `verifyIdentity` with passcode fallback on iOS; `biometryChange` listener | Inactivity lock timeout, privacy screen on background (`@capacitor/privacy-screen`), custom-passcode vaults, in-memory vaults |
+ | Secure Storage (SQLite) | `@capgo/capacitor-fast-sql` with `encrypted: true` + `encryptionKey` | Encrypted SQLite (SQLCipher), transactions, batch, `KeyValueStore` | Key management - keep the DB key in Native Biometric, not in JS constants |
+ | Secure Storage (key-value) | `@capgo/capacitor-data-storage-sqlite` or Fast SQL `KeyValueStore` | Simple encrypted key-value | |
- Start from the injected package snapshot, then read `package.json` directly and look for:
+ Non-sensitive settings can go to `@capacitor/preferences`. Never move tokens or secrets there.
- - `@ionic-enterprise/auth`
- - `@ionic-enterprise/identity-vault`
- - `@ionic-enterprise/secure-storage`
+ ## Procedure
- If none are present, tell the user no Ionic Enterprise plugins were detected.
+ ### Step 1: Detect and plan
- If multiple are present, list them and migrate them in a clear order.
+ ```bash
+ rg -n "@ionic-enterprise/" -g '!node_modules' .
+ ```
- ### Step 2: Replace Auth Connect
+ List each enterprise package, every call site, and what is stored (keys, DB names, vault config: `type`, `deviceSecurityType`, `lockAfterBackgrounded`, `unlockVaultOnLoad`). Migrate one plugin per release when more than one is present. Report the plan before editing.
- Move social and enterprise identity flows to `@capgo/capacitor-social-login`.
+ ### Step 2: Plan data carry-over (two-release rule)
- For OIDC providers, keep the provider-specific flow aligned with the compatibility wrapper or the plugin's documented OAuth/OIDC path so scopes, redirect URLs, and callback handling stay intact.
+ Old plugin data can only be read while the old plugin is still installed. For tokens, vault values, or encrypted DBs:
+ 1. Release N: install the Capgo replacement alongside the enterprise plugin. On first launch, read from the old store, write to the new one, set a `migrated` flag, then clear the old store.
+ 2. Release N+1 (after most users have opened release N): remove the enterprise plugin.
- ### Step 3: Replace Identity Vault
+ If the user accepts a forced re-login for everyone, a single release is fine; confirm this explicitly.
- Identity Vault usually combines biometric unlock with protected app state.
+ ### Step 3: Auth Connect -> Social Login
- Use `@capgo/capacitor-native-biometric` for device-level unlock checks, then rebuild the session timeout and lock screen behavior in app code.
+ ```bash
+ npm install @capgo/capacitor-social-login
+ npx cap sync
+ ```
- Keep secrets out of plain client storage. Store only the minimum local state required for UX continuity.
+ - Keep the same client IDs, scopes, and redirect URIs; register any new native redirect (custom scheme or universal link) with the IdP before shipping.
+ - Map each Auth Connect provider (Azure, Auth0, Okta, Cognito, generic OIDC) to an `oauth2` entry in `SocialLogin.initialize({ oauth2: { <providerId>: { ... } } })` with `clientId`/`appId`, `issuerUrl` or `authorizationBaseUrl` + `accessTokenEndpoint`, `redirectUrl`, and scopes. Check the plugin's OAuth2 docs for the exact fields of the installed version.
+ - Replace `AuthConnect.login/logout/refreshSession/isAccessTokenExpired` with `SocialLogin.login({ provider: 'oauth2', options: { providerId } })`, `logout`, `refreshToken`, and your own expiry check on the returned token.
+ - Compare the before/after authorization request (scopes, `prompt`, audience) and token response in a test tenant.
- ### Step 4: Replace Secure Storage
+ ### Step 4: Identity Vault -> Native Biometric
- If the app stores encrypted local data, move it to `@capgo/capacitor-fast-sql`.
+ ```bash
+ npm install @capgo/capacitor-native-biometric
+ npx cap sync
+ ```
- If the app uses structured local persistence, keep it on `@capgo/capacitor-fast-sql` so the encrypted and non-encrypted paths stay on the same engine.
+ ```ts
+ import { NativeBiometric, AccessControl } from '@capgo/capacitor-native-biometric';
- If the app only needs non-sensitive key-value storage, move those values to `@capacitor/preferences`.
+ await NativeBiometric.setCredentials({
+ server: 'com.company.app.session',
+ username: userId,
+ password: refreshToken,
+ accessControl: AccessControl.BIOMETRY_CURRENT_SET,
+ });
- Preserve the database schema and migrate the access layer instead of rewriting the data model when the app already relies on SQLite-backed storage.
+ const { password: token } = await NativeBiometric.getSecureCredentials({
+ server: 'com.company.app.session',
+ reason: 'Unlock your account',
+ });
+ ```
- ### Step 5: Search for Remaining Enterprise Imports
+ - `lockAfterBackgrounded` -> on `App` `resume`, if elapsed time exceeds the timeout, show a lock screen and call `getSecureCredentials` again.
+ - `DeviceSecurityType.Both` / passcode fallback -> `verifyIdentity` supports device passcode fallback on iOS; protected credential reads stay biometric-only.
+ - `BIOMETRY_CURRENT_SET` invalidates the item when biometrics change (like Identity Vault's strict mode); `BIOMETRY_ANY` survives enrollment changes.
+ - Privacy screen in app switcher -> `@capacitor/privacy-screen`.
+ - iOS: add `NSFaceIDUsageDescription` to `Info.plist`.
- After the replacement work, search the project for remaining enterprise references:
+ ### Step 5: Secure Storage -> Fast SQL or Data Storage SQLite
```bash
- rg -n "@ionic-enterprise" .
+ npm install @capgo/capacitor-fast-sql
+ npx cap sync
```
- Replace or remove any leftovers before continuing.
+ ```ts
+ import { FastSQL, KeyValueStore } from '@capgo/capacitor-fast-sql';
- ### Step 6: Clean Up and Verify
+ const db = await FastSQL.connect({ database: 'app', encrypted: true, encryptionKey });
+ const kv = await KeyValueStore.open({ database: 'kv', encrypted: true, encryptionKey });
+ ```
- Remove unused enterprise packages from `package.json`, reinstall dependencies with the repository's existing package manager, and run sync from the app directory that contains `capacitor.config.*`:
+ - Keep the same schema; port queries (`executeSql` -> `db.query` / `db.run` / `db.executeBatch` / `db.transaction`).
+ - Encryption requires SQLCipher: Android `implementation 'net.zetetic:sqlcipher-android:<version>'` in `android/app/build.gradle`; iOS CocoaPods subspec `CapgoCapacitorFastSql/SQLCipher`. Without it, `encrypted: true` fails with `Encryption is not available in this build` on iOS.
+ - Fast SQL runs a localhost HTTP server: add `NSAppTransportSecurity` -> `NSAllowsLocalNetworking` (iOS) and a localhost cleartext `network_security_config.xml` (Android). See `sqlite-to-fast-sql` for the full setup.
+ - Store `encryptionKey` with Native Biometric (Step 4) or derive it server-side; never hard-code it.
+ ### Step 6: Clean up
+
```bash
- npm install
+ npm uninstall @ionic-enterprise/auth @ionic-enterprise/identity-vault @ionic-enterprise/secure-storage
+ rg -n "@ionic-enterprise" -g '!node_modules' .
npx cap sync
```
- Then verify the app builds on every shipped platform.
+ Remove the Ionic Enterprise registry/token lines from `.npmrc` only after no enterprise package remains (CI installs fail otherwise).
+ ## Verification
+
+ - Upgrade test: install the current store build, log in, store data; install the new build over it; user stays logged in and data is present.
+ - Fresh install: login, token refresh, logout, and biometric unlock work on real iOS and Android devices (simulators cannot fully test biometrics).
+ - Change device biometrics: `BIOMETRY_CURRENT_SET` items become unreadable and the app falls back to login.
+ - `rg -n "@ionic-enterprise" -g '!node_modules' .` returns nothing after the final release.
+ - `npm ci` succeeds in CI without Ionic Enterprise registry credentials.
+
## Error Handling
- - For storage migrations, keep encrypted data on `@capgo/capacitor-fast-sql` unless the use case is explicitly non-sensitive.
- - When OIDC behavior changes after migration, compare the before-and-after redirect and token exchange flow before shipping.
- - Reuse any existing secure native store instead of introducing a second storage model.
+ | Problem | Fix |
+ |---|---|
+ | `npm error 401 Unauthorized` / `404` for `@ionic-enterprise/*` in CI | Enterprise registry token expired; finish removal or keep the token until release N+1 |
+ | Users logged out after update | Data not carried over; ship the dual-plugin release N first |
+ | `redirect_uri_mismatch` / IdP error after switching | Register the new redirect URL with the IdP; keep scopes identical |
+ | `Encryption is not available in this build` | Add the SQLCipher dependency/subspec, rebuild |
+ | Fast SQL calls fail with network errors | Missing ATS local networking / Android cleartext config for localhost |
+ | Biometric read fails after enrollment change | Expected with `BIOMETRY_CURRENT_SET`; re-authenticate and save again |