capacitor-oidc 0.0.1-alpha.1 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CapacitorOidc.podspec +1 -1
  2. package/Package.swift +1 -1
  3. package/README.md +66 -62
  4. package/SECURITY.md +60 -0
  5. package/android/build.gradle +1 -1
  6. package/android/src/main/java/com/jojopirker/capacitor/oidc/CapacitorOidcPlugin.java +33 -27
  7. package/contracts/fixtures/stored-session-v1.json +11 -0
  8. package/contracts/stored-session-v1.schema.json +42 -0
  9. package/dist/esm/capacitor-navigator.js +14 -12
  10. package/dist/esm/capacitor-navigator.js.map +1 -1
  11. package/dist/esm/capacitor-secure-state-store.js +4 -20
  12. package/dist/esm/capacitor-secure-state-store.js.map +1 -1
  13. package/dist/esm/capacitor-user-manager.js +8 -13
  14. package/dist/esm/capacitor-user-manager.js.map +1 -1
  15. package/dist/esm/definitions.d.ts +3 -6
  16. package/dist/esm/definitions.js.map +1 -1
  17. package/dist/esm/errors.js +1 -2
  18. package/dist/esm/errors.js.map +1 -1
  19. package/dist/esm/native.js +1 -2
  20. package/dist/esm/native.js.map +1 -1
  21. package/dist/plugin.cjs +28 -64
  22. package/dist/plugin.cjs.map +1 -1
  23. package/docs/API.md +91 -0
  24. package/docs/GETTING_STARTED.md +132 -0
  25. package/docs/PLATFORM_SETUP.md +98 -0
  26. package/docs/PROVIDERS.md +184 -0
  27. package/docs/PUBLISHING.md +90 -0
  28. package/docs/README.md +23 -0
  29. package/docs/SESSIONS_AND_WIDGETS.md +82 -0
  30. package/docs/TESTING.md +60 -0
  31. package/docs/TROUBLESHOOTING.md +67 -0
  32. package/docs/adr/0001-use-oidc-client-ts.md +22 -0
  33. package/docs/adr/0002-keep-the-native-boundary-small.md +16 -0
  34. package/docs/adr/0003-share-session-storage-with-widgets.md +20 -0
  35. package/ios/Sources/CapacitorOidcPlugin/CapacitorOidcPlugin.swift +52 -43
  36. package/package.json +14 -14
  37. package/android/src/main/java/com/jojopirker/capacitor/oidc/NativeContract.java +0 -35
  38. package/dist/esm/generated/native-contract.d.ts +0 -37
  39. package/dist/esm/generated/native-contract.js +0 -38
  40. package/dist/esm/generated/native-contract.js.map +0 -1
  41. package/ios/Sources/CapacitorOidcPlugin/NativeContract.generated.swift +0 -39
@@ -13,6 +13,6 @@ Pod::Spec.new do |spec|
13
13
  spec.source = { git: repository_url, tag: spec.version.to_s }
14
14
  spec.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
15
15
  spec.ios.deployment_target = '15.0'
16
- spec.dependency 'Capacitor'
16
+ spec.dependency 'Capacitor', '>= 7.0'
17
17
  spec.swift_version = '5.9'
18
18
  end
package/Package.swift CHANGED
@@ -8,7 +8,7 @@ let package = Package(
8
8
  .library(name: "CapacitorOidc", targets: ["CapacitorOidcPlugin"])
9
9
  ],
10
10
  dependencies: [
11
- .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "8.0.0")
11
+ .package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", "7.0.0"..<"9.0.0")
12
12
  ],
