@oxyhq/services 16.0.0 → 18.0.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/README.md +77 -98
- package/lib/commonjs/index.js +40 -51
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/ui/client.js +0 -14
- package/lib/commonjs/ui/client.js.map +1 -1
- package/lib/commonjs/ui/components/OxyAccountDialog.js +742 -0
- package/lib/commonjs/ui/components/OxyAccountDialog.js.map +1 -0
- package/lib/commonjs/ui/components/OxyConsentScreen.js +461 -0
- package/lib/commonjs/ui/components/OxyConsentScreen.js.map +1 -0
- package/lib/commonjs/ui/components/OxyProvider.js +13 -6
- package/lib/commonjs/ui/components/OxyProvider.js.map +1 -1
- package/lib/commonjs/ui/components/OxySignInButton.js +180 -22
- package/lib/commonjs/ui/components/OxySignInButton.js.map +1 -1
- package/lib/commonjs/ui/components/ProfileButton.js +25 -112
- package/lib/commonjs/ui/components/ProfileButton.js.map +1 -1
- package/lib/commonjs/ui/components/RequireOxyAuth.js +299 -0
- package/lib/commonjs/ui/components/RequireOxyAuth.js.map +1 -0
- package/lib/commonjs/ui/components/oauthNavigation.js +73 -0
- package/lib/commonjs/ui/components/oauthNavigation.js.map +1 -0
- package/lib/commonjs/ui/context/OxyContext.js +122 -4
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/hooks/mutations/useAccountMutations.js +1 -1
- package/lib/commonjs/ui/hooks/useAuth.js +19 -30
- package/lib/commonjs/ui/hooks/useAuth.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js +37 -267
- package/lib/commonjs/ui/hooks/useSwitchableAccounts.js.map +1 -1
- package/lib/commonjs/ui/index.js +5 -40
- package/lib/commonjs/ui/index.js.map +1 -1
- package/lib/commonjs/ui/navigation/accountDialogManager.js +91 -0
- package/lib/commonjs/ui/navigation/accountDialogManager.js.map +1 -0
- package/lib/commonjs/ui/navigation/routes.js +0 -2
- package/lib/commonjs/ui/navigation/routes.js.map +1 -1
- package/lib/commonjs/ui/screens/ManageAccountScreen.js +4 -3
- package/lib/commonjs/ui/screens/ManageAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/session/createSessionClient.js +10 -2
- package/lib/commonjs/ui/session/createSessionClient.js.map +1 -1
- package/lib/module/index.js +19 -16
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/client.js +1 -2
- package/lib/module/ui/client.js.map +1 -1
- package/lib/module/ui/components/OxyAccountDialog.js +739 -0
- package/lib/module/ui/components/OxyAccountDialog.js.map +1 -0
- package/lib/module/ui/components/OxyConsentScreen.js +454 -0
- package/lib/module/ui/components/OxyConsentScreen.js.map +1 -0
- package/lib/module/ui/components/OxyProvider.js +13 -6
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/OxySignInButton.js +181 -22
- package/lib/module/ui/components/OxySignInButton.js.map +1 -1
- package/lib/module/ui/components/ProfileButton.js +26 -112
- package/lib/module/ui/components/ProfileButton.js.map +1 -1
- package/lib/module/ui/components/RequireOxyAuth.js +294 -0
- package/lib/module/ui/components/RequireOxyAuth.js.map +1 -0
- package/lib/module/ui/components/oauthNavigation.js +70 -0
- package/lib/module/ui/components/oauthNavigation.js.map +1 -0
- package/lib/module/ui/context/OxyContext.js +123 -5
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/hooks/mutations/useAccountMutations.js +1 -1
- package/lib/module/ui/hooks/useAuth.js +19 -30
- package/lib/module/ui/hooks/useAuth.js.map +1 -1
- package/lib/module/ui/hooks/useSwitchableAccounts.js +38 -267
- package/lib/module/ui/hooks/useSwitchableAccounts.js.map +1 -1
- package/lib/module/ui/index.js +1 -5
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/navigation/accountDialogManager.js +81 -0
- package/lib/module/ui/navigation/accountDialogManager.js.map +1 -0
- package/lib/module/ui/navigation/routes.js +0 -2
- package/lib/module/ui/navigation/routes.js.map +1 -1
- package/lib/module/ui/screens/ManageAccountScreen.js +4 -3
- package/lib/module/ui/screens/ManageAccountScreen.js.map +1 -1
- package/lib/module/ui/session/createSessionClient.js +10 -2
- package/lib/module/ui/session/createSessionClient.js.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +8 -12
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/client.d.ts +0 -4
- package/lib/typescript/commonjs/ui/client.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyAccountDialog.d.ts +51 -0
- package/lib/typescript/commonjs/ui/components/OxyAccountDialog.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/OxyConsentScreen.d.ts +45 -0
- package/lib/typescript/commonjs/ui/components/OxyConsentScreen.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts +2 -2
- package/lib/typescript/commonjs/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts +56 -0
- package/lib/typescript/commonjs/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts +11 -23
- package/lib/typescript/commonjs/ui/components/ProfileButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/RequireOxyAuth.d.ts +55 -0
- package/lib/typescript/commonjs/ui/components/RequireOxyAuth.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/oauthNavigation.d.ts +36 -0
- package/lib/typescript/commonjs/ui/components/oauthNavigation.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +27 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts +13 -152
- package/lib/typescript/commonjs/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/index.d.ts +2 -5
- package/lib/typescript/commonjs/ui/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts +49 -0
- package/lib/typescript/commonjs/ui/navigation/accountDialogManager.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/commonjs/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts +1 -1
- package/lib/typescript/commonjs/ui/screens/ManageAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts +9 -2
- package/lib/typescript/commonjs/ui/session/createSessionClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/types/navigation.d.ts +27 -0
- package/lib/typescript/commonjs/ui/types/navigation.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +8 -12
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/client.d.ts +0 -4
- package/lib/typescript/module/ui/client.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyAccountDialog.d.ts +51 -0
- package/lib/typescript/module/ui/components/OxyAccountDialog.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/OxyConsentScreen.d.ts +45 -0
- package/lib/typescript/module/ui/components/OxyConsentScreen.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/OxyProvider.d.ts +2 -2
- package/lib/typescript/module/ui/components/OxyProvider.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts +56 -0
- package/lib/typescript/module/ui/components/OxySignInButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/ProfileButton.d.ts +11 -23
- package/lib/typescript/module/ui/components/ProfileButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/RequireOxyAuth.d.ts +55 -0
- package/lib/typescript/module/ui/components/RequireOxyAuth.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/oauthNavigation.d.ts +36 -0
- package/lib/typescript/module/ui/components/oauthNavigation.d.ts.map +1 -0
- package/lib/typescript/module/ui/context/OxyContext.d.ts +27 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts +1 -1
- package/lib/typescript/module/ui/hooks/queries/useServicesQueries.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useAuth.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts +13 -152
- package/lib/typescript/module/ui/hooks/useSwitchableAccounts.d.ts.map +1 -1
- package/lib/typescript/module/ui/index.d.ts +2 -5
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts +49 -0
- package/lib/typescript/module/ui/navigation/accountDialogManager.d.ts.map +1 -0
- package/lib/typescript/module/ui/navigation/routes.d.ts +1 -1
- package/lib/typescript/module/ui/navigation/routes.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts +1 -1
- package/lib/typescript/module/ui/screens/ManageAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/session/createSessionClient.d.ts +9 -2
- package/lib/typescript/module/ui/session/createSessionClient.d.ts.map +1 -1
- package/lib/typescript/module/ui/types/navigation.d.ts +27 -0
- package/lib/typescript/module/ui/types/navigation.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +33 -27
- package/src/ui/client.ts +0 -4
- package/src/ui/components/OxyAccountDialog.tsx +735 -0
- package/src/ui/components/OxyConsentScreen.tsx +456 -0
- package/src/ui/components/OxyProvider.tsx +14 -6
- package/src/ui/components/OxySignInButton.tsx +227 -22
- package/src/ui/components/ProfileButton.tsx +23 -126
- package/src/ui/components/RequireOxyAuth.tsx +266 -0
- package/src/ui/components/__tests__/OxyConsentScreen.test.tsx +130 -0
- package/src/ui/components/oauthNavigation.ts +89 -0
- package/src/ui/context/OxyContext.tsx +176 -9
- package/src/ui/context/__tests__/OxyContext.coldBoot.test.tsx +165 -0
- package/src/ui/hooks/mutations/useAccountMutations.ts +1 -1
- package/src/ui/hooks/useAuth.ts +19 -31
- package/src/ui/hooks/useSwitchableAccounts.ts +42 -376
- package/src/ui/index.ts +2 -5
- package/src/ui/navigation/accountDialogManager.ts +84 -0
- package/src/ui/navigation/routes.ts +0 -4
- package/src/ui/screens/ManageAccountScreen.tsx +3 -2
- package/src/ui/session/createSessionClient.ts +9 -1
- package/src/ui/types/navigation.ts +27 -0
- package/lib/commonjs/ui/components/AccountMenu.js +0 -598
- package/lib/commonjs/ui/components/AccountMenu.js.map +0 -1
- package/lib/commonjs/ui/components/AccountMenuButton.js +0 -135
- package/lib/commonjs/ui/components/AccountMenuButton.js.map +0 -1
- package/lib/commonjs/ui/components/AccountSwitcher.js +0 -780
- package/lib/commonjs/ui/components/AccountSwitcher.js.map +0 -1
- package/lib/commonjs/ui/components/AnotherDeviceQR.js +0 -116
- package/lib/commonjs/ui/components/AnotherDeviceQR.js.map +0 -1
- package/lib/commonjs/ui/components/ProfileMenu.js +0 -518
- package/lib/commonjs/ui/components/ProfileMenu.js.map +0 -1
- package/lib/commonjs/ui/components/SignInAccountChooser.js +0 -189
- package/lib/commonjs/ui/components/SignInAccountChooser.js.map +0 -1
- package/lib/commonjs/ui/components/SignInModal.js +0 -600
- package/lib/commonjs/ui/components/SignInModal.js.map +0 -1
- package/lib/commonjs/ui/hooks/useOxyAuthSession.js +0 -501
- package/lib/commonjs/ui/hooks/useOxyAuthSession.js.map +0 -1
- package/lib/commonjs/ui/hooks/usePasswordSignIn.js +0 -170
- package/lib/commonjs/ui/hooks/usePasswordSignIn.js.map +0 -1
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js +0 -51
- package/lib/commonjs/ui/screens/AccountSwitcherScreen.js.map +0 -1
- package/lib/commonjs/ui/screens/OxyAuthScreen.js +0 -312
- package/lib/commonjs/ui/screens/OxyAuthScreen.js.map +0 -1
- package/lib/commonjs/utils/deviceFlowSignIn.js +0 -109
- package/lib/commonjs/utils/deviceFlowSignIn.js.map +0 -1
- package/lib/module/ui/components/AccountMenu.js +0 -593
- package/lib/module/ui/components/AccountMenu.js.map +0 -1
- package/lib/module/ui/components/AccountMenuButton.js +0 -130
- package/lib/module/ui/components/AccountMenuButton.js.map +0 -1
- package/lib/module/ui/components/AccountSwitcher.js +0 -774
- package/lib/module/ui/components/AccountSwitcher.js.map +0 -1
- package/lib/module/ui/components/AnotherDeviceQR.js +0 -110
- package/lib/module/ui/components/AnotherDeviceQR.js.map +0 -1
- package/lib/module/ui/components/ProfileMenu.js +0 -514
- package/lib/module/ui/components/ProfileMenu.js.map +0 -1
- package/lib/module/ui/components/SignInAccountChooser.js +0 -183
- package/lib/module/ui/components/SignInAccountChooser.js.map +0 -1
- package/lib/module/ui/components/SignInModal.js +0 -591
- package/lib/module/ui/components/SignInModal.js.map +0 -1
- package/lib/module/ui/hooks/useOxyAuthSession.js +0 -495
- package/lib/module/ui/hooks/useOxyAuthSession.js.map +0 -1
- package/lib/module/ui/hooks/usePasswordSignIn.js +0 -165
- package/lib/module/ui/hooks/usePasswordSignIn.js.map +0 -1
- package/lib/module/ui/screens/AccountSwitcherScreen.js +0 -48
- package/lib/module/ui/screens/AccountSwitcherScreen.js.map +0 -1
- package/lib/module/ui/screens/OxyAuthScreen.js +0 -306
- package/lib/module/ui/screens/OxyAuthScreen.js.map +0 -1
- package/lib/module/utils/deviceFlowSignIn.js +0 -106
- package/lib/module/utils/deviceFlowSignIn.js.map +0 -1
- package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts +0 -47
- package/lib/typescript/commonjs/ui/components/AccountMenu.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts +0 -26
- package/lib/typescript/commonjs/ui/components/AccountMenuButton.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts +0 -46
- package/lib/typescript/commonjs/ui/components/AccountSwitcher.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts +0 -34
- package/lib/typescript/commonjs/ui/components/AnotherDeviceQR.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts +0 -49
- package/lib/typescript/commonjs/ui/components/ProfileMenu.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/SignInAccountChooser.d.ts +0 -29
- package/lib/typescript/commonjs/ui/components/SignInAccountChooser.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/components/SignInModal.d.ts +0 -28
- package/lib/typescript/commonjs/ui/components/SignInModal.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts +0 -105
- package/lib/typescript/commonjs/ui/hooks/useOxyAuthSession.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/hooks/usePasswordSignIn.d.ts +0 -31
- package/lib/typescript/commonjs/ui/hooks/usePasswordSignIn.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts +0 -11
- package/lib/typescript/commonjs/ui/screens/AccountSwitcherScreen.d.ts.map +0 -1
- package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts +0 -22
- package/lib/typescript/commonjs/ui/screens/OxyAuthScreen.d.ts.map +0 -1
- package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts +0 -97
- package/lib/typescript/commonjs/utils/deviceFlowSignIn.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/AccountMenu.d.ts +0 -47
- package/lib/typescript/module/ui/components/AccountMenu.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/AccountMenuButton.d.ts +0 -26
- package/lib/typescript/module/ui/components/AccountMenuButton.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/AccountSwitcher.d.ts +0 -46
- package/lib/typescript/module/ui/components/AccountSwitcher.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts +0 -34
- package/lib/typescript/module/ui/components/AnotherDeviceQR.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/ProfileMenu.d.ts +0 -49
- package/lib/typescript/module/ui/components/ProfileMenu.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/SignInAccountChooser.d.ts +0 -29
- package/lib/typescript/module/ui/components/SignInAccountChooser.d.ts.map +0 -1
- package/lib/typescript/module/ui/components/SignInModal.d.ts +0 -28
- package/lib/typescript/module/ui/components/SignInModal.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts +0 -105
- package/lib/typescript/module/ui/hooks/useOxyAuthSession.d.ts.map +0 -1
- package/lib/typescript/module/ui/hooks/usePasswordSignIn.d.ts +0 -31
- package/lib/typescript/module/ui/hooks/usePasswordSignIn.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts +0 -11
- package/lib/typescript/module/ui/screens/AccountSwitcherScreen.d.ts.map +0 -1
- package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts +0 -22
- package/lib/typescript/module/ui/screens/OxyAuthScreen.d.ts.map +0 -1
- package/lib/typescript/module/utils/deviceFlowSignIn.d.ts +0 -97
- package/lib/typescript/module/utils/deviceFlowSignIn.d.ts.map +0 -1
- package/src/ui/components/AccountMenu.tsx +0 -645
- package/src/ui/components/AccountMenuButton.tsx +0 -126
- package/src/ui/components/AccountSwitcher.tsx +0 -751
- package/src/ui/components/AnotherDeviceQR.tsx +0 -119
- package/src/ui/components/ProfileMenu.tsx +0 -564
- package/src/ui/components/SignInAccountChooser.tsx +0 -162
- package/src/ui/components/SignInModal.tsx +0 -530
- package/src/ui/hooks/useOxyAuthSession.ts +0 -635
- package/src/ui/hooks/usePasswordSignIn.ts +0 -207
- package/src/ui/screens/AccountSwitcherScreen.tsx +0 -43
- package/src/ui/screens/OxyAuthScreen.tsx +0 -324
- package/src/utils/__tests__/deviceFlowSignIn.test.ts +0 -231
- package/src/utils/deviceFlowSignIn.ts +0 -152
|
@@ -1,495 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* useOxyAuthSession — the single shared engine for the cross-app device-flow
|
|
5
|
-
* sign-in ("Sign in with Oxy") used by BOTH containers:
|
|
6
|
-
*
|
|
7
|
-
* - `SignInModal` (web centered modal)
|
|
8
|
-
* - `OxyAuthScreen` (native bottom sheet)
|
|
9
|
-
*
|
|
10
|
-
* Before this hook existed, those two files each re-implemented ~90% of the
|
|
11
|
-
* same auth-session machinery (session-token creation, QR data, socket.io
|
|
12
|
-
* `/auth-session` subscription, the HTTP polling fallback, waiting/error/retry
|
|
13
|
-
* state, the open-auth handler, and cleanup) — and they had drifted (notably a
|
|
14
|
-
* weaker `Math.random()` session token on native vs the crypto-secure one on
|
|
15
|
-
* web). This hook owns ALL of it ONCE, with a clean typed surface, so the
|
|
16
|
-
* containers only own their layout. The transport is functionally identical to
|
|
17
|
-
* the previous implementations — this is a structural de-duplication, not a
|
|
18
|
-
* behavior change.
|
|
19
|
-
*
|
|
20
|
-
* The native-only deep-link return path (`Linking` redirect handling) lives
|
|
21
|
-
* HERE, gated to native via `Platform.OS`, so the web container never carries
|
|
22
|
-
* native-only code while the two paths still cannot drift.
|
|
23
|
-
*/
|
|
24
|
-
|
|
25
|
-
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
26
|
-
import { Linking, Platform } from 'react-native';
|
|
27
|
-
import io from 'socket.io-client';
|
|
28
|
-
import { createDebugLogger } from '@oxyhq/core';
|
|
29
|
-
import { completeDeviceFlowSignIn } from "../../utils/deviceFlowSignIn.js";
|
|
30
|
-
const debug = createDebugLogger('useOxyAuthSession');
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Default destination for the "Create an Oxy account" / "Get Oxy Accounts"
|
|
34
|
-
* link, shared by both containers. Reused as-is from the original native
|
|
35
|
-
* `OxyAuthScreen` so no new route is invented.
|
|
36
|
-
*/
|
|
37
|
-
export const OXY_ACCOUNTS_WEB_URL = 'https://accounts.oxy.so';
|
|
38
|
-
|
|
39
|
-
/** Default central Oxy auth web origin used when no override can be resolved. */
|
|
40
|
-
export const OXY_AUTH_WEB_URL = 'https://auth.oxy.so';
|
|
41
|
-
|
|
42
|
-
/** Auth session expiration (5 minutes). */
|
|
43
|
-
export const AUTH_SESSION_EXPIRY_MS = 5 * 60 * 1000;
|
|
44
|
-
|
|
45
|
-
/** Polling interval (fallback if the socket fails) in milliseconds. */
|
|
46
|
-
export const POLLING_INTERVAL_MS = 3000;
|
|
47
|
-
|
|
48
|
-
/** The active device-flow session this client created and is waiting on. */
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Extended `POST /auth/session/create` response (the "Sign in with Oxy" handoff
|
|
52
|
-
* fields, Workstream C2). Both are optional so this hook degrades gracefully
|
|
53
|
-
* when the handoff backend is not yet deployed — the legacy `oxyauth://<token>`
|
|
54
|
-
* QR (`qrData`) remains the fallback.
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
/** Real-time auth-session socket payload (also matches the poll status shape). */
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Resolve the central Oxy auth web origin from config or the API base URL.
|
|
61
|
-
* Mirrors the resolution both containers previously inlined.
|
|
62
|
-
*/
|
|
63
|
-
function resolveAuthWebBaseUrl(baseURL, authWebUrl) {
|
|
64
|
-
if (authWebUrl) {
|
|
65
|
-
return authWebUrl;
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
const url = new URL(baseURL);
|
|
69
|
-
if (url.port === '3001') {
|
|
70
|
-
url.port = '3002';
|
|
71
|
-
return url.origin;
|
|
72
|
-
}
|
|
73
|
-
if (url.hostname.startsWith('api.')) {
|
|
74
|
-
url.hostname = `auth.${url.hostname.slice(4)}`;
|
|
75
|
-
return url.origin;
|
|
76
|
-
}
|
|
77
|
-
} catch {
|
|
78
|
-
// Malformed base URL — fall back to the default origin below.
|
|
79
|
-
}
|
|
80
|
-
return OXY_AUTH_WEB_URL;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Resolve the deep-link redirect URI used on native so the auth web flow can
|
|
85
|
-
* bounce back into the app. Prefers an explicit config value, otherwise derives
|
|
86
|
-
* a clean (query/hash-stripped) URI from the app's initial deep link.
|
|
87
|
-
*/
|
|
88
|
-
async function resolveAuthRedirectUri(authRedirectUri) {
|
|
89
|
-
if (authRedirectUri) {
|
|
90
|
-
return authRedirectUri;
|
|
91
|
-
}
|
|
92
|
-
try {
|
|
93
|
-
const initialUrl = await Linking.getInitialURL();
|
|
94
|
-
if (!initialUrl) {
|
|
95
|
-
return null;
|
|
96
|
-
}
|
|
97
|
-
const parsed = new URL(initialUrl);
|
|
98
|
-
parsed.search = '';
|
|
99
|
-
parsed.hash = '';
|
|
100
|
-
return parsed.toString();
|
|
101
|
-
} catch {
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
/** Parse the `session_id` / `error` params from a deep-link redirect URL. */
|
|
107
|
-
function getRedirectParams(url) {
|
|
108
|
-
try {
|
|
109
|
-
const parsed = new URL(url);
|
|
110
|
-
const sessionId = parsed.searchParams.get('session_id') ?? undefined;
|
|
111
|
-
const error = parsed.searchParams.get('error') ?? undefined;
|
|
112
|
-
if (!sessionId && !error) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
return {
|
|
116
|
-
sessionId,
|
|
117
|
-
error
|
|
118
|
-
};
|
|
119
|
-
} catch {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Generate a cryptographically random session token.
|
|
126
|
-
*
|
|
127
|
-
* 16 random bytes -> 32 hex chars (128 bits of entropy) — unguessable.
|
|
128
|
-
* `crypto.getRandomValues` is guaranteed available because importing
|
|
129
|
-
* `@oxyhq/core` installs a polyfill via `expo-crypto` on React Native. This is
|
|
130
|
-
* the secure generator the web modal already used; the native screen previously
|
|
131
|
-
* used a weaker `Math.random()` generator, which this consolidation removes.
|
|
132
|
-
*/
|
|
133
|
-
function generateSessionToken() {
|
|
134
|
-
const bytes = new Uint8Array(16);
|
|
135
|
-
crypto.getRandomValues(bytes);
|
|
136
|
-
return Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Owns the full device-flow auth-session lifecycle for one mounted sign-in
|
|
141
|
-
* surface. Both `SignInModal` and `OxyAuthScreen` consume this; neither
|
|
142
|
-
* re-implements the socket / polling / deep-link transport.
|
|
143
|
-
*
|
|
144
|
-
* Subscriptions (socket connect/disconnect, the poll interval, the native
|
|
145
|
-
* deep-link listener, and unmount cleanup) are the legitimate `useEffect` use
|
|
146
|
-
* WITH cleanup. No effect here computes derived UI state.
|
|
147
|
-
*/
|
|
148
|
-
export function useOxyAuthSession(oxyServices, clientId, commitSession, options = {}) {
|
|
149
|
-
const {
|
|
150
|
-
onSignedIn
|
|
151
|
-
} = options;
|
|
152
|
-
const [authSession, setAuthSession] = useState(null);
|
|
153
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
154
|
-
const [error, setError] = useState(null);
|
|
155
|
-
const [isWaiting, setIsWaiting] = useState(false);
|
|
156
|
-
// "Sign in with Oxy" handoff fields surfaced from the `create` response.
|
|
157
|
-
const [authorizeCode, setAuthorizeCode] = useState(null);
|
|
158
|
-
const [qrPayload, setQrPayload] = useState(null);
|
|
159
|
-
const socketRef = useRef(null);
|
|
160
|
-
const pollingIntervalRef = useRef(null);
|
|
161
|
-
const isProcessingRef = useRef(false);
|
|
162
|
-
const linkingHandledRef = useRef(false);
|
|
163
|
-
|
|
164
|
-
// The latest `onSignedIn` callback, read via ref so the success handler does
|
|
165
|
-
// not need it in its dependency list (which would otherwise rebuild the
|
|
166
|
-
// socket/poll callbacks on every render where the container passes a new
|
|
167
|
-
// closure).
|
|
168
|
-
const onSignedInRef = useRef(onSignedIn);
|
|
169
|
-
onSignedInRef.current = onSignedIn;
|
|
170
|
-
|
|
171
|
-
// Cleanup socket and polling. Idempotent.
|
|
172
|
-
const cleanup = useCallback(() => {
|
|
173
|
-
setIsWaiting(false);
|
|
174
|
-
if (socketRef.current) {
|
|
175
|
-
socketRef.current.disconnect();
|
|
176
|
-
socketRef.current = null;
|
|
177
|
-
}
|
|
178
|
-
if (pollingIntervalRef.current) {
|
|
179
|
-
clearInterval(pollingIntervalRef.current);
|
|
180
|
-
pollingIntervalRef.current = null;
|
|
181
|
-
}
|
|
182
|
-
}, []);
|
|
183
|
-
|
|
184
|
-
// Handle successful authorization.
|
|
185
|
-
//
|
|
186
|
-
// The auth-session socket / poll (or deep-link return) hands us the
|
|
187
|
-
// authorized `sessionId`. Before any session-management code can use it we
|
|
188
|
-
// MUST first exchange the secret `sessionToken` (held only by this client,
|
|
189
|
-
// generated for THIS flow) for the first access token via
|
|
190
|
-
// `claimSessionByToken` — the device-flow equivalent of OAuth's
|
|
191
|
-
// code-for-token exchange (RFC 8628 §3.4).
|
|
192
|
-
//
|
|
193
|
-
// Without that exchange the SDK has no bearer token — the session is
|
|
194
|
-
// authorized server-side but the app never becomes authenticated and the UI
|
|
195
|
-
// sits "Waiting for authorization..." forever. Once `claimSessionByToken`
|
|
196
|
-
// plants the tokens in the HttpService, the claimed session is committed via
|
|
197
|
-
// `commitSession` (`useOxy().handleWebSession`) — the SAME path a fresh
|
|
198
|
-
// password sign-in or a silent cross-domain restore uses to register the
|
|
199
|
-
// account into the device's server-authoritative session set. It is NOT yet a
|
|
200
|
-
// member of that set, so
|
|
201
|
-
// `switchSession` (an account-SWITCH between accounts already on the
|
|
202
|
-
// device) is the wrong primitive here. Shared with both containers via
|
|
203
|
-
// `completeDeviceFlowSignIn` so the two paths cannot drift.
|
|
204
|
-
const handleAuthSuccess = useCallback(async (sessionId, sessionToken) => {
|
|
205
|
-
if (isProcessingRef.current) return;
|
|
206
|
-
isProcessingRef.current = true;
|
|
207
|
-
try {
|
|
208
|
-
if (!commitSession) {
|
|
209
|
-
throw new Error('Session commit unavailable');
|
|
210
|
-
}
|
|
211
|
-
const user = await completeDeviceFlowSignIn({
|
|
212
|
-
oxyServices,
|
|
213
|
-
sessionId,
|
|
214
|
-
sessionToken,
|
|
215
|
-
commitSession
|
|
216
|
-
});
|
|
217
|
-
onSignedInRef.current?.(user);
|
|
218
|
-
} catch (err) {
|
|
219
|
-
debug.error('Error completing auth:', err);
|
|
220
|
-
setError('Authorization successful but failed to complete sign in. Please try again.');
|
|
221
|
-
isProcessingRef.current = false;
|
|
222
|
-
}
|
|
223
|
-
}, [oxyServices, commitSession]);
|
|
224
|
-
|
|
225
|
-
// Start polling for authorization.
|
|
226
|
-
//
|
|
227
|
-
// Idempotent: if a poll interval is already running this is a no-op, so the
|
|
228
|
-
// `connect_error` path (which also calls this) cannot stack a second interval
|
|
229
|
-
// on top of the always-on poll started in `generateAuthSession`.
|
|
230
|
-
const startPolling = useCallback(sessionToken => {
|
|
231
|
-
if (pollingIntervalRef.current) return;
|
|
232
|
-
pollingIntervalRef.current = setInterval(async () => {
|
|
233
|
-
if (isProcessingRef.current) return;
|
|
234
|
-
try {
|
|
235
|
-
const response = await oxyServices.makeRequest('GET', `/auth/session/status/${sessionToken}`, undefined, {
|
|
236
|
-
cache: false
|
|
237
|
-
});
|
|
238
|
-
if (response.authorized && response.sessionId) {
|
|
239
|
-
cleanup();
|
|
240
|
-
// Pass the original sessionToken (in closure) through; the claim
|
|
241
|
-
// exchange needs it to mint the first access token.
|
|
242
|
-
handleAuthSuccess(response.sessionId, sessionToken);
|
|
243
|
-
} else if (response.status === 'cancelled') {
|
|
244
|
-
cleanup();
|
|
245
|
-
setError('Authorization was denied.');
|
|
246
|
-
} else if (response.status === 'expired') {
|
|
247
|
-
cleanup();
|
|
248
|
-
setError('Session expired. Please try again.');
|
|
249
|
-
}
|
|
250
|
-
} catch (err) {
|
|
251
|
-
// Transient poll error — the next tick retries. Logged, never thrown.
|
|
252
|
-
debug.log('Auth polling error:', err);
|
|
253
|
-
}
|
|
254
|
-
}, POLLING_INTERVAL_MS);
|
|
255
|
-
}, [oxyServices, handleAuthSuccess, cleanup]);
|
|
256
|
-
|
|
257
|
-
// Connect to the auth-session socket for real-time updates.
|
|
258
|
-
const connectSocket = useCallback(sessionToken => {
|
|
259
|
-
const baseURL = oxyServices.getBaseURL();
|
|
260
|
-
|
|
261
|
-
// Connect to the auth-session namespace (no authentication required).
|
|
262
|
-
const socket = io(`${baseURL}/auth-session`, {
|
|
263
|
-
transports: ['websocket', 'polling'],
|
|
264
|
-
reconnection: true,
|
|
265
|
-
reconnectionAttempts: 3,
|
|
266
|
-
reconnectionDelay: 1000
|
|
267
|
-
});
|
|
268
|
-
socketRef.current = socket;
|
|
269
|
-
socket.on('connect', () => {
|
|
270
|
-
debug.log('Auth socket connected');
|
|
271
|
-
socket.emit('join', sessionToken);
|
|
272
|
-
});
|
|
273
|
-
socket.on('joined', () => {
|
|
274
|
-
debug.log('Joined auth session room');
|
|
275
|
-
});
|
|
276
|
-
socket.on('auth_update', payload => {
|
|
277
|
-
debug.log('Auth update received:', payload);
|
|
278
|
-
if (payload.status === 'authorized' && payload.sessionId) {
|
|
279
|
-
cleanup();
|
|
280
|
-
// `sessionToken` is this flow's secret credential (in closure) — pass
|
|
281
|
-
// it through so `handleAuthSuccess` can claim the first access token.
|
|
282
|
-
handleAuthSuccess(payload.sessionId, sessionToken);
|
|
283
|
-
} else if (payload.status === 'cancelled') {
|
|
284
|
-
cleanup();
|
|
285
|
-
setError('Authorization was denied.');
|
|
286
|
-
} else if (payload.status === 'expired') {
|
|
287
|
-
cleanup();
|
|
288
|
-
setError('Session expired. Please try again.');
|
|
289
|
-
}
|
|
290
|
-
});
|
|
291
|
-
socket.on('connect_error', err => {
|
|
292
|
-
debug.log('Socket connection error, falling back to polling:', err instanceof Error ? err.message : null);
|
|
293
|
-
// Realtime transport errored — fall back to polling. The poll is
|
|
294
|
-
// already running (started unconditionally in `generateAuthSession`),
|
|
295
|
-
// so `startPolling` here is a no-op backstop.
|
|
296
|
-
socket.disconnect();
|
|
297
|
-
startPolling(sessionToken);
|
|
298
|
-
});
|
|
299
|
-
socket.on('disconnect', () => {
|
|
300
|
-
debug.log('Auth socket disconnected');
|
|
301
|
-
});
|
|
302
|
-
}, [oxyServices, handleAuthSuccess, cleanup, startPolling]);
|
|
303
|
-
|
|
304
|
-
// Generate a new auth session.
|
|
305
|
-
const generateAuthSession = useCallback(async () => {
|
|
306
|
-
setIsLoading(true);
|
|
307
|
-
setError(null);
|
|
308
|
-
// Reset the handoff fields for the fresh session (also clears them on retry).
|
|
309
|
-
setAuthorizeCode(null);
|
|
310
|
-
setQrPayload(null);
|
|
311
|
-
isProcessingRef.current = false;
|
|
312
|
-
|
|
313
|
-
// The cross-app device sign-in flow identifies the requesting app by its
|
|
314
|
-
// real registered OAuth client id (ApplicationCredential publicKey).
|
|
315
|
-
// Without it the API cannot resolve the consent identity, so we fail fast
|
|
316
|
-
// with a clear configuration error rather than creating a session the
|
|
317
|
-
// server would reject.
|
|
318
|
-
if (!clientId) {
|
|
319
|
-
setError('This app is not configured for sign-in (missing clientId).');
|
|
320
|
-
setIsLoading(false);
|
|
321
|
-
return;
|
|
322
|
-
}
|
|
323
|
-
try {
|
|
324
|
-
const sessionToken = generateSessionToken();
|
|
325
|
-
const expiresAt = Date.now() + AUTH_SESSION_EXPIRY_MS;
|
|
326
|
-
|
|
327
|
-
// Register the auth session with the server. The response carries the
|
|
328
|
-
// "Sign in with Oxy" handoff fields (public `authorizeCode` + structured
|
|
329
|
-
// `qrPayload`) when the handoff backend is deployed; both are optional, so
|
|
330
|
-
// the legacy `oxyauth://<token>` QR path keeps working without them.
|
|
331
|
-
const createResponse = await oxyServices.makeRequest('POST', '/auth/session/create', {
|
|
332
|
-
sessionToken,
|
|
333
|
-
expiresAt,
|
|
334
|
-
clientId
|
|
335
|
-
}, {
|
|
336
|
-
cache: false
|
|
337
|
-
});
|
|
338
|
-
setAuthSession({
|
|
339
|
-
sessionToken,
|
|
340
|
-
expiresAt
|
|
341
|
-
});
|
|
342
|
-
setAuthorizeCode(createResponse?.authorizeCode ?? null);
|
|
343
|
-
setQrPayload(createResponse?.qrPayload ?? null);
|
|
344
|
-
setIsWaiting(true);
|
|
345
|
-
|
|
346
|
-
// Socket is the fast path; the poll is a transport-independent backstop
|
|
347
|
-
// that guarantees completion even if the socket connects but silently
|
|
348
|
-
// never delivers auth_update (RN transport / idle-timeout).
|
|
349
|
-
connectSocket(sessionToken);
|
|
350
|
-
startPolling(sessionToken);
|
|
351
|
-
} catch (err) {
|
|
352
|
-
setError((err instanceof Error ? err.message : null) || 'Failed to create auth session');
|
|
353
|
-
} finally {
|
|
354
|
-
setIsLoading(false);
|
|
355
|
-
}
|
|
356
|
-
}, [oxyServices, connectSocket, startPolling, clientId]);
|
|
357
|
-
|
|
358
|
-
// Open the central Oxy auth approval surface for this device-flow session.
|
|
359
|
-
// On web this is a centered popup; on native it opens the system browser,
|
|
360
|
-
// carrying a `redirect_uri` so the deep-link return path can complete the
|
|
361
|
-
// flow even if the socket/poll is slow.
|
|
362
|
-
const openAuthApproval = useCallback(async () => {
|
|
363
|
-
if (!authSession) return;
|
|
364
|
-
const authBaseUrl = resolveAuthWebBaseUrl(oxyServices.getBaseURL(), oxyServices.config?.authWebUrl);
|
|
365
|
-
const webUrl = new URL('/authorize', authBaseUrl);
|
|
366
|
-
webUrl.searchParams.set('token', authSession.sessionToken);
|
|
367
|
-
if (Platform.OS === 'web') {
|
|
368
|
-
// Open a separate approval window on web for the device-flow token.
|
|
369
|
-
const width = 500;
|
|
370
|
-
const height = 650;
|
|
371
|
-
const screenWidth = window.screen?.width ?? width;
|
|
372
|
-
const screenHeight = window.screen?.height ?? height;
|
|
373
|
-
const left = (screenWidth - width) / 2;
|
|
374
|
-
const top = (screenHeight - height) / 2;
|
|
375
|
-
window.open(webUrl.toString(), 'oxy-auth-approval', `width=${width},height=${height},left=${left},top=${top}`);
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Native: carry a redirect URI so the auth web flow can bounce back in.
|
|
380
|
-
const redirectUri = await resolveAuthRedirectUri(oxyServices.config?.authRedirectUri);
|
|
381
|
-
if (redirectUri) {
|
|
382
|
-
webUrl.searchParams.set('redirect_uri', redirectUri);
|
|
383
|
-
}
|
|
384
|
-
try {
|
|
385
|
-
await Linking.openURL(webUrl.toString());
|
|
386
|
-
} catch (err) {
|
|
387
|
-
debug.error('Unable to open Oxy Auth:', err);
|
|
388
|
-
setError('Unable to open Oxy Auth. Please try again or use the QR code.');
|
|
389
|
-
}
|
|
390
|
-
}, [authSession, oxyServices]);
|
|
391
|
-
|
|
392
|
-
// Same-device "Sign in with Oxy" handoff: deep-link to the `qrPayload`
|
|
393
|
-
// (`oxycommons://approve?...`) so the native Oxy identity app opens directly
|
|
394
|
-
// to approve. The socket / poll already resolves the flow once the approval
|
|
395
|
-
// lands, so this only needs to launch the deep link. No-op when the handoff
|
|
396
|
-
// backend returned no `qrPayload`.
|
|
397
|
-
const openSameDeviceApproval = useCallback(async () => {
|
|
398
|
-
if (!qrPayload) {
|
|
399
|
-
return;
|
|
400
|
-
}
|
|
401
|
-
try {
|
|
402
|
-
await Linking.openURL(qrPayload);
|
|
403
|
-
} catch (err) {
|
|
404
|
-
debug.error('Unable to open the Oxy app for approval:', err);
|
|
405
|
-
setError('Unable to open the Oxy app. Scan the QR code from another device instead.');
|
|
406
|
-
}
|
|
407
|
-
}, [qrPayload]);
|
|
408
|
-
|
|
409
|
-
// Tear down and recreate the session (the retry action).
|
|
410
|
-
const retry = useCallback(() => {
|
|
411
|
-
cleanup();
|
|
412
|
-
generateAuthSession();
|
|
413
|
-
}, [generateAuthSession, cleanup]);
|
|
414
|
-
|
|
415
|
-
// Handle a native deep-link return carrying the authorized session_id.
|
|
416
|
-
const handleAuthRedirect = useCallback(url => {
|
|
417
|
-
const params = getRedirectParams(url);
|
|
418
|
-
if (!params) {
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
if (params.error) {
|
|
422
|
-
cleanup();
|
|
423
|
-
setError('Authorization was denied.');
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
if (params.sessionId) {
|
|
427
|
-
// The deep-link return carries only `session_id` — the secret
|
|
428
|
-
// `sessionToken` for this flow lives in component state (generated in
|
|
429
|
-
// `generateAuthSession`). Without it we cannot claim the first access
|
|
430
|
-
// token, so the flow would 401 in `handleAuthSuccess`. If it is somehow
|
|
431
|
-
// unavailable, fall through to the socket/poll path (which carries the
|
|
432
|
-
// token in closure) rather than attempting an unauthenticated claim.
|
|
433
|
-
const flowSessionToken = authSession?.sessionToken;
|
|
434
|
-
if (!flowSessionToken) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
cleanup();
|
|
438
|
-
handleAuthSuccess(params.sessionId, flowSessionToken);
|
|
439
|
-
}
|
|
440
|
-
}, [authSession, cleanup, handleAuthSuccess]);
|
|
441
|
-
|
|
442
|
-
// Initialize the auth session once on mount.
|
|
443
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies: this must run exactly once on mount; re-running on `generateAuthSession` identity changes would recreate the session mid-flow.
|
|
444
|
-
useEffect(() => {
|
|
445
|
-
generateAuthSession();
|
|
446
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
447
|
-
}, []);
|
|
448
|
-
|
|
449
|
-
// Native-only: handle the deep-link return from the auth web flow. Gated to
|
|
450
|
-
// native so the web container never carries this listener. The socket / poll
|
|
451
|
-
// path still resolves the flow if no deep link arrives.
|
|
452
|
-
useEffect(() => {
|
|
453
|
-
if (Platform.OS === 'web') {
|
|
454
|
-
return;
|
|
455
|
-
}
|
|
456
|
-
const subscription = Linking.addEventListener('url', ({
|
|
457
|
-
url
|
|
458
|
-
}) => {
|
|
459
|
-
linkingHandledRef.current = true;
|
|
460
|
-
handleAuthRedirect(url);
|
|
461
|
-
});
|
|
462
|
-
Linking.getInitialURL().then(url => {
|
|
463
|
-
if (url && !linkingHandledRef.current) {
|
|
464
|
-
handleAuthRedirect(url);
|
|
465
|
-
}
|
|
466
|
-
}).catch(() => {
|
|
467
|
-
// Ignore linking errors; auth will still resolve via socket/polling.
|
|
468
|
-
});
|
|
469
|
-
return () => {
|
|
470
|
-
subscription.remove();
|
|
471
|
-
};
|
|
472
|
-
}, [handleAuthRedirect]);
|
|
473
|
-
|
|
474
|
-
// Clean up subscriptions on unmount.
|
|
475
|
-
useEffect(() => {
|
|
476
|
-
return () => {
|
|
477
|
-
cleanup();
|
|
478
|
-
};
|
|
479
|
-
}, [cleanup]);
|
|
480
|
-
const qrData = authSession ? `oxyauth://${authSession.sessionToken}` : '';
|
|
481
|
-
return {
|
|
482
|
-
authSession,
|
|
483
|
-
qrData,
|
|
484
|
-
authorizeCode,
|
|
485
|
-
qrPayload,
|
|
486
|
-
isLoading,
|
|
487
|
-
error,
|
|
488
|
-
isWaiting,
|
|
489
|
-
openAuthApproval,
|
|
490
|
-
openSameDeviceApproval,
|
|
491
|
-
retry,
|
|
492
|
-
cleanup
|
|
493
|
-
};
|
|
494
|
-
}
|
|
495
|
-
//# sourceMappingURL=useOxyAuthSession.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["useState","useEffect","useCallback","useRef","Linking","Platform","io","createDebugLogger","completeDeviceFlowSignIn","debug","OXY_ACCOUNTS_WEB_URL","OXY_AUTH_WEB_URL","AUTH_SESSION_EXPIRY_MS","POLLING_INTERVAL_MS","resolveAuthWebBaseUrl","baseURL","authWebUrl","url","URL","port","origin","hostname","startsWith","slice","resolveAuthRedirectUri","authRedirectUri","initialUrl","getInitialURL","parsed","search","hash","toString","getRedirectParams","sessionId","searchParams","get","undefined","error","generateSessionToken","bytes","Uint8Array","crypto","getRandomValues","Array","from","b","padStart","join","useOxyAuthSession","oxyServices","clientId","commitSession","options","onSignedIn","authSession","setAuthSession","isLoading","setIsLoading","setError","isWaiting","setIsWaiting","authorizeCode","setAuthorizeCode","qrPayload","setQrPayload","socketRef","pollingIntervalRef","isProcessingRef","linkingHandledRef","onSignedInRef","current","cleanup","disconnect","clearInterval","handleAuthSuccess","sessionToken","Error","user","err","startPolling","setInterval","response","makeRequest","cache","authorized","status","log","connectSocket","getBaseURL","socket","transports","reconnection","reconnectionAttempts","reconnectionDelay","on","emit","payload","message","generateAuthSession","expiresAt","Date","now","createResponse","openAuthApproval","authBaseUrl","config","webUrl","set","OS","width","height","screenWidth","window","screen","screenHeight","left","top","open","redirectUri","openURL","openSameDeviceApproval","retry","handleAuthRedirect","params","flowSessionToken","subscription","addEventListener","then","catch","remove","qrData"],"sourceRoot":"../../../../src","sources":["ui/hooks/useOxyAuthSession.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* `usePasswordSignIn` — the first-party password sign-in state machine.
|
|
5
|
-
*
|
|
6
|
-
* Drives the in-app "Sign in with Oxy" password flow shared by the web
|
|
7
|
-
* `SignInModal` and the native `OxyAuthScreen`: identifier → password → optional
|
|
8
|
-
* two-factor. It is a thin UI state machine over the context methods
|
|
9
|
-
* `signInWithPassword` + `completeTwoFactorSignIn` (which own the network call,
|
|
10
|
-
* the persisted-refresh commit, and the device-set registration) — so both
|
|
11
|
-
* surfaces present an identical flow without re-implementing any transport.
|
|
12
|
-
*
|
|
13
|
-
* On a committed session `onSignedIn` fires (the modal/screen closes); the
|
|
14
|
-
* device-first cold boot / SessionClient projection then drive the app into the
|
|
15
|
-
* authenticated state.
|
|
16
|
-
*/
|
|
17
|
-
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
18
|
-
import { useOxy } from "../context/OxyContext.js";
|
|
19
|
-
import { handleAuthError } from "../utils/errorHandlers.js";
|
|
20
|
-
export function usePasswordSignIn(options = {}) {
|
|
21
|
-
const {
|
|
22
|
-
signInWithPassword,
|
|
23
|
-
completeTwoFactorSignIn
|
|
24
|
-
} = useOxy();
|
|
25
|
-
const {
|
|
26
|
-
onSignedIn
|
|
27
|
-
} = options;
|
|
28
|
-
const [step, setStep] = useState('identifier');
|
|
29
|
-
const [identifier, setIdentifier] = useState('');
|
|
30
|
-
const [password, setPassword] = useState('');
|
|
31
|
-
const [code, setCode] = useState('');
|
|
32
|
-
const [useBackupCode, setUseBackupCode] = useState(false);
|
|
33
|
-
const [error, setError] = useState(null);
|
|
34
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
35
|
-
const [loginToken, setLoginToken] = useState(null);
|
|
36
|
-
|
|
37
|
-
// Synchronous in-flight guard. `isSubmitting` state drives the UI, but a rapid
|
|
38
|
-
// double-tap fires both handlers in the SAME tick — before React re-renders —
|
|
39
|
-
// so a state read would still see `false` on the second call and double-fire
|
|
40
|
-
// the network request (rate-limit + race). This ref is set/checked
|
|
41
|
-
// synchronously, so the second call is a true no-op.
|
|
42
|
-
const submittingRef = useRef(false);
|
|
43
|
-
const surfaceError = useCallback((err, defaultMessage) => {
|
|
44
|
-
setError(handleAuthError(err, {
|
|
45
|
-
defaultMessage,
|
|
46
|
-
code: 'PASSWORD_SIGN_IN_ERROR'
|
|
47
|
-
}));
|
|
48
|
-
}, []);
|
|
49
|
-
const submitIdentifier = useCallback(() => {
|
|
50
|
-
if (!identifier.trim()) {
|
|
51
|
-
setError('Enter your username or email');
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
setError(null);
|
|
55
|
-
setStep('password');
|
|
56
|
-
}, [identifier]);
|
|
57
|
-
const submitPassword = useCallback(async () => {
|
|
58
|
-
// A second call while one is already in flight is a no-op (double-tap guard).
|
|
59
|
-
if (submittingRef.current) {
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
|
-
if (!password) {
|
|
63
|
-
setError('Enter your password');
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
setError(null);
|
|
67
|
-
submittingRef.current = true;
|
|
68
|
-
setIsSubmitting(true);
|
|
69
|
-
try {
|
|
70
|
-
const result = await signInWithPassword(identifier.trim(), password);
|
|
71
|
-
if (result.status === '2fa_required') {
|
|
72
|
-
setLoginToken(result.loginToken);
|
|
73
|
-
setCode('');
|
|
74
|
-
setUseBackupCode(false);
|
|
75
|
-
setStep('twoFactor');
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
onSignedIn?.();
|
|
79
|
-
} catch (err) {
|
|
80
|
-
surfaceError(err, 'Sign in failed');
|
|
81
|
-
} finally {
|
|
82
|
-
submittingRef.current = false;
|
|
83
|
-
setIsSubmitting(false);
|
|
84
|
-
}
|
|
85
|
-
}, [identifier, password, signInWithPassword, onSignedIn, surfaceError]);
|
|
86
|
-
const submitTwoFactor = useCallback(async () => {
|
|
87
|
-
// A second call while one is already in flight is a no-op (double-tap guard).
|
|
88
|
-
if (submittingRef.current) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
if (!loginToken) {
|
|
92
|
-
setError('Your sign-in session expired. Start again.');
|
|
93
|
-
setStep('password');
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
if (!code.trim()) {
|
|
97
|
-
setError(useBackupCode ? 'Enter a backup code' : 'Enter your 6-digit code');
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
setError(null);
|
|
101
|
-
submittingRef.current = true;
|
|
102
|
-
setIsSubmitting(true);
|
|
103
|
-
try {
|
|
104
|
-
await completeTwoFactorSignIn({
|
|
105
|
-
loginToken,
|
|
106
|
-
...(useBackupCode ? {
|
|
107
|
-
backupCode: code.trim()
|
|
108
|
-
} : {
|
|
109
|
-
token: code.trim()
|
|
110
|
-
})
|
|
111
|
-
});
|
|
112
|
-
onSignedIn?.();
|
|
113
|
-
} catch (err) {
|
|
114
|
-
surfaceError(err, 'Verification failed');
|
|
115
|
-
} finally {
|
|
116
|
-
submittingRef.current = false;
|
|
117
|
-
setIsSubmitting(false);
|
|
118
|
-
}
|
|
119
|
-
}, [loginToken, code, useBackupCode, completeTwoFactorSignIn, onSignedIn, surfaceError]);
|
|
120
|
-
const back = useCallback(() => {
|
|
121
|
-
setError(null);
|
|
122
|
-
setStep(current => {
|
|
123
|
-
if (current === 'twoFactor') {
|
|
124
|
-
setLoginToken(null);
|
|
125
|
-
setCode('');
|
|
126
|
-
return 'password';
|
|
127
|
-
}
|
|
128
|
-
if (current === 'password') {
|
|
129
|
-
setPassword('');
|
|
130
|
-
return 'identifier';
|
|
131
|
-
}
|
|
132
|
-
return current;
|
|
133
|
-
});
|
|
134
|
-
}, []);
|
|
135
|
-
const reset = useCallback(() => {
|
|
136
|
-
setStep('identifier');
|
|
137
|
-
setIdentifier('');
|
|
138
|
-
setPassword('');
|
|
139
|
-
setCode('');
|
|
140
|
-
setUseBackupCode(false);
|
|
141
|
-
setLoginToken(null);
|
|
142
|
-
setError(null);
|
|
143
|
-
submittingRef.current = false;
|
|
144
|
-
setIsSubmitting(false);
|
|
145
|
-
}, []);
|
|
146
|
-
return useMemo(() => ({
|
|
147
|
-
step,
|
|
148
|
-
identifier,
|
|
149
|
-
setIdentifier,
|
|
150
|
-
password,
|
|
151
|
-
setPassword,
|
|
152
|
-
code,
|
|
153
|
-
setCode,
|
|
154
|
-
useBackupCode,
|
|
155
|
-
setUseBackupCode,
|
|
156
|
-
error,
|
|
157
|
-
isSubmitting,
|
|
158
|
-
submitIdentifier,
|
|
159
|
-
submitPassword,
|
|
160
|
-
submitTwoFactor,
|
|
161
|
-
back,
|
|
162
|
-
reset
|
|
163
|
-
}), [step, identifier, password, code, useBackupCode, error, isSubmitting, submitIdentifier, submitPassword, submitTwoFactor, back, reset]);
|
|
164
|
-
}
|
|
165
|
-
//# sourceMappingURL=usePasswordSignIn.js.map
|