@oxy.so/services 11.0.0 → 11.2.0-oxy-one.0
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.
- package/lib/commonjs/index.js +13 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/boot/runProviderColdBoot.js +14 -1
- package/lib/commonjs/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +25 -7
- package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +198 -41
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/commitSessionFlow.js +5 -0
- package/lib/commonjs/ui/context/commitSessionFlow.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +56 -9
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/isolatedOAuthSession.js +52 -0
- package/lib/commonjs/ui/context/isolatedOAuthSession.js.map +1 -0
- package/lib/commonjs/ui/context/useOxyAccountGraph.js +7 -5
- package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/usePersonalPlans.js +43 -0
- package/lib/commonjs/ui/hooks/queries/usePersonalPlans.js.map +1 -0
- package/lib/commonjs/ui/hooks/useAuth.js +7 -3
- package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
- package/lib/commonjs/ui/oauth/applicationSessionLane.js +32 -0
- package/lib/commonjs/ui/oauth/applicationSessionLane.js.map +1 -0
- package/lib/commonjs/ui/oauth/completeOAuthCode.js +4 -2
- package/lib/commonjs/ui/oauth/completeOAuthCode.js.map +1 -1
- package/lib/commonjs/ui/oauth/nativeAuthTransport.js +119 -0
- package/lib/commonjs/ui/oauth/nativeAuthTransport.js.map +1 -0
- package/lib/commonjs/ui/session/createSessionClient.js +14 -2
- package/lib/commonjs/ui/session/createSessionClient.js.map +1 -1
- package/lib/commonjs/ui/session/deviceCredentialTracker.js +8 -0
- package/lib/commonjs/ui/session/deviceCredentialTracker.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/boot/runProviderColdBoot.js +14 -1
- package/lib/module/ui/boot/runProviderColdBoot.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +25 -7
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +200 -43
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/commitSessionFlow.js +5 -0
- package/lib/module/ui/context/commitSessionFlow.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +56 -9
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/isolatedOAuthSession.js +44 -0
- package/lib/module/ui/context/isolatedOAuthSession.js.map +1 -0
- package/lib/module/ui/context/useOxyAccountGraph.js +7 -5
- package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/module/ui/hooks/queries/usePersonalPlans.js +39 -0
- package/lib/module/ui/hooks/queries/usePersonalPlans.js.map +1 -0
- package/lib/module/ui/hooks/useAuth.js +7 -3
- package/lib/module/ui/hooks/useAuth.js.map +1 -1
- package/lib/module/ui/oauth/applicationSessionLane.js +26 -0
- package/lib/module/ui/oauth/applicationSessionLane.js.map +1 -0
- package/lib/module/ui/oauth/completeOAuthCode.js +4 -2
- package/lib/module/ui/oauth/completeOAuthCode.js.map +1 -1
- package/lib/module/ui/oauth/nativeAuthTransport.js +115 -0
- package/lib/module/ui/oauth/nativeAuthTransport.js.map +1 -0
- package/lib/module/ui/session/createSessionClient.js +14 -2
- package/lib/module/ui/session/createSessionClient.js.map +1 -1
- package/lib/module/ui/session/deviceCredentialTracker.js +8 -0
- package/lib/module/ui/session/deviceCredentialTracker.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +2 -0
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts +7 -0
- package/lib/typescript/commonjs/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts +2 -0
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +3 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/commitSessionFlow.d.ts +2 -0
- package/lib/typescript/commonjs/ui/context/commitSessionFlow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +3 -2
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/isolatedOAuthSession.d.ts +19 -0
- package/lib/typescript/commonjs/ui/context/isolatedOAuthSession.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +3 -0
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts +2 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +6 -0
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/usePersonalPlans.d.ts +64 -0
- package/lib/typescript/commonjs/ui/hooks/queries/usePersonalPlans.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/oauth/applicationSessionLane.d.ts +6 -0
- package/lib/typescript/commonjs/ui/oauth/applicationSessionLane.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/oauth/completeOAuthCode.d.ts +2 -2
- package/lib/typescript/commonjs/ui/oauth/nativeAuthTransport.d.ts +28 -0
- package/lib/typescript/commonjs/ui/oauth/nativeAuthTransport.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +1 -1
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/deviceCredentialTracker.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +2 -0
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts +7 -0
- package/lib/typescript/module/ui/boot/runProviderColdBoot.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts +2 -0
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +3 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/commitSessionFlow.d.ts +2 -0
- package/lib/typescript/module/ui/context/commitSessionFlow.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +3 -2
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/isolatedOAuthSession.d.ts +19 -0
- package/lib/typescript/module/ui/context/isolatedOAuthSession.d.ts.map +1 -0
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +3 -0
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts +2 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +6 -0
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/usePersonalPlans.d.ts +64 -0
- package/lib/typescript/module/ui/hooks/queries/usePersonalPlans.d.ts.map +1 -0
- package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/module/ui/oauth/applicationSessionLane.d.ts +6 -0
- package/lib/typescript/module/ui/oauth/applicationSessionLane.d.ts.map +1 -0
- package/lib/typescript/module/ui/oauth/completeOAuthCode.d.ts +2 -2
- package/lib/typescript/module/ui/oauth/nativeAuthTransport.d.ts +28 -0
- package/lib/typescript/module/ui/oauth/nativeAuthTransport.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/createSessionClient.d.ts +1 -1
- package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/deviceCredentialTracker.d.ts.map +1 -1
- package/package.json +30 -30
- package/src/index.ts +4 -0
- package/src/ui/boot/__tests__/coldBootNoIdpRedirect.test.ts +56 -2
- package/src/ui/boot/runProviderColdBoot.ts +22 -2
- package/src/ui/components/OxySignInButton.tsx +20 -4
- package/src/ui/context/OxyContext.tsx +171 -40
- package/src/ui/context/__tests__/commitSessionFlow.test.ts +13 -0
- package/src/ui/context/__tests__/isolatedOAuthSession.test.ts +35 -0
- package/src/ui/context/commitSessionFlow.ts +8 -0
- package/src/ui/context/hooks/useAuthOperations.ts +55 -9
- package/src/ui/context/isolatedOAuthSession.ts +48 -0
- package/src/ui/context/oxyContextTypes.ts +4 -0
- package/src/ui/context/useOxyAccountGraph.ts +8 -5
- package/src/ui/hooks/queries/usePersonalPlans.ts +23 -0
- package/src/ui/hooks/useAuth.ts +6 -2
- package/src/ui/oauth/__tests__/completeOAuthCode.test.ts +1 -1
- package/src/ui/oauth/__tests__/nativeAuthTransport.test.ts +57 -0
- package/src/ui/oauth/__tests__/oauthBearerCommit.http.test.ts +131 -0
- package/src/ui/oauth/applicationSessionLane.ts +26 -0
- package/src/ui/oauth/completeOAuthCode.ts +3 -3
- package/src/ui/oauth/nativeAuthTransport.ts +67 -0
- package/src/ui/session/createSessionClient.ts +13 -1
- package/src/ui/session/deviceCredentialTracker.ts +7 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useState","useEffect","useRef","Platform","logger","generatePkcePair","generateOAuthState","buildOAuthAuthorizeUrl","useAuthStore","useShallow","SocialButton","socialButtonLabel","toast","useOxy","useI18n","subscribeToAccountDialog","openAuthorizeUrlNative","closeOAuthPopup","openOAuthPopup","jsx","_jsx","ACTION_KEYS","signIn","continue","signUp","OxySignInButton","variant","appearance","action","size","fullWidth","iconOnly","onPress","style","textStyle","text","disabled","showWhenAuthenticated","oauthRedirectUri","onOAuthResult","t","openAccountDialog","oxyServices","clientId","webAuthMode","startWebOAuthSignIn","isAuthenticated","isLoading","state","isModalOpen","setIsModalOpen","appResolutionRef","routingRef","shouldPreOpenPopup","OS","Boolean","resolvePublicApplication","cached","current","promise","apps","getPublic","catch","error","notifyNotConfigured","appName","description","app","notifyFailed","startOfficialSignIn","startThirdPartyOAuth","popup","undefined","component","application","name","result","redirectUri","status","warn","reason","pkce","Promise","all","authorizeUrl","codeChallenge","redirectUrl","codeVerifier","routeSignIn","resolving","
|
|
1
|
+
{"version":3,"names":["classifyApplicationSessionLane","useCallback","useState","useEffect","useRef","Platform","logger","generatePkcePair","generateOAuthState","buildOAuthAuthorizeUrl","useAuthStore","useShallow","SocialButton","socialButtonLabel","toast","useOxy","useI18n","subscribeToAccountDialog","openAuthorizeUrlNative","closeOAuthPopup","openOAuthPopup","jsx","_jsx","ACTION_KEYS","signIn","continue","signUp","OxySignInButton","variant","appearance","action","size","fullWidth","iconOnly","onPress","style","textStyle","text","disabled","showWhenAuthenticated","oauthRedirectUri","onOAuthResult","nativeOAuthCompletion","t","openAccountDialog","oxyServices","clientId","webAuthMode","startWebOAuthSignIn","startNativeOAuthSignIn","isAuthenticated","isLoading","state","isModalOpen","setIsModalOpen","appResolutionRef","routingRef","shouldPreOpenPopup","OS","Boolean","resolvePublicApplication","cached","current","promise","apps","getPublic","cache","catch","error","notifyNotConfigured","appName","description","app","notifyFailed","startOfficialSignIn","startThirdPartyOAuth","popup","undefined","component","application","name","result","redirectUri","status","warn","reason","pkce","Promise","all","authorizeUrl","codeChallenge","redirectUrl","codeVerifier","routeSignIn","resolving","Error","String","handlePress","isButtonDisabled","resolvedAppearance","actionKey","translated","label","brand","accessibilityLabel","children"],"sourceRoot":"../../../../src","sources":["ui/components/OxySignInButton.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
import { startNativeOAuthSignIn } from "../oauth/nativeAuthTransport.js";
|
|
4
|
+
import { clearIsolatedOAuthSession, hasIsolatedOAuthSession, readIsolatedOAuthSession, setIsolatedOAuthSession } from "./isolatedOAuthSession.js";
|
|
3
5
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';
|
|
4
|
-
import { Linking, Platform } from 'react-native';
|
|
6
|
+
import { AppState, Linking, Platform } from 'react-native';
|
|
5
7
|
import { OxyServices } from '@oxy.so/core';
|
|
6
8
|
import { KeyManager } from '@oxy.so/core/crypto';
|
|
7
|
-
import { refreshDeviceSecretArm, establishIdentitySession,
|
|
9
|
+
import { refreshDeviceSecretArm, establishIdentitySession, createAuthRefreshHandler, startTokenRefreshScheduler, createAccountDialogController } from '@oxy.so/core/session';
|
|
8
10
|
import { logger as loggerUtil } from '@oxy.so/core';
|
|
9
11
|
import { registerAccountDialogControls, notifyAccountDialogVisibility } from "../navigation/accountDialogManager.js";
|
|
10
12
|
import { redirectToAuthorize } from "../components/oauthNavigation.js";
|
|
11
13
|
import { startWebOAuthSignIn } from "../oauth/browserAuthTransport.js";
|
|
12
14
|
import { openBridgeWindow, resolveBridgeOrigin, runBrowserBridge } from "../oauth/browserBridge.js";
|
|
15
|
+
import { createPlatformSharedDeviceCredentialStore } from "../session/sharedDeviceCredentialStore.js";
|
|
13
16
|
import { trackDeviceCredential } from "../session/deviceCredentialTracker.js";
|
|
14
17
|
import { requestOAuthConsent } from "../oauth/explicitOAuthConsent.js";
|
|
15
18
|
import { isWebBrowser } from "../utils/isWebBrowser.js";
|
|
16
19
|
import { resolveDeliveryPlatform } from "../utils/deliveryPlatform.js";
|
|
17
20
|
import { runProviderColdBoot } from "../boot/runProviderColdBoot.js";
|
|
21
|
+
import { resolveApplicationSessionLane } from "../oauth/applicationSessionLane.js";
|
|
22
|
+
import { handleAuthError } from "../utils/errorHandlers.js";
|
|
18
23
|
import { hasPersistedSessionCredential, loadPersistedDeviceCredential } from "../utils/deviceCredential.js";
|
|
19
24
|
import { createTokenLossRecovery } from "../session/tokenLossRecovery.js";
|
|
20
25
|
import { bindAuthStoreToRuntime } from "../stores/authStore.js";
|
|
@@ -135,9 +140,25 @@ export const OxyRuntimeProvider = ({
|
|
|
135
140
|
// Server-authoritative device session client. Built ONCE per `oxyServices`
|
|
136
141
|
// instance. Device-scoped sockets connect with deviceId+deviceSecret when no
|
|
137
142
|
// bearer is planted yet, so cross-origin apps sync via `session_state`.
|
|
143
|
+
const runtimeRef = useRef(null);
|
|
144
|
+
const registeredLaneRef = useRef({
|
|
145
|
+
clientId: clientIdProp,
|
|
146
|
+
services: oxyServices,
|
|
147
|
+
lane: null,
|
|
148
|
+
pending: null
|
|
149
|
+
});
|
|
150
|
+
if (registeredLaneRef.current.clientId !== clientIdProp || registeredLaneRef.current.services !== oxyServices) {
|
|
151
|
+
registeredLaneRef.current = {
|
|
152
|
+
clientId: clientIdProp,
|
|
153
|
+
services: oxyServices,
|
|
154
|
+
lane: null,
|
|
155
|
+
pending: null
|
|
156
|
+
};
|
|
157
|
+
}
|
|
138
158
|
const sessionClientPairRef = useRef(null);
|
|
139
159
|
if (!sessionClientPairRef.current) {
|
|
140
160
|
sessionClientPairRef.current = createSessionClient(oxyServices, origin => {
|
|
161
|
+
if (runtimeRef.current && hasIsolatedOAuthSession(runtimeRef.current)) return;
|
|
141
162
|
// Erase the DURABLE device credential only on a `request`-origin verdict
|
|
142
163
|
// (a REST sign-out / revocation). A `push`-origin empty state is a socket
|
|
143
164
|
// broadcast that may be a transient reconnect artifact — clearing the
|
|
@@ -155,7 +176,10 @@ export const OxyRuntimeProvider = ({
|
|
|
155
176
|
// option — and the pinned account id once an identity-bound provider has
|
|
156
177
|
// resolved its pin. Read through the ref so the resolver stays stable for
|
|
157
178
|
// the client's lifetime while still seeing later resolutions.
|
|
158
|
-
() => identityRef.current?.getPinnedAccountId() ?? null)
|
|
179
|
+
() => identityRef.current?.getPinnedAccountId() ?? null, () => registeredLaneRef.current.lane === 'device' && (!runtimeRef.current || !hasIsolatedOAuthSession(runtimeRef.current)), async () => {
|
|
180
|
+
if (identityRef.current || registeredLaneRef.current.lane !== 'device') return;
|
|
181
|
+
if ((await authStore.setAutomaticIdentitySignInSuppressed?.(true)) === false) throw new Error('Failed to persist explicit sign-out intent');
|
|
182
|
+
});
|
|
159
183
|
}
|
|
160
184
|
const {
|
|
161
185
|
client: sessionClient,
|
|
@@ -175,7 +199,6 @@ export const OxyRuntimeProvider = ({
|
|
|
175
199
|
const saveSessionIdsRef = useRef(() => undefined);
|
|
176
200
|
const subjectChangeRef = useRef(() => undefined);
|
|
177
201
|
const reestablishRef = useRef(() => undefined);
|
|
178
|
-
const runtimeRef = useRef(null);
|
|
179
202
|
if (!runtimeRef.current) {
|
|
180
203
|
runtimeRef.current = createOxyRuntime({
|
|
181
204
|
oxyServices,
|
|
@@ -390,11 +413,56 @@ export const OxyRuntimeProvider = ({
|
|
|
390
413
|
const cred = await loadPersistedDeviceCredential(authStore);
|
|
391
414
|
sessionClientHost.setDeviceCredential(cred);
|
|
392
415
|
}, [authStore, sessionClientHost]);
|
|
416
|
+
|
|
417
|
+
// Provider-owned classification: never accept a caller/button's trust verdict.
|
|
418
|
+
// Recovery asks freshly; concurrent boot/recovery requests share one lookup.
|
|
419
|
+
const resolveRegisteredLane = useCallback(async () => {
|
|
420
|
+
const selected = registeredLaneRef.current;
|
|
421
|
+
if (selected.clientId !== clientIdProp || selected.services !== oxyServices) throw new Error('Provider classification was superseded');
|
|
422
|
+
if (selected.pending) return selected.pending;
|
|
423
|
+
selected.lane = null;
|
|
424
|
+
const pending = (async () => {
|
|
425
|
+
const lane = await resolveApplicationSessionLane(oxyServices, clientIdProp);
|
|
426
|
+
if (registeredLaneRef.current !== selected) throw new Error('Provider classification was superseded');
|
|
427
|
+
if (lane === 'oauth' && !hasIsolatedOAuthSession(runtime)) {
|
|
428
|
+
sessionClient.resetLocalState();
|
|
429
|
+
sessionClientHost.setDeviceCredential(null);
|
|
430
|
+
await clearSessionStateRef.current();
|
|
431
|
+
}
|
|
432
|
+
if (registeredLaneRef.current !== selected) throw new Error('Provider classification was superseded');
|
|
433
|
+
selected.lane = lane;
|
|
434
|
+
return lane;
|
|
435
|
+
})();
|
|
436
|
+
selected.pending = pending;
|
|
437
|
+
try {
|
|
438
|
+
return await pending;
|
|
439
|
+
} finally {
|
|
440
|
+
if (selected.pending === pending) selected.pending = null;
|
|
441
|
+
}
|
|
442
|
+
}, [oxyServices, clientIdProp, runtime, sessionClient, sessionClientHost]);
|
|
443
|
+
const ensureDeviceSessionLane = useCallback(() => {
|
|
444
|
+
if (registeredLaneRef.current.clientId !== clientIdProp || registeredLaneRef.current.services !== oxyServices) {
|
|
445
|
+
throw new Error('Provider classification was superseded');
|
|
446
|
+
}
|
|
447
|
+
if (registeredLaneRef.current.lane === 'oauth' || hasIsolatedOAuthSession(runtime)) {
|
|
448
|
+
throw new Error('This application requires explicit OAuth sign-in');
|
|
449
|
+
}
|
|
450
|
+
if (registeredLaneRef.current.lane === 'device') return;
|
|
451
|
+
return resolveRegisteredLane().then(lane => {
|
|
452
|
+
if (registeredLaneRef.current.clientId !== clientIdProp || registeredLaneRef.current.services !== oxyServices) {
|
|
453
|
+
throw new Error('Provider classification was superseded');
|
|
454
|
+
}
|
|
455
|
+
if (lane !== 'device' || hasIsolatedOAuthSession(runtime)) {
|
|
456
|
+
throw new Error('This application requires explicit OAuth sign-in');
|
|
457
|
+
}
|
|
458
|
+
});
|
|
459
|
+
}, [resolveRegisteredLane, runtime, clientIdProp, oxyServices]);
|
|
393
460
|
const {
|
|
394
461
|
signIn,
|
|
395
462
|
logout,
|
|
396
463
|
logoutAll
|
|
397
464
|
} = useAuthOperations({
|
|
465
|
+
ensureDeviceSessionLane,
|
|
398
466
|
oxyServices,
|
|
399
467
|
store: authStore,
|
|
400
468
|
storage,
|
|
@@ -477,8 +545,9 @@ export const OxyRuntimeProvider = ({
|
|
|
477
545
|
};
|
|
478
546
|
const recovery = createTokenLossRecovery({
|
|
479
547
|
remint: () => oxyServices.http.refreshAccessToken('preflight'),
|
|
480
|
-
hasDeviceCredential: () => hasPersistedSessionCredential(authStore),
|
|
548
|
+
hasDeviceCredential: () => registeredLaneRef.current.lane !== 'device' || hasIsolatedOAuthSession(runtime) ? Promise.resolve(false) : hasPersistedSessionCredential(authStore),
|
|
481
549
|
hasKeyedRecovery: async () => {
|
|
550
|
+
if (registeredLaneRef.current.lane !== 'device' || hasIsolatedOAuthSession(runtime)) return false;
|
|
482
551
|
if (Platform.OS === 'web') {
|
|
483
552
|
return false;
|
|
484
553
|
}
|
|
@@ -529,19 +598,27 @@ export const OxyRuntimeProvider = ({
|
|
|
529
598
|
// account instead of the device's active one, and its recovery arm becomes the
|
|
530
599
|
// PRIMARY-key identity sign-in rather than the cross-app shared keychain.
|
|
531
600
|
useEffect(() => {
|
|
532
|
-
|
|
601
|
+
let disposed = false;
|
|
602
|
+
const refresh = createAuthRefreshHandler({
|
|
533
603
|
oxy: oxyServices,
|
|
534
604
|
store: authStore,
|
|
605
|
+
isCurrent: () => !disposed && registeredLaneRef.current.lane === 'device' && !hasIsolatedOAuthSession(runtime),
|
|
535
606
|
...(identity ? {
|
|
536
607
|
identity: identity.binding
|
|
608
|
+
} : {}),
|
|
609
|
+
...(!identity && !isWebBrowser() ? {
|
|
610
|
+
allowCommonsIdentityFallback: false,
|
|
611
|
+
sharedDeviceCredential: createPlatformSharedDeviceCredentialStore() ?? undefined
|
|
537
612
|
} : {})
|
|
538
613
|
});
|
|
614
|
+
oxyServices.http.setAuthRefreshHandler(reason => registeredLaneRef.current.lane !== 'device' || hasIsolatedOAuthSession(runtime) ? Promise.resolve(null) : refresh(reason));
|
|
539
615
|
const scheduler = startTokenRefreshScheduler(oxyServices);
|
|
540
616
|
return () => {
|
|
617
|
+
disposed = true;
|
|
541
618
|
scheduler.dispose();
|
|
542
|
-
|
|
619
|
+
oxyServices.http.setAuthRefreshHandler(null);
|
|
543
620
|
};
|
|
544
|
-
}, [oxyServices, authStore, identity]);
|
|
621
|
+
}, [oxyServices, authStore, identity, runtime]);
|
|
545
622
|
|
|
546
623
|
// ── Session commit funnel ────────────────────────────────────────────────
|
|
547
624
|
// The single place a session becomes committed: plant tokens, persist the
|
|
@@ -550,6 +627,22 @@ export const OxyRuntimeProvider = ({
|
|
|
550
627
|
// Used by the QR device flow (`handleWebSession`), password sign-in, 2FA
|
|
551
628
|
// completion, and the cold boot.
|
|
552
629
|
const commitSession = useCallback(async (input, options) => {
|
|
630
|
+
const isolatedOAuth = options.oauth === true && !input.deviceId && !input.deviceSecret;
|
|
631
|
+
if (isolatedOAuth || hasIsolatedOAuthSession(runtime)) {
|
|
632
|
+
sessionClient.resetLocalState();
|
|
633
|
+
sessionClientHost.setDeviceCredential(null);
|
|
634
|
+
await authStore.clear();
|
|
635
|
+
await clearSessionStateRef.current();
|
|
636
|
+
}
|
|
637
|
+
if (isolatedOAuth) {
|
|
638
|
+
if (!clientId) throw new Error('An isolated OAuth commit requires its registered client ID');
|
|
639
|
+
setIsolatedOAuthSession(runtime, {
|
|
640
|
+
sessionId: input.sessionId,
|
|
641
|
+
clientId
|
|
642
|
+
});
|
|
643
|
+
} else {
|
|
644
|
+
clearIsolatedOAuthSession(runtime);
|
|
645
|
+
}
|
|
553
646
|
if (input.accessToken) {
|
|
554
647
|
oxyServices.session.setAccessToken(input.accessToken);
|
|
555
648
|
}
|
|
@@ -599,7 +692,7 @@ export const OxyRuntimeProvider = ({
|
|
|
599
692
|
userId: input.userId,
|
|
600
693
|
isCurrent: true
|
|
601
694
|
}], {
|
|
602
|
-
merge:
|
|
695
|
+
merge: !isolatedOAuth
|
|
603
696
|
});
|
|
604
697
|
runtime.setActiveSessionId(input.sessionId);
|
|
605
698
|
});
|
|
@@ -615,6 +708,7 @@ export const OxyRuntimeProvider = ({
|
|
|
615
708
|
// on the next load).
|
|
616
709
|
await commitDeviceSetAndResolve({
|
|
617
710
|
activate: options.activate,
|
|
711
|
+
isolatedOAuth,
|
|
618
712
|
hasDeviceState: input.deviceState !== undefined,
|
|
619
713
|
userId: input.userId,
|
|
620
714
|
fallbackUser: input.user ?? null,
|
|
@@ -627,7 +721,10 @@ export const OxyRuntimeProvider = ({
|
|
|
627
721
|
onAuthStateChange: onAuthStateChangeRef.current,
|
|
628
722
|
markAuthResolved: markAuthResolvedRef.current
|
|
629
723
|
});
|
|
630
|
-
|
|
724
|
+
if (options.activate && !isolatedOAuth && !identity && input.userId && runtime.getSnapshot().account?.id === input.userId) {
|
|
725
|
+
if ((await authStore.setAutomaticIdentitySignInSuppressed?.(false)) === false) logger('Failed to release explicit sign-out intent after sign-in');
|
|
726
|
+
}
|
|
727
|
+
}, [oxyServices, authStore, runtime, sessionClient, sessionClientHost, syncFromClient, logger, clientId, identity]);
|
|
631
728
|
const commitSessionRef = useRef(commitSession);
|
|
632
729
|
commitSessionRef.current = commitSession;
|
|
633
730
|
|
|
@@ -662,9 +759,21 @@ export const OxyRuntimeProvider = ({
|
|
|
662
759
|
authorizeBaseUrl,
|
|
663
760
|
identityBound: isIdentityBound,
|
|
664
761
|
commitSession: input => commitSessionRef.current(input, {
|
|
665
|
-
activate: true
|
|
762
|
+
activate: true,
|
|
763
|
+
oauth: true
|
|
666
764
|
})
|
|
667
765
|
}, options), [webAuthMode, oxyServices, clientId, authorizeBaseUrl, isIdentityBound]);
|
|
766
|
+
const startNativeOAuthSignInForContext = useCallback(options => startNativeOAuthSignIn({
|
|
767
|
+
platform: Platform.OS === 'ios' || Platform.OS === 'android' ? 'native' : 'unsupported',
|
|
768
|
+
oxyServices,
|
|
769
|
+
clientId,
|
|
770
|
+
authorizeBaseUrl,
|
|
771
|
+
identityBound: isIdentityBound,
|
|
772
|
+
commitSession: input => commitSessionRef.current(input, {
|
|
773
|
+
activate: true,
|
|
774
|
+
oauth: true
|
|
775
|
+
})
|
|
776
|
+
}, options), [oxyServices, clientId, authorizeBaseUrl, isIdentityBound]);
|
|
668
777
|
const requestOAuthConsentForContext = useCallback(options => requestOAuthConsent({
|
|
669
778
|
platform: Platform.OS === 'web' ? 'web' : Platform.OS === 'ios' || Platform.OS === 'android' ? 'native' : 'unsupported',
|
|
670
779
|
mode: webAuthMode,
|
|
@@ -674,7 +783,8 @@ export const OxyRuntimeProvider = ({
|
|
|
674
783
|
identityBound: isIdentityBound,
|
|
675
784
|
expectedUserId: user?.id ?? null,
|
|
676
785
|
commitSession: input => commitSessionRef.current(input, {
|
|
677
|
-
activate: true
|
|
786
|
+
activate: true,
|
|
787
|
+
oauth: true
|
|
678
788
|
})
|
|
679
789
|
}, options), [webAuthMode, oxyServices, clientId, authorizeBaseUrl, isIdentityBound, user?.id]);
|
|
680
790
|
|
|
@@ -762,8 +872,8 @@ export const OxyRuntimeProvider = ({
|
|
|
762
872
|
// Native is untouched: its apps already share a device through the keychain.
|
|
763
873
|
useEffect(() => {
|
|
764
874
|
if (!isWebBrowser()) return undefined;
|
|
765
|
-
return oxyServices.session.setDeviceCredentialProvider(() => loadPersistedDeviceCredential(authStore));
|
|
766
|
-
}, [oxyServices, authStore]);
|
|
875
|
+
return oxyServices.session.setDeviceCredentialProvider(() => registeredLaneRef.current.lane === 'device' && !hasIsolatedOAuthSession(runtime) ? loadPersistedDeviceCredential(authStore) : Promise.resolve(null));
|
|
876
|
+
}, [oxyServices, authStore, runtime]);
|
|
767
877
|
|
|
768
878
|
// ── The browser bridge (ADR 0029 D2) ──────────────────────────────────────
|
|
769
879
|
// The first time a person presses sign-in in this app on the web and it holds
|
|
@@ -776,7 +886,7 @@ export const OxyRuntimeProvider = ({
|
|
|
776
886
|
const bridgeInFlightRef = useRef(false);
|
|
777
887
|
const closeAccountDialogRef = useRef(() => undefined);
|
|
778
888
|
const startBrowserBridge = useCallback(() => {
|
|
779
|
-
if (isIdentityBound || !clientId || !isWebBrowser() || bridgeInFlightRef.current) return;
|
|
889
|
+
if (registeredLaneRef.current.lane !== 'device' || hasIsolatedOAuthSession(runtime) || isIdentityBound || !clientId || !isWebBrowser() || bridgeInFlightRef.current) return;
|
|
780
890
|
if (authStoreRef.current?.heldDeviceCredential() !== null) return;
|
|
781
891
|
const bridgeOrigin = resolveBridgeOrigin(authorizeBaseUrl);
|
|
782
892
|
const pageOrigin = globalThis.location?.origin;
|
|
@@ -831,8 +941,10 @@ export const OxyRuntimeProvider = ({
|
|
|
831
941
|
}).finally(() => {
|
|
832
942
|
bridgeInFlightRef.current = false;
|
|
833
943
|
});
|
|
834
|
-
}, [isIdentityBound, clientId, authorizeBaseUrl, authRedirectUri, oxyServices, authStore, sessionClientHost, logger]);
|
|
835
|
-
const
|
|
944
|
+
}, [isIdentityBound, clientId, authorizeBaseUrl, authRedirectUri, oxyServices, authStore, sessionClientHost, logger, runtime]);
|
|
945
|
+
const openClassifiedAccountDialog = useCallback(view => {
|
|
946
|
+
if (registeredLaneRef.current.clientId !== clientIdProp || registeredLaneRef.current.services !== oxyServices) return;
|
|
947
|
+
if (registeredLaneRef.current.lane !== 'device' || hasIsolatedOAuthSession(runtime)) return;
|
|
836
948
|
if (isIdentityBound) {
|
|
837
949
|
// No controller was built, and there is nothing to choose: this app's user
|
|
838
950
|
// is fixed to the owner of the local identity key.
|
|
@@ -895,7 +1007,24 @@ export const OxyRuntimeProvider = ({
|
|
|
895
1007
|
}
|
|
896
1008
|
});
|
|
897
1009
|
setAccountDialogOpen(true);
|
|
898
|
-
}, [isIdentityBound, startBrowserBridge]);
|
|
1010
|
+
}, [isIdentityBound, startBrowserBridge, runtime, clientIdProp, oxyServices]);
|
|
1011
|
+
const openAccountDialog = useCallback(view => {
|
|
1012
|
+
if (registeredLaneRef.current.clientId !== clientIdProp || registeredLaneRef.current.services !== oxyServices) return;
|
|
1013
|
+
if (registeredLaneRef.current.lane === 'device') {
|
|
1014
|
+
// Preserve the browser bridge's synchronous user-gesture path.
|
|
1015
|
+
openClassifiedAccountDialog(view);
|
|
1016
|
+
return;
|
|
1017
|
+
}
|
|
1018
|
+
void Promise.resolve().then(() => ensureDeviceSessionLane()).then(() => openClassifiedAccountDialog(view)).catch(error => {
|
|
1019
|
+
handleAuthError(error, {
|
|
1020
|
+
defaultMessage: 'Sign in failed',
|
|
1021
|
+
code: 'LOGIN_ERROR',
|
|
1022
|
+
onError,
|
|
1023
|
+
setAuthError: message => runtime.setError(message),
|
|
1024
|
+
logger
|
|
1025
|
+
});
|
|
1026
|
+
});
|
|
1027
|
+
}, [ensureDeviceSessionLane, openClassifiedAccountDialog, onError, runtime, logger, clientIdProp, oxyServices]);
|
|
899
1028
|
const closeAccountDialog = useCallback(() => {
|
|
900
1029
|
accountDialogControllerRef.current?.cancelSignIn();
|
|
901
1030
|
dismissAccountDialogSurface();
|
|
@@ -938,9 +1067,6 @@ export const OxyRuntimeProvider = ({
|
|
|
938
1067
|
// SYNCHRONOUS read on `SessionClient`'s apply path, and a stale `null` there
|
|
939
1068
|
// would let a pinned client behave like an account-mode one for the first
|
|
940
1069
|
// state it applies (including re-electing the device's active account).
|
|
941
|
-
if (identity) {
|
|
942
|
-
await identity.ensurePinnedAccountId();
|
|
943
|
-
}
|
|
944
1070
|
await runProviderColdBoot({
|
|
945
1071
|
oxyServices,
|
|
946
1072
|
authStore,
|
|
@@ -948,6 +1074,13 @@ export const OxyRuntimeProvider = ({
|
|
|
948
1074
|
authRedirectUri,
|
|
949
1075
|
sessionMode,
|
|
950
1076
|
identity: identity?.binding,
|
|
1077
|
+
resolveSessionLane: resolveRegisteredLane,
|
|
1078
|
+
beforeDeviceBoot: identity ? async () => {
|
|
1079
|
+
await identity.ensurePinnedAccountId();
|
|
1080
|
+
} : undefined,
|
|
1081
|
+
afterDeviceBoot: identity ? async () => {
|
|
1082
|
+
await identity.refreshPinnedAccountId();
|
|
1083
|
+
} : undefined,
|
|
951
1084
|
sessionClient,
|
|
952
1085
|
syncDeviceCredentialToHost,
|
|
953
1086
|
commitSession: (input, options) => commitSessionRef.current(input, options),
|
|
@@ -957,10 +1090,7 @@ export const OxyRuntimeProvider = ({
|
|
|
957
1090
|
// The boot may have (re-)established the identity session or cleared a pin
|
|
958
1091
|
// whose key no longer exists, so re-resolve rather than trusting the memo
|
|
959
1092
|
// taken before it ran.
|
|
960
|
-
|
|
961
|
-
await identity.refreshPinnedAccountId();
|
|
962
|
-
}
|
|
963
|
-
}, [oxyServices, authStore, clientIdProp, authRedirectUri, sessionMode, identity, syncDeviceCredentialToHost, sessionClient, setTokenReady]);
|
|
1093
|
+
}, [resolveRegisteredLane, oxyServices, authStore, clientIdProp, authRedirectUri, sessionMode, identity, syncDeviceCredentialToHost, sessionClient, setTokenReady]);
|
|
964
1094
|
useEffect(() => {
|
|
965
1095
|
if (initialized) {
|
|
966
1096
|
return;
|
|
@@ -976,30 +1106,51 @@ export const OxyRuntimeProvider = ({
|
|
|
976
1106
|
});
|
|
977
1107
|
}, [runColdBoot, storage, initialized, logger]);
|
|
978
1108
|
|
|
979
|
-
// Reconcile device state
|
|
980
|
-
// miss
|
|
1109
|
+
// Reconcile device state on foreground: suspended native apps and background
|
|
1110
|
+
// tabs may miss a sibling's active-context switch or socket pushes.
|
|
981
1111
|
useEffect(() => {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
//
|
|
989
|
-
// double-rotate the device secret against them.
|
|
1112
|
+
let disposed = false;
|
|
1113
|
+
let pending = null;
|
|
1114
|
+
const reconcile = () => {
|
|
1115
|
+
if (disposed || pending || hasIsolatedOAuthSession(runtime)) return;
|
|
1116
|
+
pending = (async () => {
|
|
1117
|
+
if (!isWebBrowser() && !identity || !oxyServices.session.accessToken && sessionClientHost.getDeviceCredential()) {
|
|
1118
|
+
// The scheduler/preflight/401 paths own the same mint single-flight.
|
|
990
1119
|
await oxyServices.http.refreshAccessToken('preflight');
|
|
991
1120
|
}
|
|
1121
|
+
if (disposed || hasIsolatedOAuthSession(runtime)) return;
|
|
1122
|
+
if (!isWebBrowser() && !identity) await syncDeviceCredentialToHost();
|
|
992
1123
|
if (!oxyServices.session.accessToken && !sessionClientHost.getDeviceCredential()) {
|
|
993
1124
|
return;
|
|
994
1125
|
}
|
|
995
1126
|
await sessionClient.bootstrap();
|
|
1127
|
+
if (disposed || hasIsolatedOAuthSession(runtime)) return;
|
|
996
1128
|
await syncFromClient();
|
|
1129
|
+
})().catch(() => undefined).finally(() => {
|
|
1130
|
+
pending = null;
|
|
1131
|
+
});
|
|
1132
|
+
};
|
|
1133
|
+
if (isWebBrowser()) {
|
|
1134
|
+
const onVisibility = () => {
|
|
1135
|
+
if (document.visibilityState === 'visible') reconcile();
|
|
1136
|
+
};
|
|
1137
|
+
document.addEventListener('visibilitychange', onVisibility);
|
|
1138
|
+
return () => {
|
|
1139
|
+
disposed = true;
|
|
1140
|
+
document.removeEventListener('visibilitychange', onVisibility);
|
|
997
1141
|
};
|
|
998
|
-
|
|
1142
|
+
}
|
|
1143
|
+
let previousState = AppState.currentState;
|
|
1144
|
+
const subscription = AppState.addEventListener('change', state => {
|
|
1145
|
+
const resumed = state === 'active' && (previousState === 'inactive' || previousState === 'background');
|
|
1146
|
+
previousState = state;
|
|
1147
|
+
if (resumed) reconcile();
|
|
1148
|
+
});
|
|
1149
|
+
return () => {
|
|
1150
|
+
disposed = true;
|
|
1151
|
+
subscription.remove();
|
|
999
1152
|
};
|
|
1000
|
-
|
|
1001
|
-
return () => document.removeEventListener('visibilitychange', onVisibility);
|
|
1002
|
-
}, [oxyServices, sessionClient, sessionClientHost, syncFromClient]);
|
|
1153
|
+
}, [oxyServices, sessionClient, sessionClientHost, syncFromClient, syncDeviceCredentialToHost, identity, runtime]);
|
|
1003
1154
|
|
|
1004
1155
|
// Reconnect heal: when connectivity transitions offline→online while there is
|
|
1005
1156
|
// no live access token but a persisted device credential exists, re-mint ONCE
|
|
@@ -1023,6 +1174,7 @@ export const OxyRuntimeProvider = ({
|
|
|
1023
1174
|
return;
|
|
1024
1175
|
}
|
|
1025
1176
|
void (async () => {
|
|
1177
|
+
if (hasIsolatedOAuthSession(runtime)) return;
|
|
1026
1178
|
if (oxyServices.session.accessToken || !sessionClientHost.getDeviceCredential()) {
|
|
1027
1179
|
return;
|
|
1028
1180
|
}
|
|
@@ -1034,14 +1186,15 @@ export const OxyRuntimeProvider = ({
|
|
|
1034
1186
|
await syncFromClient();
|
|
1035
1187
|
})().catch(() => undefined);
|
|
1036
1188
|
});
|
|
1037
|
-
}, [oxyServices, sessionClient, sessionClientHost, syncFromClient]);
|
|
1189
|
+
}, [oxyServices, sessionClient, sessionClientHost, syncFromClient, runtime]);
|
|
1038
1190
|
|
|
1039
1191
|
// Exposed `refreshSessions`: re-bootstrap the server-authoritative device
|
|
1040
1192
|
// state and reproject — the manual counterpart to the realtime socket.
|
|
1041
1193
|
const refreshSessionsForContext = useCallback(async () => {
|
|
1194
|
+
if (hasIsolatedOAuthSession(runtime)) throw new Error('An isolated OAuth session has no shared device sessions');
|
|
1042
1195
|
await sessionClient.bootstrap();
|
|
1043
1196
|
await syncFromClient();
|
|
1044
|
-
}, [sessionClient, syncFromClient]);
|
|
1197
|
+
}, [sessionClient, syncFromClient, runtime]);
|
|
1045
1198
|
|
|
1046
1199
|
// Exposed `switchSession`: route through the server-authoritative
|
|
1047
1200
|
// `SessionClient`. Resolve the target account from the current device state,
|
|
@@ -1050,6 +1203,7 @@ export const OxyRuntimeProvider = ({
|
|
|
1050
1203
|
// Identity-bound providers reject: this is the session-keyed twin of
|
|
1051
1204
|
// `switchToAccount`, so leaving it live would be a bypass around the same rule.
|
|
1052
1205
|
const switchSessionForContext = useCallback(async sessionId => {
|
|
1206
|
+
if (hasIsolatedOAuthSession(runtime)) throw new Error('An isolated OAuth session cannot switch device sessions');
|
|
1053
1207
|
if (isIdentityBound) {
|
|
1054
1208
|
throw new IdentityBoundSessionError('switchSession');
|
|
1055
1209
|
}
|
|
@@ -1096,6 +1250,7 @@ export const OxyRuntimeProvider = ({
|
|
|
1096
1250
|
tokenReady,
|
|
1097
1251
|
initialized,
|
|
1098
1252
|
identityBound: isIdentityBound,
|
|
1253
|
+
isolatedOAuth: readIsolatedOAuthSession(runtime) !== null,
|
|
1099
1254
|
oxyServices,
|
|
1100
1255
|
sessionClient,
|
|
1101
1256
|
syncFromClient,
|
|
@@ -1182,6 +1337,7 @@ export const OxyRuntimeProvider = ({
|
|
|
1182
1337
|
revokeSuspiciousSignIn,
|
|
1183
1338
|
handleWebSession,
|
|
1184
1339
|
startWebOAuthSignIn: startWebOAuthSignInForContext,
|
|
1340
|
+
startNativeOAuthSignIn: startNativeOAuthSignInForContext,
|
|
1185
1341
|
requestOAuthConsent: requestOAuthConsentForContext,
|
|
1186
1342
|
logout,
|
|
1187
1343
|
logoutAll,
|
|
@@ -1209,8 +1365,9 @@ export const OxyRuntimeProvider = ({
|
|
|
1209
1365
|
switchToAccount,
|
|
1210
1366
|
refreshAccounts,
|
|
1211
1367
|
createAccount: createAccountFn
|
|
1212
|
-
}), [user, sessions, activeSessionId, isAuthenticated, isLoading, tokenReady, hasAccessToken, canUsePrivateApi, isPrivateApiPending, authResolved, snapshot.storageReady, isAccountCacheReady, isIdentityBound, webAuthMode, error, currentLanguage, currentLanguages, currentLanguageMetadata, currentLanguageName, currentNativeLanguageName, hasIdentity, getPublicKey, signIn, revokeSuspiciousSignIn, handleWebSession, startWebOAuthSignInForContext, requestOAuthConsentForContext, logout, logoutAll, switchSessionForContext, refreshSessionsForContext, setLanguage, getDeviceSessions, logoutAllDeviceSessions, updateDeviceName, clearSessionState, clearAllAccountData, storageKeyPrefix, clientId, oxyServices, sessionClient, showBottomSheetForContext, openAvatarPicker, accountDialogController, accountDialogOpen, openAccountDialog, closeAccountDialog, accounts, switchToAccount, refreshAccounts, createAccountFn]);
|
|
1368
|
+
}), [user, sessions, activeSessionId, isAuthenticated, isLoading, tokenReady, hasAccessToken, canUsePrivateApi, isPrivateApiPending, authResolved, snapshot.storageReady, isAccountCacheReady, isIdentityBound, webAuthMode, error, currentLanguage, currentLanguages, currentLanguageMetadata, currentLanguageName, currentNativeLanguageName, hasIdentity, getPublicKey, signIn, revokeSuspiciousSignIn, handleWebSession, startWebOAuthSignInForContext, startNativeOAuthSignInForContext, requestOAuthConsentForContext, logout, logoutAll, switchSessionForContext, refreshSessionsForContext, setLanguage, getDeviceSessions, logoutAllDeviceSessions, updateDeviceName, clearSessionState, clearAllAccountData, storageKeyPrefix, clientId, oxyServices, sessionClient, showBottomSheetForContext, openAvatarPicker, accountDialogController, accountDialogOpen, openAccountDialog, closeAccountDialog, accounts, switchToAccount, refreshAccounts, createAccountFn]);
|
|
1213
1369
|
const authActionsValue = useMemo(() => ({
|
|
1370
|
+
ensureDeviceSessionLane,
|
|
1214
1371
|
signIn,
|
|
1215
1372
|
logout,
|
|
1216
1373
|
logoutAll,
|
|
@@ -1222,7 +1379,7 @@ export const OxyRuntimeProvider = ({
|
|
|
1222
1379
|
showBottomSheet: showBottomSheetForContext,
|
|
1223
1380
|
openAvatarPicker,
|
|
1224
1381
|
openAccountDialog
|
|
1225
|
-
}), [signIn, logout, logoutAll, refreshSessionsForContext, oxyServices, switchToAccount, hasIdentity, getPublicKey, showBottomSheetForContext, openAvatarPicker, openAccountDialog]);
|
|
1382
|
+
}), [ensureDeviceSessionLane, signIn, logout, logoutAll, refreshSessionsForContext, oxyServices, switchToAccount, hasIdentity, getPublicKey, showBottomSheetForContext, openAvatarPicker, openAccountDialog]);
|
|
1226
1383
|
|
|
1227
1384
|
// Two contexts, deliberately. The inner one carries the wide compatibility
|
|
1228
1385
|
// value every `useOxy()` consumer reads, rebuilt whenever any of its members
|