13
13
  targets: [
14
14
  .target(
package/README.md CHANGED
@@ -1,30 +1,49 @@
1
1
  # capacitor-oidc
2
2
 
3
- A small native Capacitor adapter for [`oidc-client-ts`](https://github.com/authts/oidc-client-ts).
3
+ [![npm](https://img.shields.io/npm/v/capacitor-oidc)](https://www.npmjs.com/package/capacitor-oidc)
4
+ [![CI](https://github.com/jojopirker/capacitor-oidc/actions/workflows/ci.yml/badge.svg)](https://github.com/jojopirker/capacitor-oidc/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/npm/l/capacitor-oidc)](LICENSE)
4
6
 
5
- > [!WARNING]
6
- > This package is not ready for production use. `oidc-client-ts` 3.5.0 does not validate the required ID-token `iss`, `aud`, and `exp` claims. See [Security](SECURITY.md).
7
+ Native OAuth 2.0 and OpenID Connect for Capacitor, powered by
8
+ [`oidc-client-ts`](https://github.com/authts/oidc-client-ts).
7
9
 
8
- The package keeps OAuth and OpenID Connect in `oidc-client-ts`. Its native code only presents system authentication UI and stores state securely:
10
+ `capacitor-oidc` adapts the familiar `UserManager` API to native iOS and Android
11
+ applications. It keeps protocol behavior in `oidc-client-ts` and adds only the
12
+ Capacitor-specific pieces:
9
13
 
10
- - iOS: `ASWebAuthenticationSession` and Keychain.
11
- - Android: Auth Tab with its Custom Tab fallback, plus AES-GCM protected storage with a key held by Android Keystore.
12
- - TypeScript: a native `INavigator`, secure `StateStore`, foreground refresh serialization, and a resume check.
14
+ - system authentication UI instead of an embedded WebView;
15
+ - secure native storage for OIDC transactions and sessions;
16
+ - refresh-token renewal when the app is active or resumes;
17
+ - a native-readable session snapshot for app widgets.
13
18
 
14
- It does not patch `fetch`, add native OIDC networking, accept client secrets, render authentication in a WebView, or implement iframe renewal.
19
+ On iOS, authentication uses `ASWebAuthenticationSession`. On Android, it uses
20
+ AndroidX Auth Tab with its Custom Tab fallback.
21
+
22
+ > [!CAUTION]
23
+ > This package is an alpha. The public API and stored-session format can still
24
+ > change before v1. See [Security](SECURITY.md) and
25
+ > [current test coverage](docs/TESTING.md) before making a production decision.
26
+
27
+ ## Requirements
28
+
29
+ - Capacitor 7 or 8
30
+ - iOS 15 or newer
31
+ - Android API 24 or newer
32
+ - Android compile SDK 36, Java 21, and a compatible Android Gradle Plugin
33
+ - an OAuth public client using Authorization Code Flow with PKCE
34
+ - Web Crypto in the packaged Capacitor WebView
35
+ - CORS support for the app's Capacitor origin on OIDC HTTP endpoints
36
+
37
+ Never ship a client secret in a Capacitor application.
15
38
 
16
39
  ## Install
17
40
 
18
41
  ```sh
19
- npm install capacitor-oidc oidc-client-ts @capacitor/app
42
+ npm install capacitor-oidc @capacitor/app
20
43
  npx cap sync
21
44
  ```
22
45
 
23
- All discovery, token, refresh, UserInfo, and revocation requests use normal WebView `fetch`. The provider must allow the app's configured Capacitor origin through CORS.
24
-
25
- Authorization and logout endpoints must use HTTPS. Plain HTTP is accepted only for loopback local development.
26
-
27
- ## Usage
46
+ ## Quick start
28
47
 
29
48
  ```ts
30
49
  import { CapacitorUserManager } from 'capacitor-oidc';
@@ -41,69 +60,54 @@ const manager = await CapacitorUserManager.create(
41
60
  },
42
61
  {
43
62
  storageNamespace: 'primary',
44
- ios: {
45
- keychainAccessGroup: 'TEAMID.group.com.example.app',
46
- keychainAccessibility: 'afterFirstUnlockThisDeviceOnly',
47
- prefersEphemeralWebBrowserSession: false,
48
- },
49
63
  },
50
64
  );
51
65
 
52
66
  const user = await manager.signin();
53
67
  const validUser = await manager.getValidUser(30);
68
+
54
69
  await manager.signout();
55
70
  await manager.dispose();
56
71
  ```
57
72
 
58
- `automaticSilentRenew` uses `oidc-client-ts`'s foreground expiry timer. Native silent renewal uses a refresh token only and never falls back to an iframe. Concurrent renewal triggers share one request. Returning to the foreground calls `getValidUser()` so a token that expired while the app was suspended is refreshed.
59
-
60
- The operating system can suspend or terminate the app, so exact background refresh timing is not promised.
61
-
62
- ## Redirect setup
63
-
64
- Register the redirect URI as a native public-client redirect at the provider. Never put a client secret in the app.
73
+ Register the redirect and post-logout redirect URIs exactly at your provider and
74
+ in the native application. The provider client must be public and must allow
75
+ Authorization Code Flow with PKCE.
65
76
 
66
- For an iOS custom scheme, add it to the application target's `CFBundleURLTypes`. HTTPS callbacks through `ASWebAuthenticationSession` require iOS 17.4 or newer and the appropriate Associated Domains configuration.
77
+ `CapacitorUserManager` is for native Capacitor runtimes. For a browser build, use
78
+ the normal `UserManager` from `oidc-client-ts` and select the implementation with
79
+ `Capacitor.isNativePlatform()` in the application.
67
80
 
68
- For Android custom-scheme fallback, add an intent filter to the app's `BridgeActivity`. HTTPS callbacks require a verified App Link and Digital Asset Links. Auth Tab handles the result directly when the installed browser supports it; its intent is intentionally compatible with Custom Tabs on older browsers.
81
+ ## Documentation
69
82
 
70
- Calling `cancel()` on Android rejects the pending JavaScript promise, but Android does not provide an API to forcibly close an already-open system Auth Tab or Custom Tab. Ephemeral browsing is a request to the installed browser and may be ignored by a fallback browser.
83
+ - [Getting started](docs/GETTING_STARTED.md)
84
+ - [iOS and Android setup](docs/PLATFORM_SETUP.md)
85
+ - [Provider configuration](docs/PROVIDERS.md)
86
+ - [API and `oidc-client-ts` compatibility](docs/API.md)
87
+ - [Sessions, secure storage, and widgets](docs/SESSIONS_AND_WIDGETS.md)
88
+ - [Troubleshooting](docs/TROUBLESHOOTING.md)
89
+ - [Testing status](docs/TESTING.md)
90
+ - [Security](SECURITY.md)
71
91
 
72
- ## Secure storage and widgets
92
+ ## Session renewal
73
93
 
74
- `userStore` and transaction `stateStore` are separate secure namespaces. Each successful user write also updates a versioned native `StoredSessionV1` snapshot. The snapshot is an eventually consistent widget cache, not the canonical OIDC session.
94
+ `automaticSilentRenew` uses the foreground expiry timer from `oidc-client-ts`.
95
+ Native silent renewal uses the refresh token and never falls back to an iframe.
96
+ Concurrent renewal triggers share one request. When the app returns to the
97
+ foreground, the manager checks whether the current user needs renewal.
75
98
 
76
- An iOS app and WidgetKit extension can construct the public `TokenVault` with the same Keychain access group:
99
+ The operating system can suspend or terminate the app, so the package does not
100
+ promise exact background refresh timing.
77
101
 
78
- ```swift
79
- let vault = TokenVault(accessGroup: "TEAMID.group.com.example.app")
80
- let session = try vault.loadSession(namespace: "primary")
81
- ```
82
-
83
- Replace `TEAMID` with the Apple Developer Team ID. Both targets must carry the same
84
- Keychain Sharing entitlement, normally declared as
85
- `$(AppIdentifierPrefix)group.com.example.app`; the runtime option uses its expanded
86
- `TEAMID.group.com.example.app` value. The default accessibility is
87
- `AfterFirstUnlockThisDeviceOnly`; Keychain synchronization and biometric gating are disabled.
88
-
89
- An Android app widget in the same package can use the public native vault:
90
-
91
- ```java
92
- TokenVault vault = new TokenVault(context);
93
- StoredSessionV1 session = vault.loadSession("primary");
94
- ```
102
+ ## Networking
95
103
 
96
- Widgets may read the current session. Autonomous native refresh is deliberately not implemented.
104
+ Discovery, token exchange, refresh, UserInfo, and revocation are performed by
105
+ `oidc-client-ts` through the unmodified WebView `fetch`. The corresponding
106
+ provider endpoints must allow the application's configured Capacitor origin
107
+ through CORS.
97
108
 
98
- ## Logout behavior
99
-
100
- `signout()` uses the provider's end-session endpoint in the same native authentication UI. If `revokeTokensOnSignout` is enabled, upstream revocation runs before local state is cleared. A revocation failure therefore preserves the local session and its renewal timer; after revocation succeeds, a later browser or callback failure leaves the app locally signed out. Removing the user cancels its expiry timer without disabling renewal for a later sign-in with the same manager.
101
-
102
- ## Unsupported APIs
103
-
104
- Use `signin()` and `signout()` for interactive flows. Redirect navigation, iframe logout, and browser session monitoring reject with `UNSUPPORTED_RUNTIME`. Resource Owner Password Credentials, DPoP, client secrets, exact background scheduling, and autonomous widget refresh are outside v1.
105
-
106
- Only one interactive native authentication session and one configured manager are supported at a time.
109
+ The package does not patch `fetch`, add native OIDC networking, accept client
110
+ secrets, or render authentication inside a WebView.
107
111
 
108
112
  ## Development
109
113
 
@@ -113,9 +117,9 @@ npm run verify:ios
113
117
  npm run verify:android
114
118
  ```
115
119
 
116
- Physical-device verification remains required for Web Crypto, system consent UI, redirects, and shared widget access before a production release. See [Testing](docs/TESTING.md) for the full matrix.
117
-
118
- See [Publishing](docs/PUBLISHING.md) for the guarded npm trusted-publishing setup and release process.
120
+ Architecture decisions and contributor constraints are documented in
121
+ [ARCHITECTURE.md](ARCHITECTURE.md), [REQUIREMENTS.md](REQUIREMENTS.md), and
122
+ [docs/adr](docs/adr).
119
123
 
120
124
  ## License
121
125
 
package/SECURITY.md ADDED
@@ -0,0 +1,60 @@
1
+ # Security
2
+
3
+ ## Design boundary
4
+
5
+ `capacitor-oidc` delegates OAuth and OpenID Connect protocol behavior to
6
+ `oidc-client-ts`. Native code is limited to presenting system authentication UI
7
+ and storing state securely. The package does not patch `fetch`, process JWTs, or
8
+ implement OAuth endpoints in Swift or Java.
9
+
10
+ Installed applications are public clients. They must use Authorization Code Flow
11
+ with PKCE and must not contain a client secret. Authorization and provider logout
12
+ run in system authentication UI, never an embedded WebView.
13
+
14
+ ## ID-token validation in `oidc-client-ts` 3.5.0
15
+
16
+ The pinned `oidc-client-ts` 3.5.0 decodes ID-token claims and validates `sub`,
17
+ `nonce`, and selected refresh-token continuity claims. It does not independently
18
+ compare the decoded `iss`, `aud`, and `exp` claims with the configured client and
19
+ current time. This behavior is visible in the
20
+ [v3.5.0 ResponseValidator](https://github.com/authts/oidc-client-ts/blob/v3.5.0/src/ResponseValidator.ts)
21
+ and is the subject of the open upstream report
22
+ [authts/oidc-client-ts#2475](https://github.com/authts/oidc-client-ts/issues/2475).
23
+
24
+ The practical exposure is narrower than an implicit-flow token parser: this
25
+ package uses Authorization Code Flow only, and the token response comes from the
26
+ configured token endpoint over TLS after state, nonce, and PKCE processing. The
27
+ upstream project has not yet classified or resolved the report.
28
+
29
+ This is a standards-conformance and threat-model consideration, not a categorical
30
+ claim that every application using `oidc-client-ts` is unsafe. Consumers should
31
+ evaluate it against their provider, reliance on ID-token claims, and assurance
32
+ requirements. Resource servers must always validate access tokens independently;
33
+ an application must not use unverified client-side profile claims as its API
34
+ authorization boundary.
35
+
36
+ The package will follow the upstream resolution and cover the expected behavior
37
+ in provider integration tests before a stable v1 decision. It will not add a
38
+ package-local JWT or cryptographic-validation layer, because duplicating protocol
39
+ security code would expand the attack surface and create a second OIDC engine.
40
+
41
+ ## Secure-storage boundary
42
+
43
+ OIDC transactions and sessions are stored through iOS Keychain or an Android
44
+ Keystore-backed vault. Configuring an iOS Keychain access group gives every
45
+ entitled target access to the plugin's canonical session, transaction data, and
46
+ widget snapshot. Treat those extensions as part of the application's credential
47
+ trust boundary.
48
+
49
+ The widget snapshot can contain access, refresh, and ID tokens. Autonomous widget
50
+ refresh is not currently implemented; see
51
+ [Sessions, secure storage, and widgets](docs/SESSIONS_AND_WIDGETS.md).
52
+
53
+ ## Runtime assumptions
54
+
55
+ `oidc-client-ts` requires `crypto.subtle` and `crypto.getRandomValues`.
56
+ `CapacitorUserManager.create()` rejects with `UNSUPPORTED_RUNTIME` when they are
57
+ absent. Their behavior must be verified in packaged applications on supported
58
+ physical devices.
59
+
60
+ See [Testing](docs/TESTING.md) for current platform and provider coverage.
@@ -14,7 +14,7 @@ buildscript {
14
14
  mavenCentral()
15
15
  }
16
16
  dependencies {
17
- classpath 'com.android.tools.build:gradle:8.13.0'
17
+ classpath 'com.android.tools.build:gradle:8.9.1'
18
18
  }
19
19
  }
20
20
 
@@ -16,9 +16,15 @@ import java.security.GeneralSecurityException;
16
16
  import java.util.List;
17
17
  import org.json.JSONObject;
18
18
 
19
- @CapacitorPlugin(name = NativeContract.PLUGIN_NAME)
19
+ @CapacitorPlugin(name = "CapacitorOidc")
20
20
  public final class CapacitorOidcPlugin extends Plugin {
21
21
 
22
+ private static final String AUTH_SESSION_IN_PROGRESS = "AUTH_SESSION_IN_PROGRESS";
23
+ private static final String USER_CANCELLED = "USER_CANCELLED";
24
+ private static final String BROWSER_UNAVAILABLE = "BROWSER_UNAVAILABLE";
25
+ private static final String INVALID_CALLBACK = "INVALID_CALLBACK";
26
+ private static final String SECURE_STORAGE_ERROR = "SECURE_STORAGE_ERROR";
27
+
22
28
  private ActivityResultLauncher<Intent> authLauncher;
23
29
  private PluginCall pendingAuthCall;
24
30
  private Uri pendingCallback;
@@ -38,26 +44,26 @@ public final class CapacitorOidcPlugin extends Plugin {
38
44
  @PluginMethod
39
45
  public void open(PluginCall call) {
40
46
  if (pendingAuthCall != null) {
41
- call.reject("An authentication session is already active.", NativeContract.ERROR_AUTH_SESSION_IN_PROGRESS);
47
+ call.reject("An authentication session is already active.", AUTH_SESSION_IN_PROGRESS);
42
48
  return;
43
49
  }
44
50
 
45
- String urlValue = requiredString(call, NativeContract.FIELD_URL);
46
- String callbackValue = requiredString(call, NativeContract.FIELD_CALLBACK_URL);
51
+ String urlValue = requiredString(call, "url");
52
+ String callbackValue = requiredString(call, "callbackUrl");
47
53
  if (urlValue == null || callbackValue == null) return;
48
54
 
49
55
  Uri url = Uri.parse(urlValue);
50
56
  Uri callback = Uri.parse(callbackValue);
51
57
  if (!isSecureRequestUrl(url)) {
52
- call.reject("The authentication URL must use HTTPS outside loopback development.", NativeContract.ERROR_BROWSER_UNAVAILABLE);
58
+ call.reject("The authentication URL must use HTTPS outside loopback development.", BROWSER_UNAVAILABLE);
53
59
  return;
54
60
  }
55
61
  if (!isSupportedCallback(callback)) {
56
- call.reject("The callback URL must use HTTPS or a custom scheme.", NativeContract.ERROR_INVALID_CALLBACK);
62
+ call.reject("The callback URL must use HTTPS or a custom scheme.", INVALID_CALLBACK);
57
63
  return;
58
64
  }
59
65
 
60
- boolean ephemeral = Boolean.TRUE.equals(call.getBoolean(NativeContract.FIELD_PREFERS_EPHEMERAL_WEB_BROWSER_SESSION, false));
66
+ boolean ephemeral = Boolean.TRUE.equals(call.getBoolean("prefersEphemeralWebBrowserSession", false));
61
67
  AuthTabIntent authTab = new AuthTabIntent.Builder().setEphemeralBrowsingEnabled(ephemeral).build();
62
68
  pendingAuthCall = call;
63
69
  pendingCallback = callback;
@@ -70,7 +76,7 @@ public final class CapacitorOidcPlugin extends Plugin {
70
76
  }
71
77
  } catch (ActivityNotFoundException | IllegalStateException error) {
72
78
  clearPendingAuth();
73
- call.reject("No compatible system browser is available.", NativeContract.ERROR_BROWSER_UNAVAILABLE);
79
+ call.reject("No compatible system browser is available.", BROWSER_UNAVAILABLE);
74
80
  }
75
81
  }
76
82
 
@@ -78,7 +84,7 @@ public final class CapacitorOidcPlugin extends Plugin {
78
84
  public void cancel(PluginCall call) {
79
85
  PluginCall authCall = pendingAuthCall;
80
86
  clearPendingAuth();
81
- if (authCall != null) authCall.reject("The authentication session was cancelled.", NativeContract.ERROR_USER_CANCELLED);
87
+ if (authCall != null) authCall.reject("The authentication session was cancelled.", USER_CANCELLED);
82
88
  call.resolve();
83
89
  }
84
90
 
@@ -90,15 +96,15 @@ public final class CapacitorOidcPlugin extends Plugin {
90
96
 
91
97
  clearPendingAuth();
92
98
  JSObject response = new JSObject();
93
- response.put(NativeContract.FIELD_URL, callback.toString());
99
+ response.put("url", callback.toString());
94
100
  call.resolve(response);
95
101
  }
96
102
 
97
103
  @PluginMethod
98
104
  public void storageSet(PluginCall call) {
99
- String namespace = requiredString(call, NativeContract.FIELD_NAMESPACE);
100
- String key = requiredString(call, NativeContract.FIELD_KEY);
101
- String value = call.getString(NativeContract.FIELD_VALUE);
105
+ String namespace = requiredString(call, "namespace");
106
+ String key = requiredString(call, "key");
107
+ String value = call.getString("value");
102
108
  if (namespace == null || key == null) return;
103
109
  if (value == null) {
104
110
  call.reject("value is required.");
@@ -115,8 +121,8 @@ public final class CapacitorOidcPlugin extends Plugin {
115
121
 
116
122
  @PluginMethod
117
123
  public void storageGet(PluginCall call) {
118
- String namespace = requiredString(call, NativeContract.FIELD_NAMESPACE);
119
- String key = requiredString(call, NativeContract.FIELD_KEY);
124
+ String namespace = requiredString(call, "namespace");
125
+ String key = requiredString(call, "key");
120
126
  if (namespace == null || key == null) return;
121
127
 
122
128
  try {
@@ -128,8 +134,8 @@ public final class CapacitorOidcPlugin extends Plugin {
128
134
 
129
135
  @PluginMethod
130
136
  public void storageRemove(PluginCall call) {
131
- String namespace = requiredString(call, NativeContract.FIELD_NAMESPACE);
132
- String key = requiredString(call, NativeContract.FIELD_KEY);
137
+ String namespace = requiredString(call, "namespace");
138
+ String key = requiredString(call, "key");
133
139
  if (namespace == null || key == null) return;
134
140
 
135
141
  try {
@@ -141,13 +147,13 @@ public final class CapacitorOidcPlugin extends Plugin {
141
147
 
142
148
  @PluginMethod
143
149
  public void storageGetAllKeys(PluginCall call) {
144
- String namespace = requiredString(call, NativeContract.FIELD_NAMESPACE);
150
+ String namespace = requiredString(call, "namespace");
145
151
  if (namespace == null) return;
146
152
 
147
153
  try {
148
154
  List<String> keys = vault.getAllKeys(namespace);
149
155
  JSObject result = new JSObject();
150
- result.put(NativeContract.FIELD_KEYS, new JSArray(keys));
156
+ result.put("keys", new JSArray(keys));
151
157
  call.resolve(result);
152
158
  } catch (GeneralSecurityException | IOException error) {
153
159
  rejectStorage(call);
@@ -156,11 +162,11 @@ public final class CapacitorOidcPlugin extends Plugin {
156
162
 
157
163
  @PluginMethod
158
164
  public void setSessionSnapshot(PluginCall call) {
159
- String namespace = requiredString(call, NativeContract.FIELD_NAMESPACE);
165
+ String namespace = requiredString(call, "namespace");
160
166
  if (namespace == null) return;
161
167
 
162
168
  try {
163
- vault.setSessionSnapshot(namespace, call.getString(NativeContract.FIELD_VALUE));
169
+ vault.setSessionSnapshot(namespace, call.getString("value"));
164
170
  call.resolve();
165
171
  } catch (GeneralSecurityException | IOException error) {
166
172
  rejectStorage(call);
@@ -174,20 +180,20 @@ public final class CapacitorOidcPlugin extends Plugin {
174
180
  if (call == null) return;
175
181
 
176
182
  if (result.resultCode == AuthTabIntent.RESULT_CANCELED) {
177
- call.reject("The authentication session was cancelled.", NativeContract.ERROR_USER_CANCELLED);
183
+ call.reject("The authentication session was cancelled.", USER_CANCELLED);
178
184
  return;
179
185
  }
180
186
  if (result.resultCode != AuthTabIntent.RESULT_OK || result.resultUri == null) {
181
- call.reject("The browser did not return a valid callback.", NativeContract.ERROR_INVALID_CALLBACK);
187
+ call.reject("The browser did not return a valid callback.", INVALID_CALLBACK);
182
188
  return;
183
189
  }
184
190
  if (!CallbackUriMatcher.matches(result.resultUri, expectedCallback)) {
185
- call.reject("The authentication callback does not match the configured redirect URL.", NativeContract.ERROR_INVALID_CALLBACK);
191
+ call.reject("The authentication callback does not match the configured redirect URL.", INVALID_CALLBACK);
186
192
  return;
187
193
  }
188
194
 
189
195
  JSObject response = new JSObject();
190
- response.put(NativeContract.FIELD_URL, result.resultUri.toString());
196
+ response.put("url", result.resultUri.toString());
191
197
  call.resolve(response);
192
198
  }
193
199
 
@@ -230,11 +236,11 @@ public final class CapacitorOidcPlugin extends Plugin {
230
236
 
231
237
  private static void resolveValue(PluginCall call, String value) {
232
238
  JSObject result = new JSObject();
233
- result.put(NativeContract.FIELD_VALUE, value == null ? JSONObject.NULL : value);
239
+ result.put("value", value == null ? JSONObject.NULL : value);
234
240
  call.resolve(result);
235
241
  }
236
242
 
237
243
  private static void rejectStorage(PluginCall call) {
238
- call.reject("Secure storage failed.", NativeContract.ERROR_SECURE_STORAGE_ERROR);
244
+ call.reject("Secure storage failed.", SECURE_STORAGE_ERROR);
239
245
  }
240
246
  }
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 1,
3
+ "issuer": "https://issuer.example",
4
+ "clientId": "mobile",
5
+ "accessToken": "access",
6
+ "refreshToken": "refresh",
7
+ "idToken": "id-token",
8
+ "tokenType": "Bearer",
9
+ "scope": "openid profile offline_access",
10
+ "expiresAt": 1800000000
11
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/jojopirker/capacitor-oidc/contracts/stored-session-v1.schema.json",
4
+ "title": "StoredSessionV1",
5
+ "type": "object",
6
+ "additionalProperties": false,
7
+ "required": ["version", "issuer", "clientId", "accessToken", "tokenType"],
8
+ "properties": {
9
+ "version": {
10
+ "const": 1
11
+ },
12
+ "issuer": {
13
+ "type": "string",
14
+ "format": "uri"
15
+ },
16
+ "clientId": {
17
+ "type": "string",
18
+ "minLength": 1
19
+ },
20
+ "accessToken": {
21
+ "type": "string",
22
+ "minLength": 1
23
+ },
24
+ "refreshToken": {
25
+ "type": "string"
26
+ },
27
+ "idToken": {
28
+ "type": "string"
29
+ },
30
+ "tokenType": {
31
+ "type": "string",
32
+ "minLength": 1
33
+ },
34
+ "scope": {
35
+ "type": "string"
36
+ },
37
+ "expiresAt": {
38
+ "type": "integer",
39
+ "minimum": 0
40
+ }
41
+ }
42
+ }
@@ -1,5 +1,4 @@
1
1
  import { CapacitorOidcError, unsupported } from './errors';
2
- import { nativeContract } from './generated/native-contract';
3
2
  import { NativeOidc } from './native';
4
3
  export class CapacitorNavigator {
5
4
  prefersEphemeralWebBrowserSession;
@@ -22,14 +21,14 @@ class CapacitorWindow {
22
21
  assertSecureRequestUrl(url);
23
22
  const callbackUrl = callbackUrlFromRequest(url);
24
23
  const response = await NativeOidc.open({
25
- [nativeContract.fields.url]: url,
26
- [nativeContract.fields.callbackUrl]: callbackUrl,
27
- [nativeContract.fields.prefersEphemeralWebBrowserSession]: this.prefersEphemeralWebBrowserSession,
24
+ url,
25
+ callbackUrl,
26
+ prefersEphemeralWebBrowserSession: this.prefersEphemeralWebBrowserSession,
28
27
  });
29
- if (!isExpectedCallback(response[nativeContract.fields.url], callbackUrl)) {
30
- throw new CapacitorOidcError(nativeContract.errorCodes.invalidCallback, 'The authentication callback does not match the configured redirect URI');
28
+ if (!isExpectedCallback(response.url, callbackUrl)) {
29
+ throw new CapacitorOidcError('INVALID_CALLBACK', 'The authentication callback does not match the configured redirect URI');
31
30
  }
32
- return { url: response[nativeContract.fields.url] };
31
+ return response;
33
32
  }
34
33
  close() {
35
34
  void NativeOidc.cancel();
@@ -37,16 +36,19 @@ class CapacitorWindow {
37
36
  }
38
37
  export function assertSecureRequestUrl(requestUrl) {
39
38
  const url = new URL(requestUrl);
40
- const isLocalDevelopment = url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]';
41
- if (url.protocol !== 'https:' && !isLocalDevelopment) {
42
- throw new CapacitorOidcError(nativeContract.errorCodes.browserUnavailable, 'OIDC authorization and logout endpoints must use HTTPS');
39
+ const isHttpLoopback = url.protocol === 'http:' &&
40
+ (url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]');
41
+ if (url.protocol !== 'https:' && !isHttpLoopback) {
42
+ throw new CapacitorOidcError('BROWSER_UNAVAILABLE', 'OIDC authorization and logout endpoints must use HTTPS');
43
43
  }
44
44
  }
45
45
  export function callbackUrlFromRequest(requestUrl) {
46
46
  const url = new URL(requestUrl);
47
- const callback = url.searchParams.get('redirect_uri') ?? url.searchParams.get('post_logout_redirect_uri');
47
+ const callback = url.searchParams.get('post_logout_redirect_uri') ??
48
+ url.searchParams.get('logout_uri') ??
49
+ url.searchParams.get('redirect_uri');
48
50
  if (!callback) {
49
- throw new CapacitorOidcError(nativeContract.errorCodes.invalidCallback, 'The OIDC request does not contain a redirect URI');
51
+ throw new CapacitorOidcError('INVALID_CALLBACK', 'The OIDC request does not contain a callback URI');
50
52
  }
51
53
  return callback;
52
54
  }
@@ -1 +1 @@
1
- {"version":3,"file":"capacitor-navigator.js","sourceRoot":"","sources":["../../src/capacitor-navigator.ts"],"names":[],"mappings":"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","sourcesContent":["import type { INavigator, IWindow, NavigateParams, NavigateResponse } from 'oidc-client-ts';\n\nimport { CapacitorOidcError, unsupported } from './errors';\nimport { nativeContract } from './generated/native-contract';\nimport { NativeOidc } from './native';\n\nexport class CapacitorNavigator implements INavigator {\n constructor(private readonly prefersEphemeralWebBrowserSession: boolean) {}\n\n async prepare(): Promise<IWindow> {\n return new CapacitorWindow(this.prefersEphemeralWebBrowserSession);\n }\n\n async callback(): Promise<void> {\n unsupported('Navigator callbacks');\n }\n}\n\nclass CapacitorWindow implements IWindow {\n constructor(private readonly prefersEphemeralWebBrowserSession: boolean) {}\n\n async navigate({ url }: NavigateParams): Promise<NavigateResponse> {\n assertSecureRequestUrl(url);\n const callbackUrl = callbackUrlFromRequest(url);\n const response = await NativeOidc.open({\n [nativeContract.fields.url]: url,\n [nativeContract.fields.callbackUrl]: callbackUrl,\n [nativeContract.fields.prefersEphemeralWebBrowserSession]: this.prefersEphemeralWebBrowserSession,\n });\n\n if (!isExpectedCallback(response[nativeContract.fields.url], callbackUrl)) {\n throw new CapacitorOidcError(\n nativeContract.errorCodes.invalidCallback,\n 'The authentication callback does not match the configured redirect URI',\n );\n }\n\n return { url: response[nativeContract.fields.url] };\n }\n\n close(): void {\n void NativeOidc.cancel();\n }\n}\n\nexport function assertSecureRequestUrl(requestUrl: string): void {\n const url = new URL(requestUrl);\n const isLocalDevelopment = url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]';\n if (url.protocol !== 'https:' && !isLocalDevelopment) {\n throw new CapacitorOidcError(\n nativeContract.errorCodes.browserUnavailable,\n 'OIDC authorization and logout endpoints must use HTTPS',\n );\n }\n}\n\nexport function callbackUrlFromRequest(requestUrl: string): string {\n const url = new URL(requestUrl);\n const callback = url.searchParams.get('redirect_uri') ?? url.searchParams.get('post_logout_redirect_uri');\n if (!callback) {\n throw new CapacitorOidcError(\n nativeContract.errorCodes.invalidCallback,\n 'The OIDC request does not contain a redirect URI',\n );\n }\n return callback;\n}\n\nexport function isExpectedCallback(actualValue: string, expectedValue: string): boolean {\n const actual = new URL(actualValue);\n const expected = new URL(expectedValue);\n return (\n actual.protocol.toLowerCase() === expected.protocol.toLowerCase() &&\n actual.host.toLowerCase() === expected.host.toLowerCase() &&\n actual.pathname === expected.pathname\n );\n}\n\nexport class UnsupportedIframeNavigator implements INavigator {\n async prepare(): Promise<IWindow> {\n unsupported('Iframe navigation');\n }\n\n async callback(): Promise<void> {\n unsupported('Iframe navigation');\n }\n}\n"]}
1
+ {"version":3,"file":"capacitor-navigator.js","sourceRoot":"","sources":["../../src/capacitor-navigator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,OAAO,kBAAkB;IACA;IAA7B,YAA6B,iCAA0C;QAA1C,sCAAiC,GAAjC,iCAAiC,CAAS;IAAG,CAAC;IAE3E,KAAK,CAAC,OAAO;QACX,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IACrE,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,WAAW,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;CACF;AAED,MAAM,eAAe;IACU;IAA7B,YAA6B,iCAA0C;QAA1C,sCAAiC,GAAjC,iCAAiC,CAAS;IAAG,CAAC;IAE3E,KAAK,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAkB;QACpC,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,WAAW,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC;YACrC,GAAG;YACH,WAAW;YACX,iCAAiC,EAAE,IAAI,CAAC,iCAAiC;SAC1E,CAAC,CAAC;QAEH,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,EAAE,CAAC;YACnD,MAAM,IAAI,kBAAkB,CAC1B,kBAAkB,EAClB,wEAAwE,CACzE,CAAC;QACJ,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK;QACH,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;IAC3B,CAAC;CACF;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,cAAc,GAClB,GAAG,CAAC,QAAQ,KAAK,OAAO;QACxB,CAAC,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,WAAW,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAC7F,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,cAAc,EAAE,CAAC;QACjD,MAAM,IAAI,kBAAkB,CAAC,qBAAqB,EAAE,wDAAwD,CAAC,CAAC;IAChH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IAChC,MAAM,QAAQ,GACZ,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,0BAA0B,CAAC;QAChD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC;QAClC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACvC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,kBAAkB,CAAC,kBAAkB,EAAE,kDAAkD,CAAC,CAAC;IACvG,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,aAAqB;IAC3E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IACpC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;IACxC,OAAO,CACL,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE;QACjE,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,IAAI,CAAC,WAAW,EAAE;QACzD,MAAM,CAAC,QAAQ,KAAK,QAAQ,CAAC,QAAQ,CACtC,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,0BAA0B;IACrC,KAAK,CAAC,OAAO;QACX,WAAW,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,WAAW,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;CACF","sourcesContent":["import type { INavigator, IWindow, NavigateParams, NavigateResponse } from 'oidc-client-ts';\n\nimport { CapacitorOidcError, unsupported } from './errors';\nimport { NativeOidc } from './native';\n\nexport class CapacitorNavigator implements INavigator {\n constructor(private readonly prefersEphemeralWebBrowserSession: boolean) {}\n\n async prepare(): Promise<IWindow> {\n return new CapacitorWindow(this.prefersEphemeralWebBrowserSession);\n }\n\n async callback(): Promise<void> {\n unsupported('Navigator callbacks');\n }\n}\n\nclass CapacitorWindow implements IWindow {\n constructor(private readonly prefersEphemeralWebBrowserSession: boolean) {}\n\n async navigate({ url }: NavigateParams): Promise<NavigateResponse> {\n assertSecureRequestUrl(url);\n const callbackUrl = callbackUrlFromRequest(url);\n const response = await NativeOidc.open({\n url,\n callbackUrl,\n prefersEphemeralWebBrowserSession: this.prefersEphemeralWebBrowserSession,\n });\n\n if (!isExpectedCallback(response.url, callbackUrl)) {\n throw new CapacitorOidcError(\n 'INVALID_CALLBACK',\n 'The authentication callback does not match the configured redirect URI',\n );\n }\n\n return response;\n }\n\n close(): void {\n void NativeOidc.cancel();\n }\n}\n\nexport function assertSecureRequestUrl(requestUrl: string): void {\n const url = new URL(requestUrl);\n const isHttpLoopback =\n url.protocol === 'http:' &&\n (url.hostname === 'localhost' || url.hostname === '127.0.0.1' || url.hostname === '[::1]');\n if (url.protocol !== 'https:' && !isHttpLoopback) {\n throw new CapacitorOidcError('BROWSER_UNAVAILABLE', 'OIDC authorization and logout endpoints must use HTTPS');\n }\n}\n\nexport function callbackUrlFromRequest(requestUrl: string): string {\n const url = new URL(requestUrl);\n const callback =\n url.searchParams.get('post_logout_redirect_uri') ??\n url.searchParams.get('logout_uri') ??\n url.searchParams.get('redirect_uri');\n if (!callback) {\n throw new CapacitorOidcError('INVALID_CALLBACK', 'The OIDC request does not contain a callback URI');\n }\n return callback;\n}\n\nexport function isExpectedCallback(actualValue: string, expectedValue: string): boolean {\n const actual = new URL(actualValue);\n const expected = new URL(expectedValue);\n return (\n actual.protocol.toLowerCase() === expected.protocol.toLowerCase() &&\n actual.host.toLowerCase() === expected.host.toLowerCase() &&\n actual.pathname === expected.pathname\n );\n}\n\nexport class UnsupportedIframeNavigator implements INavigator {\n async prepare(): Promise<IWindow> {\n unsupported('Iframe navigation');\n }\n\n async callback(): Promise<void> {\n unsupported('Iframe navigation');\n }\n}\n"]}
@@ -1,4 +1,3 @@
1
- import { nativeContract } from './generated/native-contract';
2
1
  import { NativeOidc } from './native';
3
2
  export class CapacitorSecureStateStore {
4
3
  namespace;
@@ -6,31 +5,16 @@ export class CapacitorSecureStateStore {
6
5
  this.namespace = namespace;
7
6
  }
8
7
  async set(key, value) {
9
- await NativeOidc.storageSet({
10
- [nativeContract.fields.namespace]: this.namespace,
11
- [nativeContract.fields.key]: key,
12
- [nativeContract.fields.value]: value,
13
- });
8
+ await NativeOidc.storageSet({ namespace: this.namespace, key, value });
14
9
  }
15
10
  async get(key) {
16
- const result = await NativeOidc.storageGet({
17
- [nativeContract.fields.namespace]: this.namespace,
18
- [nativeContract.fields.key]: key,
19
- });
20
- return result[nativeContract.fields.value];
11
+ return (await NativeOidc.storageGet({ namespace: this.namespace, key })).value;
21
12
  }
22
13
  async remove(key) {
23
- const result = await NativeOidc.storageRemove({
24
- [nativeContract.fields.namespace]: this.namespace,
25
- [nativeContract.fields.key]: key,
26
- });
27
- return result[nativeContract.fields.value];
14
+ return (await NativeOidc.storageRemove({ namespace: this.namespace, key })).value;
28
15
  }
29
16
  async getAllKeys() {
30
- const result = await NativeOidc.storageGetAllKeys({
31
- [nativeContract.fields.namespace]: this.namespace,
32
- });
33
- return result[nativeContract.fields.keys];
17
+ return (await NativeOidc.storageGetAllKeys({ namespace: this.namespace })).keys;
34
18
  }
35
19
  }
36
20
  //# sourceMappingURL=capacitor-secure-state-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"capacitor-secure-state-store.js","sourceRoot":"","sources":["../../src/capacitor-secure-state-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,OAAO,yBAAyB;IACP;IAA7B,YAA6B,SAAiB;QAAjB,cAAS,GAAT,SAAS,CAAQ;IAAG,CAAC;IAElD,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,MAAM,UAAU,CAAC,UAAU,CAAC;YAC1B,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS;YACjD,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG;YAChC,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK;SACrC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC;YACzC,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS;YACjD,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG;SACjC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,aAAa,CAAC;YAC5C,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS;YACjD,CAAC,cAAc,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG;SACjC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC7C,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,iBAAiB,CAAC;YAChD,CAAC,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS;SAClD,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;CACF","sourcesContent":["import type { StateStore } from 'oidc-client-ts';\n\nimport { nativeContract } from './generated/native-contract';\nimport { NativeOidc } from './native';\n\nexport class CapacitorSecureStateStore implements StateStore {\n constructor(private readonly namespace: string) {}\n\n async set(key: string, value: string): Promise<void> {\n await NativeOidc.storageSet({\n [nativeContract.fields.namespace]: this.namespace,\n [nativeContract.fields.key]: key,\n [nativeContract.fields.value]: value,\n });\n }\n\n async get(key: string): Promise<string | null> {\n const result = await NativeOidc.storageGet({\n [nativeContract.fields.namespace]: this.namespace,\n [nativeContract.fields.key]: key,\n });\n return result[nativeContract.fields.value];\n }\n\n async remove(key: string): Promise<string | null> {\n const result = await NativeOidc.storageRemove({\n [nativeContract.fields.namespace]: this.namespace,\n [nativeContract.fields.key]: key,\n });\n return result[nativeContract.fields.value];\n }\n\n async getAllKeys(): Promise<string[]> {\n const result = await NativeOidc.storageGetAllKeys({\n [nativeContract.fields.namespace]: this.namespace,\n });\n return result[nativeContract.fields.keys];\n }\n}\n"]}
1
+ {"version":3,"file":"capacitor-secure-state-store.js","sourceRoot":"","sources":["../../src/capacitor-secure-state-store.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,OAAO,yBAAyB;IACP;IAA7B,YAA6B,SAAiB;QAAjB,cAAS,GAAT,SAAS,CAAQ;IAAG,CAAC;IAElD,KAAK,CAAC,GAAG,CAAC,GAAW,EAAE,KAAa;QAClC,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,GAAW;QACnB,OAAO,CAAC,MAAM,UAAU,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACjF,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,GAAW;QACtB,OAAO,CAAC,MAAM,UAAU,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;IACpF,CAAC;IAED,KAAK,CAAC,UAAU;QACd,OAAO,CAAC,MAAM,UAAU,CAAC,iBAAiB,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAClF,CAAC;CACF","sourcesContent":["import type { StateStore } from 'oidc-client-ts';\n\nimport { NativeOidc } from './native';\n\nexport class CapacitorSecureStateStore implements StateStore {\n constructor(private readonly namespace: string) {}\n\n async set(key: string, value: string): Promise<void> {\n await NativeOidc.storageSet({ namespace: this.namespace, key, value });\n }\n\n async get(key: string): Promise<string | null> {\n return (await NativeOidc.storageGet({ namespace: this.namespace, key })).value;\n }\n\n async remove(key: string): Promise<string | null> {\n return (await NativeOidc.storageRemove({ namespace: this.namespace, key })).value;\n }\n\n async getAllKeys(): Promise<string[]> {\n return (await NativeOidc.storageGetAllKeys({ namespace: this.namespace })).keys;\n }\n}\n"]}