@oxyhq/core 12.4.0 → 12.4.1
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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/session/refresh.js +14 -3
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/session/refresh.js +14 -3
- package/dist/types/.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/session/__tests__/refresh.test.ts +20 -0
- package/src/session/refresh.ts +12 -3
package/package.json
CHANGED
|
@@ -159,6 +159,26 @@ describe('refreshPersistedSession — arm 1 (device-secret mint)', () => {
|
|
|
159
159
|
expect(await store.load()).toEqual(STORED);
|
|
160
160
|
expect(signInWithSharedIdentity).not.toHaveBeenCalled();
|
|
161
161
|
});
|
|
162
|
+
|
|
163
|
+
it('KEEPS the store on an UNRECOGNIZED 401 (proxy / middleware / deploy-window) — never wipes the credential on an ambiguous 401', async () => {
|
|
164
|
+
const store = createMemoryAuthStateStore();
|
|
165
|
+
await store.save(STORED);
|
|
166
|
+
const signInWithSharedIdentity = jest.fn(async () => null);
|
|
167
|
+
const { oxy } = makeOxy({
|
|
168
|
+
mintFromDeviceSecret: async () => {
|
|
169
|
+
// A 401 whose body is NEITHER `invalid_device_secret` NOR `no_active_session`
|
|
170
|
+
// — an auth-layer / proxy / starting-instance 401 common during a deploy
|
|
171
|
+
// window. It is NOT proof the secret diverged, so the durable device
|
|
172
|
+
// credential must survive (treated as transient) and a later attempt self-heals.
|
|
173
|
+
throw Object.assign(new Error('Unauthorized'), { status: 401 });
|
|
174
|
+
},
|
|
175
|
+
signInWithSharedIdentity,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
expect(await refreshPersistedSession({ oxy, store, allowSharedKeyFallback: true })).toBeNull();
|
|
179
|
+
expect(await store.load()).toEqual(STORED);
|
|
180
|
+
expect(signInWithSharedIdentity).not.toHaveBeenCalled();
|
|
181
|
+
});
|
|
162
182
|
});
|
|
163
183
|
|
|
164
184
|
describe('refreshPersistedSession — arm 2 (native shared-key fallback)', () => {
|
package/src/session/refresh.ts
CHANGED
|
@@ -136,9 +136,18 @@ export async function refreshDeviceSecretArm(deps: {
|
|
|
136
136
|
// Structural read (not `instanceof Error`): the thrown value can be a
|
|
137
137
|
// plain ApiError-shaped object or come from another realm.
|
|
138
138
|
const message = (error as { message?: unknown })?.message;
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
const body = typeof message === 'string' ? message : '';
|
|
140
|
+
// ONLY the server's explicit `invalid_device_secret` proves the presented
|
|
141
|
+
// secret is bad and may clear the durable device credential. `no_active_session`
|
|
142
|
+
// is an authoritative signed-out. ANY OTHER 401 — a middleware/CSRF/proxy 401,
|
|
143
|
+
// an ALB/starting-instance 401, a CORS error page, etc., all common during a
|
|
144
|
+
// deploy/restart window — is NOT proof the secret diverged: treat it as
|
|
145
|
+
// transient and KEEP the credential so a later attempt self-heals. Wiping the
|
|
146
|
+
// credential on an ambiguous 401 is what logged users out on every deploy,
|
|
147
|
+
// ecosystem-wide.
|
|
148
|
+
if (body.includes('invalid_device_secret')) return { status: 'invalid-secret' };
|
|
149
|
+
if (body.includes('no_active_session')) return { status: 'no-session' };
|
|
150
|
+
return { status: 'transient' };
|
|
142
151
|
}
|
|
143
152
|
return { status: 'transient' };
|
|
144
153
|
}
|