@oxyhq/core 1.11.14 → 1.11.15
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.
|
@@ -172,8 +172,48 @@ function OxyServicesPopupAuthMixin(Base) {
|
|
|
172
172
|
document.body.appendChild(iframe);
|
|
173
173
|
try {
|
|
174
174
|
const session = await this.waitForIframeAuth(iframe, timeout, clientId);
|
|
175
|
-
|
|
176
|
-
|
|
175
|
+
// Bail early on incomplete responses. The iframe contract requires
|
|
176
|
+
// both an access token and a session id; anything less is unusable.
|
|
177
|
+
// Returning `null` here (without installing the token) prevents a
|
|
178
|
+
// stale credential from being committed to HttpService when the
|
|
179
|
+
// user is actually signed out — that pattern caused a `getCurrentUser`
|
|
180
|
+
// -> 401 -> token-clear loop in consumer apps because callers gated
|
|
181
|
+
// on `session?.user` and never installed the user via
|
|
182
|
+
// `handleAuthSuccess`, while HttpService quietly held the token.
|
|
183
|
+
const accessToken = session ? session.accessToken : undefined;
|
|
184
|
+
if (!session || !accessToken || !session.sessionId) {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
// Snapshot the previous token so we can roll back if the user
|
|
188
|
+
// lookup below fails — this avoids leaving a half-committed session
|
|
189
|
+
// (token installed, user missing) which would let the next
|
|
190
|
+
// authenticated request 401 with no way to recover.
|
|
191
|
+
const previousAccessToken = this.httpService.getAccessToken();
|
|
192
|
+
this.httpService.setTokens(accessToken);
|
|
193
|
+
// The iframe typically returns `{ sessionId, accessToken }` without
|
|
194
|
+
// user data. Fetch the user explicitly so callers receive a
|
|
195
|
+
// fully-formed session and never need a second `/users/me` round
|
|
196
|
+
// trip. If this fails the session is unusable — revert the token
|
|
197
|
+
// and return null so the caller treats this exactly like a
|
|
198
|
+
// missing-session response.
|
|
199
|
+
if (!session.user) {
|
|
200
|
+
try {
|
|
201
|
+
const userData = await this.makeRequest('GET', `/session/user/${session.sessionId}`, undefined, { cache: false, retry: false });
|
|
202
|
+
if (!userData) {
|
|
203
|
+
throw new Error('Empty user response');
|
|
204
|
+
}
|
|
205
|
+
session.user = userData;
|
|
206
|
+
}
|
|
207
|
+
catch (userError) {
|
|
208
|
+
debug.warn('silentSignIn: failed to fetch user data, rolling back token', userError);
|
|
209
|
+
if (previousAccessToken) {
|
|
210
|
+
this.httpService.setTokens(previousAccessToken);
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.httpService.clearTokens();
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
177
217
|
}
|
|
178
218
|
return session;
|
|
179
219
|
}
|