capacitor-oidc 0.0.1-alpha.0 → 0.0.1-alpha.2

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 (34) hide show
  1. package/CapacitorOidc.podspec +3 -2
  2. package/Package.swift +1 -1
  3. package/README.md +31 -3
  4. package/SECURITY.md +31 -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/PUBLISHING.md +86 -0
  24. package/docs/TESTING.md +47 -0
  25. package/docs/adr/0001-use-oidc-client-ts.md +22 -0
  26. package/docs/adr/0002-keep-the-native-boundary-small.md +16 -0
  27. package/docs/adr/0003-share-session-storage-with-widgets.md +20 -0
  28. package/ios/Sources/CapacitorOidcPlugin/CapacitorOidcPlugin.swift +52 -43
  29. package/package.json +13 -12
  30. package/android/src/main/java/com/jojopirker/capacitor/oidc/NativeContract.java +0 -35
  31. package/dist/esm/generated/native-contract.d.ts +0 -37
  32. package/dist/esm/generated/native-contract.js +0 -38
  33. package/dist/esm/generated/native-contract.js.map +0 -1
  34. package/ios/Sources/CapacitorOidcPlugin/NativeContract.generated.swift +0 -39
@@ -1,6 +1,7 @@
1
1
  require 'json'
2
2
 
3
3
  package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+ repository_url = package['repository']['url'].sub(/\Agit\+/, '')
4
5
 
5
6
  Pod::Spec.new do |spec|
6
7
  spec.name = 'CapacitorOidc'
@@ -9,9 +10,9 @@ Pod::Spec.new do |spec|
9
10
  spec.license = package['license']
10
11
  spec.homepage = package['homepage']
11
12
  spec.author = package['author']
12
- spec.source = { git: package['repository']['url'], tag: spec.version.to_s }
13
+ spec.source = { git: repository_url, tag: spec.version.to_s }
13
14
  spec.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
14
15
  spec.ios.deployment_target = '15.0'
15
- spec.dependency 'Capacitor'
16
+ spec.dependency 'Capacitor', '>= 7.0'
16
17
  spec.swift_version = '5.9'
17
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
@@ -20,6 +20,8 @@ npm install capacitor-oidc oidc-client-ts @capacitor/app
20
20
  npx cap sync
