@oxyhq/services 22.12.3 → 22.12.5
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/ui/components/oauthNavigation.js +11 -1
- package/lib/commonjs/ui/components/oauthNavigation.js.map +1 -1
- package/lib/commonjs/ui/screens/CreateAccountScreen.js +5 -0
- package/lib/commonjs/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js +14 -3
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/commonjs/ui/utils/crossOriginRestore.js +5 -1
- package/lib/commonjs/ui/utils/crossOriginRestore.js.map +1 -1
- package/lib/commonjs/ui/utils/oauthReturn.js +50 -4
- package/lib/commonjs/ui/utils/oauthReturn.js.map +1 -1
- package/lib/module/ui/components/oauthNavigation.js +12 -2
- package/lib/module/ui/components/oauthNavigation.js.map +1 -1
- package/lib/module/ui/screens/CreateAccountScreen.js +5 -0
- package/lib/module/ui/screens/CreateAccountScreen.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js +14 -3
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/module/ui/utils/crossOriginRestore.js +5 -1
- package/lib/module/ui/utils/crossOriginRestore.js.map +1 -1
- package/lib/module/ui/utils/oauthReturn.js +50 -5
- package/lib/module/ui/utils/oauthReturn.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/oauthNavigation.d.ts +7 -0
- package/lib/typescript/commonjs/ui/components/oauthNavigation.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/crossOriginRestore.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/oauthReturn.d.ts +19 -0
- package/lib/typescript/commonjs/ui/utils/oauthReturn.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/oauthNavigation.d.ts +7 -0
- package/lib/typescript/module/ui/components/oauthNavigation.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/CreateAccountScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/crossOriginRestore.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/oauthReturn.d.ts +19 -0
- package/lib/typescript/module/ui/utils/oauthReturn.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/ui/components/oauthNavigation.ts +12 -2
- package/src/ui/screens/CreateAccountScreen.tsx +5 -0
- package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +15 -3
- package/src/ui/utils/crossOriginRestore.ts +5 -1
- package/src/ui/utils/oauthReturn.ts +51 -4
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { OxyServices } from '@oxyhq/core';
|
|
2
2
|
import {
|
|
3
3
|
clearOAuthHandshake,
|
|
4
|
+
consumeOAuthReturnPath,
|
|
4
5
|
logger,
|
|
5
6
|
normalizeOAuthRedirectUri,
|
|
6
7
|
readOAuthHandshake,
|
|
@@ -53,8 +54,10 @@ export async function tryCompleteOAuthReturn(opts: {
|
|
|
53
54
|
logger.warn('OAuth return ignored: missing or mismatched handshake', {
|
|
54
55
|
component: 'oauthReturn',
|
|
55
56
|
});
|
|
56
|
-
clearOAuthHandshake
|
|
57
|
+
// Consume the return path before clearing the handshake — clearOAuthHandshake
|
|
58
|
+
// drops the persisted path along with the PKCE keys.
|
|
57
59
|
stripOAuthParamsFromUrl();
|
|
60
|
+
clearOAuthHandshake();
|
|
58
61
|
return false;
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -70,8 +73,9 @@ export async function tryCompleteOAuthReturn(opts: {
|
|
|
70
73
|
codeVerifier: handshake.codeVerifier,
|
|
71
74
|
});
|
|
72
75
|
// Strip OAuth params before commit so a stale `?code=` cannot re-enter the exchange loop.
|
|
73
|
-
clearOAuthHandshake
|
|
76
|
+
// Read the return path first — clearOAuthHandshake drops it with the PKCE keys.
|
|
74
77
|
stripOAuthParamsFromUrl();
|
|
78
|
+
clearOAuthHandshake();
|
|
75
79
|
await opts.commitSession({
|
|
76
80
|
sessionId: result.sessionId,
|
|
77
81
|
accessToken: result.accessToken,
|
|
@@ -84,12 +88,55 @@ export async function tryCompleteOAuthReturn(opts: {
|
|
|
84
88
|
return true;
|
|
85
89
|
} catch (error) {
|
|
86
90
|
logger.warn('OAuth return exchange failed', { component: 'oauthReturn' }, error);
|
|
87
|
-
clearOAuthHandshake();
|
|
88
91
|
stripOAuthParamsFromUrl();
|
|
92
|
+
clearOAuthHandshake();
|
|
89
93
|
return false;
|
|
90
94
|
}
|
|
91
95
|
}
|
|
92
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Rewrite the address bar after an authorize round trip, and tell the router.
|
|
99
|
+
*
|
|
100
|
+
* Prefers the page the visit started on (see `persistOAuthReturnPath`) over the
|
|
101
|
+
* bare origin the IdP redirected to, falling back to `fallbackUrl` when nothing
|
|
102
|
+
* was recorded.
|
|
103
|
+
*
|
|
104
|
+
* The `popstate` dispatch is the load-bearing part. `history.replaceState`
|
|
105
|
+
* fires no event, and cold boot runs *inside* the mounted app — by the time
|
|
106
|
+
* this executes, a history-based router (React Router, Vue Router, …) has
|
|
107
|
+
* already read `location` and rendered the route for `/`. Without a
|
|
108
|
+
* notification the address bar would show the restored deep link while the page
|
|
109
|
+
* still displayed the home page. `popstate` is the event the History API
|
|
110
|
+
* defines for exactly this, and it is what those routers subscribe to.
|
|
111
|
+
*
|
|
112
|
+
* Only dispatched when the URL actually changed, so the common no-op case does
|
|
113
|
+
* not push a spurious event at every listener on the page.
|
|
114
|
+
*/
|
|
115
|
+
export function replaceUrlAfterOAuthReturn(fallbackUrl: string): void {
|
|
116
|
+
const location = (globalThis as { location?: Location }).location;
|
|
117
|
+
const history = (globalThis as { history?: History }).history;
|
|
118
|
+
if (!location || !history?.replaceState) return;
|
|
119
|
+
|
|
120
|
+
const current = `${location.pathname}${location.search}${location.hash}`;
|
|
121
|
+
const target = consumeOAuthReturnPath() ?? fallbackUrl;
|
|
122
|
+
history.replaceState(history.state, '', target);
|
|
123
|
+
if (target === current) return;
|
|
124
|
+
|
|
125
|
+
const dispatch = (globalThis as { dispatchEvent?: (event: Event) => boolean }).dispatchEvent;
|
|
126
|
+
if (typeof dispatch !== 'function') return;
|
|
127
|
+
try {
|
|
128
|
+
// `PopStateEvent` is web-only; plain `Event` is a good enough carrier for
|
|
129
|
+
// any host that lacks it (routers read `location`, not `event.state`).
|
|
130
|
+
const event =
|
|
131
|
+
typeof PopStateEvent === 'function'
|
|
132
|
+
? new PopStateEvent('popstate', { state: history.state })
|
|
133
|
+
: new Event('popstate');
|
|
134
|
+
dispatch.call(globalThis, event);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
logger.warn('Could not notify router of restored URL', { component: 'oauthReturn' }, error);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
93
140
|
function stripOAuthParamsFromUrl(): void {
|
|
94
141
|
const location = (globalThis as { location?: Location; history?: History }).location;
|
|
95
142
|
const history = (globalThis as { history?: History }).history;
|
|
@@ -100,7 +147,7 @@ function stripOAuthParamsFromUrl(): void {
|
|
|
100
147
|
url.searchParams.delete('error');
|
|
101
148
|
url.searchParams.delete('error_description');
|
|
102
149
|
url.searchParams.delete('hub_sync');
|
|
103
|
-
|
|
150
|
+
replaceUrlAfterOAuthReturn(`${url.pathname}${url.search}${url.hash}`);
|
|
104
151
|
}
|
|
105
152
|
|
|
106
153
|
/**
|