21
21
  ```
22
22
 
23
+ The package supports Capacitor 7 and newer.
24
+
23
25
  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
26
 
25
27
  Authorization and logout endpoints must use HTTPS. Plain HTTP is accepted only for loopback local development.
@@ -40,11 +42,11 @@ const manager = await CapacitorUserManager.create(
40
42
  revokeTokensOnSignout: true,
41
43
  },
42
44
  {
45
+ prefersEphemeralWebBrowserSession: false,
43
46
  storageNamespace: 'primary',
44
47
  ios: {
45
48
  keychainAccessGroup: 'TEAMID.group.com.example.app',
46
49
  keychainAccessibility: 'afterFirstUnlockThisDeviceOnly',
47
- prefersEphemeralWebBrowserSession: false,
48
50
  },
49
51
  },
50
52
  );
@@ -65,9 +67,35 @@ Register the redirect URI as a native public-client redirect at the provider. Ne
65
67
 
66
68
  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.
67
69
 
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.
70
+ For an Android custom-scheme redirect, keep the host app's `MainActivity` in Capacitor's default `singleTask` launch mode and add this intent filter inside that existing activity declaration. This ensures callbacks from Auth Tab's Custom Tab fallback reach the plugin instance that opened the session. Replace the scheme with the one used by your redirect URI:
71
+
72
+ ```xml
73
+ <activity
74
+ android:name=".MainActivity"
75
+ android:launchMode="singleTask">
76
+ <intent-filter>
77
+ <action android:name="android.intent.action.VIEW" />
78
+ <category android:name="android.intent.category.DEFAULT" />
79
+ <category android:name="android.intent.category.BROWSABLE" />
80
+ <data android:scheme="com.example.app" />
81
+ </intent-filter>
82
+ </activity>
83
+ ```
84
+
85
+ HTTPS callbacks require a verified App Link and Digital Asset Links. Auth Tab handles the result directly when the installed browser supports it and falls back to a Custom Tab on older browsers.
86
+
87
+ 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 requested on both platforms and may be ignored by an Android fallback browser.
88
+
89
+ Provider-specific logout parameters remain available through `oidc-client-ts`. For Amazon Cognito, leave `post_logout_redirect_uri` unset in the manager settings and pass its `client_id` and `logout_uri` parameters when signing out:
69
90
 
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.
91
+ ```ts
92
+ await manager.signout({
93
+ extraQueryParams: {
94
+ client_id: 'mobile-app',
95
+ logout_uri: 'com.example.app:/logout-callback',
96
+ },
97
+ });
98
+ ```
71
99
 
72
100
  ## Secure storage and widgets
73
101
 
package/SECURITY.md ADDED
@@ -0,0 +1,31 @@
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
+ ## Known limitation in the pinned OIDC engine
11
+
12
+ This prerelease pins `oidc-client-ts` 3.5.0. Its ID-token response validation
13
+ checks `sub`, `nonce`, and selected refresh-token continuity claims, but does not
14
+ check the required `iss`, `aud`, and `exp` claims. The behavior is visible in the
15
+ [v3.5.0 ResponseValidator](https://github.com/authts/oidc-client-ts/blob/v3.5.0/src/ResponseValidator.ts)
16
+ and is tracked in [authts/oidc-client-ts#2475](https://github.com/authts/oidc-client-ts/issues/2475).
17
+
18
+ The current alpha must not be treated as production-ready. Before a stable
19
+ release, use an upstream version that performs the required validation and cover
20
+ it with provider integration tests, or replace ADR 0001 with a different protocol
21
+ engine decision. Do not add package-local JWT or cryptographic validation as a
22
+ workaround.
23
+
24
+ ## Runtime assumptions
25
+
26
+ `oidc-client-ts` requires `crypto.subtle` and `crypto.getRandomValues`.
27
+ `CapacitorUserManager.create()` rejects with `UNSUPPORTED_RUNTIME` when they are
28
+ absent. Their presence and behavior must also be verified in packaged applications
29
+ on physical iOS and Android devices.
30
+
31
+ See [Testing](docs/TESTING.md) for the remaining device 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":"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","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"]}
@@ -3,7 +3,6 @@ import { ErrorResponse, UserManager, } from 'oidc-client-ts';
3
3
  import { CapacitorNavigator, UnsupportedIframeNavigator } from './capacitor-navigator';
4
4
  import { CapacitorSecureStateStore } from './capacitor-secure-state-store';
5
5
  import { CapacitorOidcError, unsupported } from './errors';
6
- import { nativeContract } from './generated/native-contract';
7
6
  import { NativeOidc } from './native';
8
7
  export class CapacitorUserManager extends UserManager {
9
8
  storageNamespace;
@@ -12,7 +11,7 @@ export class CapacitorUserManager extends UserManager {
12
11
  constructor(settings, nativeOptions, storageNamespace) {
13
12
  const stateStore = new CapacitorSecureStateStore(`${storageNamespace}.transactions`);
14
13
  const userStore = new CapacitorSecureStateStore(`${storageNamespace}.session`);
15
- const navigator = new CapacitorNavigator(nativeOptions.ios?.prefersEphemeralWebBrowserSession ?? false);
14
+ const navigator = new CapacitorNavigator(nativeOptions.prefersEphemeralWebBrowserSession ?? false);
16
15
  super({
17
16
  ...settings,
18
17
  response_type: 'code',
@@ -28,11 +27,7 @@ export class CapacitorUserManager extends UserManager {
28
27
  static async create(settings, nativeOptions = {}) {
29
28
  assertRuntime();
30
29
  assertSettings(settings);
31
- await NativeOidc.configure({
32
- [nativeContract.fields.prefersEphemeralWebBrowserSession]: nativeOptions.ios?.prefersEphemeralWebBrowserSession,
33
- [nativeContract.fields.keychainAccessGroup]: nativeOptions.ios?.keychainAccessGroup,
34
- [nativeContract.fields.keychainAccessibility]: nativeOptions.ios?.keychainAccessibility,
35
- });
30
+ await NativeOidc.configure(nativeOptions.ios ?? {});
36
31
  const manager = new CapacitorUserManager(settings, nativeOptions, nativeOptions.storageNamespace ?? 'default');
37
32
  await manager.getValidUser();
38
33
  manager.appStateListener = await App.addListener('appStateChange', ({ isActive }) => {
@@ -83,9 +78,9 @@ export class CapacitorUserManager extends UserManager {
83
78
  async storeUser(user) {
84
79
  await super.storeUser(user);
85
80
  await NativeOidc.setSessionSnapshot({
86
- [nativeContract.fields.namespace]: this.storageNamespace,
87
- [nativeContract.fields.value]: user
88
- ? JSON.stringify(toStoredSession(user, this.settings.authority, this.settings.client_id))
81
+ namespace: this.storageNamespace,
82
+ value: user
83
+ ? JSON.stringify(toStoredSession(user, user.profile.iss ?? this.settings.metadata?.issuer ?? this.settings.authority, this.settings.client_id))
89
84
  : null,
90
85
  });
91
86
  }
@@ -133,15 +128,15 @@ export class CapacitorUserManager extends UserManager {
133
128
  }
134
129
  function assertRuntime() {
135
130
  if (!globalThis.crypto?.subtle || !globalThis.crypto.getRandomValues) {
136
- throw new CapacitorOidcError(nativeContract.errorCodes.unsupportedRuntime, 'Web Crypto is required by oidc-client-ts');
131
+ throw new CapacitorOidcError('UNSUPPORTED_RUNTIME', 'Web Crypto is required by oidc-client-ts');
137
132
  }
138
133
  }
139
134
  function assertSettings(settings) {
140
135
  if ('client_secret' in settings) {
141
- throw new CapacitorOidcError(nativeContract.errorCodes.unsupportedRuntime, 'Native public clients must not contain a client secret');
136
+ throw new CapacitorOidcError('UNSUPPORTED_RUNTIME', 'Native public clients must not contain a client secret');
142
137
  }
143
138
  if ('client_authentication' in settings || 'dpop' in settings) {
144
- throw new CapacitorOidcError(nativeContract.errorCodes.unsupportedRuntime, 'The supplied settings contain an unsupported native-client option');
139
+ throw new CapacitorOidcError('UNSUPPORTED_RUNTIME', 'The supplied settings contain an unsupported native-client option');
145
140
  }
146
141
  }
147
142
  function toStoredSession(user, issuer, clientId) {
@@ -1 +1 @@
1
- {"version":3,"file":"capacitor-user-manager.js","sourceRoot":"","sources":["../../src/capacitor-user-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import { App } from '@capacitor/app';\nimport type { PluginListenerHandle } from '@capacitor/core';\nimport {\n ErrorResponse,\n UserManager,\n type SigninPopupArgs,\n type SigninResourceOwnerCredentialsArgs,\n type SigninSilentArgs,\n type SignoutResponse,\n type SignoutPopupArgs,\n type User,\n} from 'oidc-client-ts';\n\nimport { CapacitorNavigator, UnsupportedIframeNavigator } from './capacitor-navigator';\nimport { CapacitorSecureStateStore } from './capacitor-secure-state-store';\nimport type { CapacitorOidcNativeOptions, CapacitorUserManagerSettings, StoredSessionV1 } from './definitions';\nimport { CapacitorOidcError, unsupported } from './errors';\nimport { nativeContract } from './generated/native-contract';\nimport { NativeOidc } from './native';\n\nexport class CapacitorUserManager extends UserManager {\n private refreshPromise?: Promise<User | null>;\n private appStateListener?: PluginListenerHandle;\n\n private constructor(\n settings: CapacitorUserManagerSettings,\n nativeOptions: CapacitorOidcNativeOptions,\n private readonly storageNamespace: string,\n ) {\n const stateStore = new CapacitorSecureStateStore(`${storageNamespace}.transactions`);\n const userStore = new CapacitorSecureStateStore(`${storageNamespace}.session`);\n const navigator = new CapacitorNavigator(nativeOptions.ios?.prefersEphemeralWebBrowserSession ?? false);\n\n super(\n {\n ...settings,\n response_type: 'code',\n disablePKCE: false,\n monitorSession: false,\n popup_redirect_uri: settings.redirect_uri,\n popup_post_logout_redirect_uri: settings.post_logout_redirect_uri,\n stateStore,\n userStore,\n },\n navigator,\n navigator,\n new UnsupportedIframeNavigator(),\n );\n }\n\n static async create(\n settings: CapacitorUserManagerSettings,\n nativeOptions: CapacitorOidcNativeOptions = {},\n ): Promise<CapacitorUserManager> {\n assertRuntime();\n assertSettings(settings);\n await NativeOidc.configure({\n [nativeContract.fields.prefersEphemeralWebBrowserSession]: nativeOptions.ios?.prefersEphemeralWebBrowserSession,\n [nativeContract.fields.keychainAccessGroup]: nativeOptions.ios?.keychainAccessGroup,\n [nativeContract.fields.keychainAccessibility]: nativeOptions.ios?.keychainAccessibility,\n });\n const manager = new CapacitorUserManager(settings, nativeOptions, nativeOptions.storageNamespace ?? 'default');\n await manager.getValidUser();\n manager.appStateListener = await App.addListener('appStateChange', ({ isActive }) => {\n if (isActive) {\n void manager\n .getValidUser()\n .catch((error: unknown) =>\n manager.events._raiseSilentRenewError(error instanceof Error ? error : new Error('Silent renewal failed')),\n );\n }\n });\n return manager;\n }\n\n async signin(args: SigninPopupArgs = {}): Promise<User> {\n return super.signinPopup(args);\n }\n\n async signout(args: SignoutPopupArgs = {}): Promise<void> {\n await super.signoutPopup(args);\n }\n\n async getValidUser(minimumValiditySeconds = 60): Promise<User | null> {\n const user = await this.getUser();\n if (!user) return null;\n if (user.expires_in === undefined || user.expires_in > minimumValiditySeconds) return user;\n return this.signinSilent();\n }\n\n override signinSilent(args: SigninSilentArgs = {}): Promise<User | null> {\n if (!this.refreshPromise) {\n this.refreshPromise = this.refresh(args).finally(() => {\n this.refreshPromise = undefined;\n });\n }\n return this.refreshPromise;\n }\n\n private async refresh(args: SigninSilentArgs): Promise<User | null> {\n const user = await this.getUser();\n if (!user?.refresh_token) {\n if (user?.expired) await this.removeUser();\n return null;\n }\n\n const refresh = super.signinSilent({ ...args, forceIframeAuth: false }).catch(async (error: unknown) => {\n if (error instanceof ErrorResponse && error.error === 'invalid_grant') await this.removeUser();\n throw error;\n });\n return refresh;\n }\n\n override async storeUser(user: User | null): Promise<void> {\n await super.storeUser(user);\n await NativeOidc.setSessionSnapshot({\n [nativeContract.fields.namespace]: this.storageNamespace,\n [nativeContract.fields.value]: user\n ? JSON.stringify(toStoredSession(user, this.settings.authority, this.settings.client_id))\n : null,\n });\n }\n\n async cancel(): Promise<void> {\n await NativeOidc.cancel();\n }\n\n async dispose(): Promise<void> {\n this.stopSilentRenew();\n await this.appStateListener?.remove();\n await this.cancel();\n }\n\n override async signinRedirect(): Promise<void> {\n unsupported('Redirect navigation');\n }\n\n override async signinRedirectCallback(_url?: string): Promise<User> {\n unsupported('Redirect navigation');\n }\n\n override async signinCallback(_url?: string): Promise<User | undefined> {\n unsupported('Browser callback dispatch');\n }\n\n override async signinResourceOwnerCredentials(_args: SigninResourceOwnerCredentialsArgs): Promise<User> {\n unsupported('Resource Owner Password Credentials');\n }\n\n override async signinSilentCallback(_url?: string): Promise<void> {\n unsupported('Iframe navigation');\n }\n\n override async signoutRedirect(): Promise<void> {\n unsupported('Redirect navigation');\n }\n\n override async signoutRedirectCallback(_url?: string): Promise<SignoutResponse> {\n unsupported('Redirect navigation');\n }\n\n override async signoutCallback(_url?: string, _keepOpen?: boolean): Promise<SignoutResponse | undefined> {\n unsupported('Browser callback dispatch');\n }\n\n override async signoutSilent(): Promise<void> {\n unsupported('Iframe logout');\n }\n\n override async signoutSilentCallback(_url?: string): Promise<void> {\n unsupported('Iframe logout');\n }\n\n override async querySessionStatus(): Promise<null> {\n unsupported('Browser session monitoring');\n }\n}\n\nfunction assertRuntime(): void {\n if (!globalThis.crypto?.subtle || !globalThis.crypto.getRandomValues) {\n throw new CapacitorOidcError(\n nativeContract.errorCodes.unsupportedRuntime,\n 'Web Crypto is required by oidc-client-ts',\n );\n }\n}\n\nfunction assertSettings(settings: CapacitorUserManagerSettings): void {\n if ('client_secret' in settings) {\n throw new CapacitorOidcError(\n nativeContract.errorCodes.unsupportedRuntime,\n 'Native public clients must not contain a client secret',\n );\n }\n if ('client_authentication' in settings || 'dpop' in settings) {\n throw new CapacitorOidcError(\n nativeContract.errorCodes.unsupportedRuntime,\n 'The supplied settings contain an unsupported native-client option',\n );\n }\n}\n\nfunction toStoredSession(user: User, issuer: string, clientId: string): StoredSessionV1 {\n return {\n version: 1,\n issuer,\n clientId,\n accessToken: user.access_token,\n refreshToken: user.refresh_token,\n idToken: user.id_token,\n tokenType: user.token_type,\n scope: user.scope,\n expiresAt: user.expires_at,\n };\n}\n"]}
1
+ {"version":3,"file":"capacitor-user-manager.js","sourceRoot":"","sources":["../../src/capacitor-user-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,OAAO,EACL,aAAa,EACb,WAAW,GAOZ,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAE3E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,OAAO,oBAAqB,SAAQ,WAAW;IAOhC;IANX,cAAc,CAAwB;IACtC,gBAAgB,CAAwB;IAEhD,YACE,QAAsC,EACtC,aAAyC,EACxB,gBAAwB;QAEzC,MAAM,UAAU,GAAG,IAAI,yBAAyB,CAAC,GAAG,gBAAgB,eAAe,CAAC,CAAC;QACrF,MAAM,SAAS,GAAG,IAAI,yBAAyB,CAAC,GAAG,gBAAgB,UAAU,CAAC,CAAC;QAC/E,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,iCAAiC,IAAI,KAAK,CAAC,CAAC;QAEnG,KAAK,CACH;YACE,GAAG,QAAQ;YACX,aAAa,EAAE,MAAM;YACrB,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE,KAAK;YACrB,kBAAkB,EAAE,QAAQ,CAAC,YAAY;YACzC,8BAA8B,EAAE,QAAQ,CAAC,wBAAwB;YACjE,UAAU;YACV,SAAS;SACV,EACD,SAAS,EACT,SAAS,EACT,IAAI,0BAA0B,EAAE,CACjC,CAAC;QApBe,qBAAgB,GAAhB,gBAAgB,CAAQ;IAqB3C,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CACjB,QAAsC,EACtC,gBAA4C,EAAE;QAE9C,aAAa,EAAE,CAAC;QAChB,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzB,MAAM,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,oBAAoB,CAAC,QAAQ,EAAE,aAAa,EAAE,aAAa,CAAC,gBAAgB,IAAI,SAAS,CAAC,CAAC;QAC/G,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;QAC7B,OAAO,CAAC,gBAAgB,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;YAClF,IAAI,QAAQ,EAAE,CAAC;gBACb,KAAK,OAAO;qBACT,YAAY,EAAE;qBACd,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,CACxB,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC,CAC3G,CAAC;YACN,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,OAAwB,EAAE;QACrC,OAAO,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAyB,EAAE;QACvC,MAAM,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,sBAAsB,GAAG,EAAE;QAC5C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,IAAI,IAAI,CAAC,UAAU,GAAG,sBAAsB;YAAE,OAAO,IAAI,CAAC;QAC3F,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;IAC7B,CAAC;IAEQ,YAAY,CAAC,OAAyB,EAAE;QAC/C,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE;gBACpD,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;YAClC,CAAC,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,OAAO,CAAC,IAAsB;QAC1C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC;YACzB,IAAI,IAAI,EAAE,OAAO;gBAAE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC,EAAE,GAAG,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,KAAc,EAAE,EAAE;YACrG,IAAI,KAAK,YAAY,aAAa,IAAI,KAAK,CAAC,KAAK,KAAK,eAAe;gBAAE,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/F,MAAM,KAAK,CAAC;QACd,CAAC,CAAC,CAAC;QACH,OAAO,OAAO,CAAC;IACjB,CAAC;IAEQ,KAAK,CAAC,SAAS,CAAC,IAAiB;QACxC,MAAM,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,MAAM,UAAU,CAAC,kBAAkB,CAAC;YAClC,SAAS,EAAE,IAAI,CAAC,gBAAgB;YAChC,KAAK,EAAE,IAAI;gBACT,CAAC,CAAC,IAAI,CAAC,SAAS,CACZ,eAAe,CACb,IAAI,EACJ,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,EAC7E,IAAI,CAAC,QAAQ,CAAC,SAAS,CACxB,CACF;gBACH,CAAC,CAAC,IAAI;SACT,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,eAAe,EAAE,CAAC;QACvB,MAAM,IAAI,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;QACtC,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;IACtB,CAAC;IAEQ,KAAK,CAAC,cAAc;QAC3B,WAAW,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAEQ,KAAK,CAAC,sBAAsB,CAAC,IAAa;QACjD,WAAW,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAEQ,KAAK,CAAC,cAAc,CAAC,IAAa;QACzC,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAC3C,CAAC;IAEQ,KAAK,CAAC,8BAA8B,CAAC,KAAyC;QACrF,WAAW,CAAC,qCAAqC,CAAC,CAAC;IACrD,CAAC;IAEQ,KAAK,CAAC,oBAAoB,CAAC,IAAa;QAC/C,WAAW,CAAC,mBAAmB,CAAC,CAAC;IACnC,CAAC;IAEQ,KAAK,CAAC,eAAe;QAC5B,WAAW,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAEQ,KAAK,CAAC,uBAAuB,CAAC,IAAa;QAClD,WAAW,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;IAEQ,KAAK,CAAC,eAAe,CAAC,IAAa,EAAE,SAAmB;QAC/D,WAAW,CAAC,2BAA2B,CAAC,CAAC;IAC3C,CAAC;IAEQ,KAAK,CAAC,aAAa;QAC1B,WAAW,CAAC,eAAe,CAAC,CAAC;IAC/B,CAAC;IAEQ,KAAK,CAAC,qBAAqB,CAAC,IAAa;QAChD,WAAW,CAAC,eAAe,CAAC,CAAC;IAC/B,CAAC;IAEQ,KAAK,CAAC,kBAAkB;QAC/B,WAAW,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;CACF;AAED,SAAS,aAAa;IACpB,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QACrE,MAAM,IAAI,kBAAkB,CAAC,qBAAqB,EAAE,0CAA0C,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,QAAsC;IAC5D,IAAI,eAAe,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,IAAI,kBAAkB,CAAC,qBAAqB,EAAE,wDAAwD,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,uBAAuB,IAAI,QAAQ,IAAI,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9D,MAAM,IAAI,kBAAkB,CAC1B,qBAAqB,EACrB,mEAAmE,CACpE,CAAC;IACJ,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,IAAU,EAAE,MAAc,EAAE,QAAgB;IACnE,OAAO;QACL,OAAO,EAAE,CAAC;QACV,MAAM;QACN,QAAQ;QACR,WAAW,EAAE,IAAI,CAAC,YAAY;QAC9B,YAAY,EAAE,IAAI,CAAC,aAAa;QAChC,OAAO,EAAE,IAAI,CAAC,QAAQ;QACtB,SAAS,EAAE,IAAI,CAAC,UAAU;QAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,SAAS,EAAE,IAAI,CAAC,UAAU;KAC3B,CAAC;AACJ,CAAC","sourcesContent":["import { App } from '@capacitor/app';\nimport type { PluginListenerHandle } from '@capacitor/core';\nimport {\n ErrorResponse,\n UserManager,\n type SigninPopupArgs,\n type SigninResourceOwnerCredentialsArgs,\n type SigninSilentArgs,\n type SignoutResponse,\n type SignoutPopupArgs,\n type User,\n} from 'oidc-client-ts';\n\nimport { CapacitorNavigator, UnsupportedIframeNavigator } from './capacitor-navigator';\nimport { CapacitorSecureStateStore } from './capacitor-secure-state-store';\nimport type { CapacitorOidcNativeOptions, CapacitorUserManagerSettings, StoredSessionV1 } from './definitions';\nimport { CapacitorOidcError, unsupported } from './errors';\nimport { NativeOidc } from './native';\n\nexport class CapacitorUserManager extends UserManager {\n private refreshPromise?: Promise<User | null>;\n private appStateListener?: PluginListenerHandle;\n\n private constructor(\n settings: CapacitorUserManagerSettings,\n nativeOptions: CapacitorOidcNativeOptions,\n private readonly storageNamespace: string,\n ) {\n const stateStore = new CapacitorSecureStateStore(`${storageNamespace}.transactions`);\n const userStore = new CapacitorSecureStateStore(`${storageNamespace}.session`);\n const navigator = new CapacitorNavigator(nativeOptions.prefersEphemeralWebBrowserSession ?? false);\n\n super(\n {\n ...settings,\n response_type: 'code',\n disablePKCE: false,\n monitorSession: false,\n popup_redirect_uri: settings.redirect_uri,\n popup_post_logout_redirect_uri: settings.post_logout_redirect_uri,\n stateStore,\n userStore,\n },\n navigator,\n navigator,\n new UnsupportedIframeNavigator(),\n );\n }\n\n static async create(\n settings: CapacitorUserManagerSettings,\n nativeOptions: CapacitorOidcNativeOptions = {},\n ): Promise<CapacitorUserManager> {\n assertRuntime();\n assertSettings(settings);\n await NativeOidc.configure(nativeOptions.ios ?? {});\n const manager = new CapacitorUserManager(settings, nativeOptions, nativeOptions.storageNamespace ?? 'default');\n await manager.getValidUser();\n manager.appStateListener = await App.addListener('appStateChange', ({ isActive }) => {\n if (isActive) {\n void manager\n .getValidUser()\n .catch((error: unknown) =>\n manager.events._raiseSilentRenewError(error instanceof Error ? error : new Error('Silent renewal failed')),\n );\n }\n });\n return manager;\n }\n\n async signin(args: SigninPopupArgs = {}): Promise<User> {\n return super.signinPopup(args);\n }\n\n async signout(args: SignoutPopupArgs = {}): Promise<void> {\n await super.signoutPopup(args);\n }\n\n async getValidUser(minimumValiditySeconds = 60): Promise<User | null> {\n const user = await this.getUser();\n if (!user) return null;\n if (user.expires_in === undefined || user.expires_in > minimumValiditySeconds) return user;\n return this.signinSilent();\n }\n\n override signinSilent(args: SigninSilentArgs = {}): Promise<User | null> {\n if (!this.refreshPromise) {\n this.refreshPromise = this.refresh(args).finally(() => {\n this.refreshPromise = undefined;\n });\n }\n return this.refreshPromise;\n }\n\n private async refresh(args: SigninSilentArgs): Promise<User | null> {\n const user = await this.getUser();\n if (!user?.refresh_token) {\n if (user?.expired) await this.removeUser();\n return null;\n }\n\n const refresh = super.signinSilent({ ...args, forceIframeAuth: false }).catch(async (error: unknown) => {\n if (error instanceof ErrorResponse && error.error === 'invalid_grant') await this.removeUser();\n throw error;\n });\n return refresh;\n }\n\n override async storeUser(user: User | null): Promise<void> {\n await super.storeUser(user);\n await NativeOidc.setSessionSnapshot({\n namespace: this.storageNamespace,\n value: user\n ? JSON.stringify(\n toStoredSession(\n user,\n user.profile.iss ?? this.settings.metadata?.issuer ?? this.settings.authority,\n this.settings.client_id,\n ),\n )\n : null,\n });\n }\n\n async cancel(): Promise<void> {\n await NativeOidc.cancel();\n }\n\n async dispose(): Promise<void> {\n this.stopSilentRenew();\n await this.appStateListener?.remove();\n await this.cancel();\n }\n\n override async signinRedirect(): Promise<void> {\n unsupported('Redirect navigation');\n }\n\n override async signinRedirectCallback(_url?: string): Promise<User> {\n unsupported('Redirect navigation');\n }\n\n override async signinCallback(_url?: string): Promise<User | undefined> {\n unsupported('Browser callback dispatch');\n }\n\n override async signinResourceOwnerCredentials(_args: SigninResourceOwnerCredentialsArgs): Promise<User> {\n unsupported('Resource Owner Password Credentials');\n }\n\n override async signinSilentCallback(_url?: string): Promise<void> {\n unsupported('Iframe navigation');\n }\n\n override async signoutRedirect(): Promise<void> {\n unsupported('Redirect navigation');\n }\n\n override async signoutRedirectCallback(_url?: string): Promise<SignoutResponse> {\n unsupported('Redirect navigation');\n }\n\n override async signoutCallback(_url?: string, _keepOpen?: boolean): Promise<SignoutResponse | undefined> {\n unsupported('Browser callback dispatch');\n }\n\n override async signoutSilent(): Promise<void> {\n unsupported('Iframe logout');\n }\n\n override async signoutSilentCallback(_url?: string): Promise<void> {\n unsupported('Iframe logout');\n }\n\n override async querySessionStatus(): Promise<null> {\n unsupported('Browser session monitoring');\n }\n}\n\nfunction assertRuntime(): void {\n if (!globalThis.crypto?.subtle || !globalThis.crypto.getRandomValues) {\n throw new CapacitorOidcError('UNSUPPORTED_RUNTIME', 'Web Crypto is required by oidc-client-ts');\n }\n}\n\nfunction assertSettings(settings: CapacitorUserManagerSettings): void {\n if ('client_secret' in settings) {\n throw new CapacitorOidcError('UNSUPPORTED_RUNTIME', 'Native public clients must not contain a client secret');\n }\n if ('client_authentication' in settings || 'dpop' in settings) {\n throw new CapacitorOidcError(\n 'UNSUPPORTED_RUNTIME',\n 'The supplied settings contain an unsupported native-client option',\n );\n }\n}\n\nfunction toStoredSession(user: User, issuer: string, clientId: string): StoredSessionV1 {\n return {\n version: 1,\n issuer,\n clientId,\n accessToken: user.access_token,\n refreshToken: user.refresh_token,\n idToken: user.id_token,\n tokenType: user.token_type,\n scope: user.scope,\n expiresAt: user.expires_at,\n };\n}\n"]}