@oxyhq/core 5.5.0 → 7.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/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/HttpService.js +7 -4
- package/dist/cjs/OxyServices.base.js +7 -102
- package/dist/cjs/boot/coldBootV2.js +350 -0
- package/dist/cjs/boot/deviceBootReturn.js +152 -0
- package/dist/cjs/crypto/keyManager.js +95 -0
- package/dist/cjs/i18n/locales/en-US.json +13 -1
- package/dist/cjs/i18n/locales/es-ES.json +13 -1
- package/dist/cjs/i18n/locales/locales/en-US.json +13 -1
- package/dist/cjs/i18n/locales/locales/es-ES.json +13 -1
- package/dist/cjs/index.js +54 -45
- package/dist/cjs/mixins/OxyServices.accounts.js +13 -26
- package/dist/cjs/mixins/OxyServices.auth.js +66 -201
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +119 -0
- package/dist/cjs/mixins/index.js +8 -17
- package/dist/cjs/server/index.js +2 -2
- package/dist/cjs/session/SessionClient.js +40 -1
- package/dist/cjs/session/authStateStore.js +284 -0
- package/dist/cjs/session/refresh.js +264 -0
- package/dist/cjs/shared/utils/debugUtils.js +3 -3
- package/dist/cjs/utils/accountUtils.js +1 -55
- package/dist/cjs/utils/authWebUrl.js +10 -39
- package/dist/cjs/utils/coldBoot.js +10 -8
- package/dist/cjs/utils/platform.js +19 -0
- package/dist/cjs/utils/registrableApex.js +49 -0
- package/dist/cjs/utils/ssoBounce.js +15 -362
- package/dist/cjs/utils/validationUtils.js +57 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/HttpService.js +7 -4
- package/dist/esm/OxyServices.base.js +7 -102
- package/dist/esm/boot/coldBootV2.js +344 -0
- package/dist/esm/boot/deviceBootReturn.js +146 -0
- package/dist/esm/crypto/keyManager.js +95 -0
- package/dist/esm/i18n/locales/en-US.json +13 -1
- package/dist/esm/i18n/locales/es-ES.json +13 -1
- package/dist/esm/i18n/locales/locales/en-US.json +13 -1
- package/dist/esm/i18n/locales/locales/es-ES.json +13 -1
- package/dist/esm/index.js +34 -17
- package/dist/esm/mixins/OxyServices.accounts.js +13 -26
- package/dist/esm/mixins/OxyServices.auth.js +66 -201
- package/dist/esm/mixins/OxyServices.deviceBoot.js +116 -0
- package/dist/esm/mixins/index.js +8 -17
- package/dist/esm/server/index.js +1 -1
- package/dist/esm/session/SessionClient.js +40 -1
- package/dist/esm/session/authStateStore.js +278 -0
- package/dist/esm/session/refresh.js +257 -0
- package/dist/esm/shared/utils/debugUtils.js +3 -3
- package/dist/esm/utils/accountUtils.js +0 -53
- package/dist/esm/utils/authWebUrl.js +9 -37
- package/dist/esm/utils/coldBoot.js +10 -8
- package/dist/esm/utils/platform.js +18 -0
- package/dist/esm/utils/registrableApex.js +46 -0
- package/dist/esm/utils/ssoBounce.js +14 -345
- package/dist/esm/utils/validationUtils.js +56 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/HttpService.d.ts +14 -1
- package/dist/types/OxyServices.base.d.ts +0 -52
- package/dist/types/OxyServices.d.ts +0 -25
- package/dist/types/boot/coldBootV2.d.ts +76 -0
- package/dist/types/boot/deviceBootReturn.d.ts +83 -0
- package/dist/types/crypto/keyManager.d.ts +21 -0
- package/dist/types/index.d.ts +14 -21
- package/dist/types/mixins/OxyServices.accounts.d.ts +24 -29
- package/dist/types/mixins/OxyServices.analytics.d.ts +0 -2
- package/dist/types/mixins/OxyServices.appData.d.ts +0 -2
- package/dist/types/mixins/OxyServices.assets.d.ts +0 -2
- package/dist/types/mixins/OxyServices.auth.d.ts +35 -77
- package/dist/types/mixins/OxyServices.civic.d.ts +0 -2
- package/dist/types/mixins/OxyServices.connectedApps.d.ts +0 -2
- package/dist/types/mixins/OxyServices.contacts.d.ts +0 -2
- package/dist/types/mixins/OxyServices.deviceBoot.d.ts +110 -0
- package/dist/types/mixins/OxyServices.devices.d.ts +0 -2
- package/dist/types/mixins/OxyServices.features.d.ts +0 -2
- package/dist/types/mixins/OxyServices.identity.d.ts +0 -2
- package/dist/types/mixins/OxyServices.language.d.ts +0 -2
- package/dist/types/mixins/OxyServices.links.d.ts +0 -2
- package/dist/types/mixins/OxyServices.location.d.ts +0 -2
- package/dist/types/mixins/OxyServices.nodes.d.ts +0 -2
- package/dist/types/mixins/OxyServices.payment.d.ts +0 -2
- package/dist/types/mixins/OxyServices.privacy.d.ts +0 -2
- package/dist/types/mixins/OxyServices.reputation.d.ts +0 -2
- package/dist/types/mixins/OxyServices.security.d.ts +0 -2
- package/dist/types/mixins/OxyServices.topics.d.ts +0 -2
- package/dist/types/mixins/OxyServices.user.d.ts +0 -2
- package/dist/types/mixins/OxyServices.utility.d.ts +0 -2
- package/dist/types/mixins/index.d.ts +5 -9
- package/dist/types/models/interfaces.d.ts +0 -67
- package/dist/types/models/session.d.ts +4 -5
- package/dist/types/server/index.d.ts +1 -1
- package/dist/types/session/SessionClient.d.ts +26 -1
- package/dist/types/session/authStateStore.d.ts +119 -0
- package/dist/types/session/refresh.d.ts +93 -0
- package/dist/types/shared/utils/debugUtils.d.ts +3 -3
- package/dist/types/utils/accountUtils.d.ts +2 -17
- package/dist/types/utils/authWebUrl.d.ts +9 -35
- package/dist/types/utils/coldBoot.d.ts +17 -14
- package/dist/types/utils/platform.d.ts +14 -0
- package/dist/types/utils/registrableApex.d.ts +31 -0
- package/dist/types/utils/ssoBounce.d.ts +14 -280
- package/dist/types/utils/validationUtils.d.ts +15 -0
- package/package.json +2 -2
- package/src/HttpService.ts +20 -4
- package/src/OxyServices.base.ts +7 -112
- package/src/OxyServices.ts +0 -38
- package/src/boot/__tests__/coldBootV2.test.ts +317 -0
- package/src/boot/__tests__/deviceBootReturn.test.ts +158 -0
- package/src/boot/coldBootV2.ts +426 -0
- package/src/boot/deviceBootReturn.ts +195 -0
- package/src/crypto/__tests__/sharedDeviceToken.test.ts +24 -0
- package/src/crypto/keyManager.ts +101 -0
- package/src/i18n/locales/en-US.json +13 -1
- package/src/i18n/locales/es-ES.json +13 -1
- package/src/index.ts +75 -65
- package/src/mixins/OxyServices.accounts.ts +27 -39
- package/src/mixins/OxyServices.auth.ts +78 -253
- package/src/mixins/OxyServices.deviceBoot.ts +146 -0
- package/src/mixins/__tests__/OxyServices.deviceBoot.test.ts +107 -0
- package/src/mixins/__tests__/accounts.test.ts +17 -44
- package/src/mixins/__tests__/passwordSignIn.test.ts +91 -0
- package/src/mixins/index.ts +10 -23
- package/src/models/interfaces.ts +0 -79
- package/src/models/session.ts +4 -5
- package/src/server/index.ts +1 -1
- package/src/session/SessionClient.ts +53 -2
- package/src/session/__tests__/SessionClient.additive.test.ts +92 -0
- package/src/session/__tests__/SessionClient.rest.test.ts +25 -0
- package/src/session/__tests__/SessionClient.state.test.ts +18 -5
- package/src/session/__tests__/authStateStore.test.ts +209 -0
- package/src/session/__tests__/refresh.test.ts +256 -0
- package/src/session/authStateStore.ts +335 -0
- package/src/session/refresh.ts +334 -0
- package/src/shared/utils/debugUtils.ts +3 -3
- package/src/utils/__tests__/authWebUrl.test.ts +5 -40
- package/src/utils/__tests__/registrableApex.test.ts +62 -0
- package/src/utils/__tests__/validationUtils.test.ts +30 -0
- package/src/utils/accountUtils.ts +2 -65
- package/src/utils/authWebUrl.ts +9 -39
- package/src/utils/coldBoot.ts +17 -14
- package/src/utils/platform.ts +21 -0
- package/src/utils/registrableApex.ts +45 -0
- package/src/utils/ssoBounce.ts +14 -393
- package/src/utils/validationUtils.ts +62 -0
- package/dist/cjs/AuthManager.js +0 -1110
- package/dist/cjs/AuthManagerTypes.js +0 -13
- package/dist/cjs/CrossDomainAuth.js +0 -206
- package/dist/cjs/mixins/OxyServices.fedcm.js +0 -823
- package/dist/cjs/mixins/OxyServices.redirect.js +0 -95
- package/dist/cjs/mixins/OxyServices.silent.js +0 -204
- package/dist/cjs/mixins/OxyServices.sso.js +0 -208
- package/dist/cjs/utils/fapiAutoDetect.js +0 -99
- package/dist/cjs/utils/ssoEstablish.js +0 -110
- package/dist/cjs/utils/ssoReturn.js +0 -275
- package/dist/esm/AuthManager.js +0 -1105
- package/dist/esm/AuthManagerTypes.js +0 -12
- package/dist/esm/CrossDomainAuth.js +0 -201
- package/dist/esm/mixins/OxyServices.fedcm.js +0 -821
- package/dist/esm/mixins/OxyServices.redirect.js +0 -92
- package/dist/esm/mixins/OxyServices.silent.js +0 -202
- package/dist/esm/mixins/OxyServices.sso.js +0 -204
- package/dist/esm/utils/fapiAutoDetect.js +0 -95
- package/dist/esm/utils/ssoEstablish.js +0 -107
- package/dist/esm/utils/ssoReturn.js +0 -271
- package/dist/types/AuthManager.d.ts +0 -380
- package/dist/types/AuthManagerTypes.d.ts +0 -81
- package/dist/types/CrossDomainAuth.d.ts +0 -164
- package/dist/types/mixins/OxyServices.fedcm.d.ts +0 -331
- package/dist/types/mixins/OxyServices.redirect.d.ts +0 -92
- package/dist/types/mixins/OxyServices.silent.d.ts +0 -132
- package/dist/types/mixins/OxyServices.sso.d.ts +0 -138
- package/dist/types/utils/fapiAutoDetect.d.ts +0 -56
- package/dist/types/utils/ssoEstablish.d.ts +0 -85
- package/dist/types/utils/ssoReturn.d.ts +0 -156
- package/src/AuthManager.ts +0 -1269
- package/src/AuthManagerTypes.ts +0 -86
- package/src/CrossDomainAuth.ts +0 -243
- package/src/__tests__/authManager.cookiePath.test.ts +0 -390
- package/src/__tests__/authManager.security.test.ts +0 -377
- package/src/__tests__/crossDomainAuth.test.ts +0 -116
- package/src/__tests__/establishDeviceRefreshSlot.test.ts +0 -221
- package/src/mixins/OxyServices.fedcm.ts +0 -1026
- package/src/mixins/OxyServices.redirect.ts +0 -122
- package/src/mixins/OxyServices.silent.ts +0 -272
- package/src/mixins/OxyServices.sso.ts +0 -261
- package/src/mixins/__tests__/constructorAuthWebUrl.test.ts +0 -85
- package/src/mixins/__tests__/fedcm.test.ts +0 -667
- package/src/mixins/__tests__/sessionBaseUrl.test.ts +0 -61
- package/src/mixins/__tests__/silent.test.ts +0 -102
- package/src/mixins/__tests__/sso.test.ts +0 -228
- package/src/utils/__tests__/consumeSsoReturn.test.ts +0 -816
- package/src/utils/__tests__/fapiAutoDetect.test.ts +0 -183
- package/src/utils/__tests__/ssoBounce.test.ts +0 -219
- package/src/utils/__tests__/ssoEstablish.test.ts +0 -204
- package/src/utils/__tests__/ssoReturn.test.ts +0 -276
- package/src/utils/fapiAutoDetect.ts +0 -91
- package/src/utils/ssoEstablish.ts +0 -174
- package/src/utils/ssoReturn.ts +0 -389
|
@@ -26,6 +26,19 @@ export interface RequestOptions {
|
|
|
26
26
|
signal?: AbortSignal;
|
|
27
27
|
headers?: Record<string, string>;
|
|
28
28
|
responseType?: 'blob';
|
|
29
|
+
/**
|
|
30
|
+
* Skip BOTH the bearer auth header (and its near-expiry preflight refresh)
|
|
31
|
+
* AND the 401-driven auto-refresh/retry for this request.
|
|
32
|
+
*
|
|
33
|
+
* Required for the body-authenticated refresh endpoint (`POST
|
|
34
|
+
* /auth/refresh-token`): it does not need a bearer, and — critically — it is
|
|
35
|
+
* itself invoked from inside the registered `AuthRefreshHandler`. If it went
|
|
36
|
+
* through the normal preflight, `getAuthHeader` would call
|
|
37
|
+
* `refreshAccessToken` while the handler-owning `tokenRefreshPromise` is
|
|
38
|
+
* still in flight and await ITSELF (deadlock). Skipping auth makes the
|
|
39
|
+
* refresh call fully independent of the current (near-expired) bearer.
|
|
40
|
+
*/
|
|
41
|
+
skipAuth?: boolean;
|
|
29
42
|
}
|
|
30
43
|
interface RequestConfig extends RequestOptions {
|
|
31
44
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
@@ -144,7 +157,7 @@ export declare class HttpService {
|
|
|
144
157
|
* `clearCacheByPrefix` sweeps and `clearCacheEntry` base-key matching.
|
|
145
158
|
* The `clearCacheEntry` callsites all pass fixed, dataless logical keys
|
|
146
159
|
* (`GET:/users/<id>`, `GET:/session/user/<sessionId>`,
|
|
147
|
-
* `GET:/
|
|
160
|
+
* `GET:/auth/grants`), so this readable suffix can never be
|
|
148
161
|
* ambiguous with a serialized request body.
|
|
149
162
|
*/
|
|
150
163
|
private static readonly CACHE_IDENTITY_DELIM;
|
|
@@ -25,20 +25,6 @@ export declare class OxyServicesBase {
|
|
|
25
25
|
* Get the configured Oxy API base URL
|
|
26
26
|
*/
|
|
27
27
|
getBaseURL(): string;
|
|
28
|
-
/**
|
|
29
|
-
* Get the base URL the SDK's first-party session/refresh calls should target.
|
|
30
|
-
*
|
|
31
|
-
* Returns the configured `sessionBaseUrl` when provided, otherwise falls back
|
|
32
|
-
* to the API `baseURL` (`getBaseURL()`). Per the 2026 session architecture
|
|
33
|
-
* (docs/SESSION-ARCHITECTURE.md), non-`oxy.so` apps point this at their own
|
|
34
|
-
* same-site backend (e.g. `https://api.mention.earth`) whose session bridge
|
|
35
|
-
* forwards the user's refresh credential to `api.oxy.so`; `*.oxy.so` apps
|
|
36
|
-
* leave it unset so it resolves to `https://api.oxy.so` and nothing changes.
|
|
37
|
-
*
|
|
38
|
-
* This is additive: it only exposes configuration for `@oxyhq/services` to
|
|
39
|
-
* consume in a later phase. No refresh/auth logic in core reads it yet.
|
|
40
|
-
*/
|
|
41
|
-
getSessionBaseUrl(): string;
|
|
42
28
|
/**
|
|
43
29
|
* Get the HTTP service instance
|
|
44
30
|
* Useful for advanced use cases where direct access to the HTTP service is needed
|
|
@@ -142,44 +128,6 @@ export declare class OxyServicesBase {
|
|
|
142
128
|
* Get the raw access token (for constructing anchor URLs when needed)
|
|
143
129
|
*/
|
|
144
130
|
getAccessToken(): string | null;
|
|
145
|
-
/**
|
|
146
|
-
* Register the CURRENTLY-ACTIVE session in the device's first-party
|
|
147
|
-
* multi-account refresh-cookie set by calling `POST /auth/session`.
|
|
148
|
-
*
|
|
149
|
-
* This is the single, shared primitive every web primary-session commit and the
|
|
150
|
-
* account switch use to plant their `oxy_rt_<authuser>` slot. It MUST be a
|
|
151
|
-
* dedicated call to `/auth/session` rather than relying on whichever endpoint
|
|
152
|
-
* established the session: that endpoint is frequently OUTSIDE the cookie's
|
|
153
|
-
* `Path=/auth` scope (`/accounts/:id/switch`) or is a cross-origin/credential-
|
|
154
|
-
* less restore (`/sso/exchange`, the IdP `/auth/silent` postMessage) that cannot
|
|
155
|
-
* set an `api.oxy.so` cookie at all. `/auth/session` runs where the device's
|
|
156
|
-
* existing slots ARE visible, so the server resolves this user's slot (reusing an
|
|
157
|
-
* existing one or allocating a new one) without clobbering a sibling account,
|
|
158
|
-
* mints a fresh access token bound to the same session, and returns the resolved
|
|
159
|
-
* `authuser`.
|
|
160
|
-
*
|
|
161
|
-
* Behaviour:
|
|
162
|
-
* - Requires a planted bearer (the caller must have already installed the
|
|
163
|
-
* session's access token); `/auth/session` derives the session from it.
|
|
164
|
-
* - On success re-plants the rotated access token (so the active token matches
|
|
165
|
-
* the freshly-rotated cookie) and returns the device `authuser` slot.
|
|
166
|
-
* - WEB-ONLY: on native there are no first-party refresh cookies → returns
|
|
167
|
-
* `null`.
|
|
168
|
-
* - FIRST-PARTY-ONLY: the cookie is host-only on the API host with
|
|
169
|
-
* `SameSite=Lax`, so it only sticks when the page is SAME-SITE (same
|
|
170
|
-
* registrable apex) as the API. On a cross-apex RP (`mention.earth` calling
|
|
171
|
-
* `api.oxy.so`) the browser rejects the `Set-Cookie` as a third-party cookie,
|
|
172
|
-
* so a returned slot would be a phantom never enumerated by `refresh-all`.
|
|
173
|
-
* Those RPs durably restore via the per-apex `/auth/silent` iframe + `/sso`
|
|
174
|
-
* bounce, NOT this device set → returns `null` without calling the API.
|
|
175
|
-
* - BEST-EFFORT: a failure (e.g. transient network) never throws — the session
|
|
176
|
-
* stays active in-memory; only its reload durability via the device set is at
|
|
177
|
-
* risk. The caller treats `null` as "not registered in the device set".
|
|
178
|
-
*
|
|
179
|
-
* @returns The resolved device `authuser` slot, or `null` on native / cross-apex
|
|
180
|
-
* / failure.
|
|
181
|
-
*/
|
|
182
|
-
establishDeviceRefreshSlot(): Promise<number | null>;
|
|
183
131
|
/**
|
|
184
132
|
* Decode the current access token and return its `exp` claim in SECONDS since
|
|
185
133
|
* the Unix epoch (the raw JWT `exp` unit), or `null` when there is no token,
|
|
@@ -58,10 +58,6 @@
|
|
|
58
58
|
*/
|
|
59
59
|
import { type LinkedHttpClient, type OxyConfig } from './OxyServices.base';
|
|
60
60
|
import { OxyAuthenticationError, OxyAuthenticationTimeoutError } from './OxyServices.errors';
|
|
61
|
-
import type { SessionLoginResponse } from './models/session';
|
|
62
|
-
import type { FedCMAuthOptions, FedCMConfig } from './mixins/OxyServices.fedcm';
|
|
63
|
-
import type { SilentAuthOptions } from './mixins/OxyServices.silent';
|
|
64
|
-
import type { RedirectAuthOptions } from './mixins/OxyServices.redirect';
|
|
65
61
|
import { composeOxyServices } from './mixins';
|
|
66
62
|
/**
|
|
67
63
|
* OxyServices - Unified client library for interacting with the Oxy API
|
|
@@ -100,31 +96,10 @@ import { composeOxyServices } from './mixins';
|
|
|
100
96
|
*/
|
|
101
97
|
declare const OxyServicesComposed: import("./mixins").ComposedOxyServicesConstructor;
|
|
102
98
|
export declare class OxyServices extends OxyServicesComposed {
|
|
103
|
-
/**
|
|
104
|
-
* FedCM credential-request timeouts (ms). The runtime values are defined on
|
|
105
|
-
* the FedCM mixin and inherited here via `extends`; these `declare` members
|
|
106
|
-
* surface their types to TypeScript without re-emitting (or duplicating) the
|
|
107
|
-
* literals, so consumers/tests can reference `OxyServices.FEDCM_SILENT_TIMEOUT`
|
|
108
|
-
* with full typing.
|
|
109
|
-
*/
|
|
110
|
-
static readonly FEDCM_TIMEOUT: number;
|
|
111
|
-
static readonly FEDCM_SILENT_TIMEOUT: number;
|
|
112
99
|
constructor(config: OxyConfig);
|
|
113
100
|
}
|
|
114
101
|
export interface OxyServices extends InstanceType<ReturnType<typeof composeOxyServices>> {
|
|
115
102
|
createLinkedClient(config: OxyConfig): LinkedHttpClient;
|
|
116
|
-
isFedCMSupported(): boolean;
|
|
117
|
-
signInWithFedCM(options?: FedCMAuthOptions): Promise<SessionLoginResponse>;
|
|
118
|
-
silentSignInWithFedCM(): Promise<SessionLoginResponse | null>;
|
|
119
|
-
revokeFedCMCredential(): Promise<void>;
|
|
120
|
-
getFedCMConfig(): FedCMConfig;
|
|
121
|
-
resolveAuthUrl(): string;
|
|
122
|
-
silentSignIn(options?: SilentAuthOptions): Promise<SessionLoginResponse | null>;
|
|
123
|
-
waitForIframeAuth(iframe: HTMLIFrameElement, timeout: number, expectedOrigin: string): Promise<SessionLoginResponse | null>;
|
|
124
|
-
signInWithRedirect(options?: RedirectAuthOptions): void;
|
|
125
|
-
signUpWithRedirect(options?: RedirectAuthOptions): void;
|
|
126
|
-
exchangeSsoCode(code: string, state?: string): Promise<SessionLoginResponse>;
|
|
127
|
-
generateSsoState(): string;
|
|
128
103
|
auth(options?: {
|
|
129
104
|
debug?: boolean;
|
|
130
105
|
onError?: (error: unknown) => unknown;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type ColdBootOutcome } from '../utils/coldBoot';
|
|
2
|
+
import type { OxyServices } from '../OxyServices';
|
|
3
|
+
import type { AuthStateStore } from '../session/authStateStore';
|
|
4
|
+
import { type DeviceBootSession } from './deviceBootReturn';
|
|
5
|
+
/**
|
|
6
|
+
* localStorage flag marking that the cross-apex bootstrap navigation has fired
|
|
7
|
+
* once for this origin. Persistent (not session) so the visible redirect
|
|
8
|
+
* happens AT MOST ONCE EVER per browser+origin — a signed-out user is never
|
|
9
|
+
* bounced again; they sign in explicitly.
|
|
10
|
+
*/
|
|
11
|
+
export declare const BOOT_ATTEMPTED_KEY = "oxy.boot.attempted";
|
|
12
|
+
/** Why a cold boot ended without a session. */
|
|
13
|
+
export type SignedOutReason = 'no_session' | 'new_device' | 'state-mismatch' | 'error';
|
|
14
|
+
/**
|
|
15
|
+
* The DOM/storage seam. All access is injected so the boot is unit-testable
|
|
16
|
+
* under the jest `node` environment; {@link createBrowserColdBootDom} provides
|
|
17
|
+
* the guarded real-globals implementation used in production.
|
|
18
|
+
*/
|
|
19
|
+
export interface ColdBootDom {
|
|
20
|
+
getHash(): string;
|
|
21
|
+
stripFragment(): void;
|
|
22
|
+
getSessionItem(key: string): string | null;
|
|
23
|
+
setSessionItem(key: string, value: string): void;
|
|
24
|
+
removeSessionItem(key: string): void;
|
|
25
|
+
getLocalItem(key: string): string | null;
|
|
26
|
+
setLocalItem(key: string, value: string): void;
|
|
27
|
+
getLocationHostname(): string | null;
|
|
28
|
+
/** Current href WITHOUT its hash fragment (the bootstrap `return_to`). */
|
|
29
|
+
getReturnToHref(): string | null;
|
|
30
|
+
navigate(url: string): void;
|
|
31
|
+
/** A fresh high-entropy CSRF state token. */
|
|
32
|
+
randomState(): string;
|
|
33
|
+
}
|
|
34
|
+
export interface RunSessionColdBootOptions {
|
|
35
|
+
oxy: OxyServices;
|
|
36
|
+
store: AuthStateStore;
|
|
37
|
+
/** Platform hints; default derived from `@oxyhq/core`'s platform detection. */
|
|
38
|
+
platform?: {
|
|
39
|
+
isWeb?: boolean;
|
|
40
|
+
isNative?: boolean;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The RP return URL for the cross-apex hop. Defaults to the current href
|
|
44
|
+
* (sans fragment) via the DOM seam.
|
|
45
|
+
*/
|
|
46
|
+
returnTo?: string;
|
|
47
|
+
/** Invoked with the winning session (token already planted). */
|
|
48
|
+
onSession?: (session: DeviceBootSession & {
|
|
49
|
+
via: string;
|
|
50
|
+
}) => void | Promise<void>;
|
|
51
|
+
/** Invoked when the boot ended signed out (not while navigating away). */
|
|
52
|
+
onSignedOut?: (reason: SignedOutReason) => void | Promise<void>;
|
|
53
|
+
onStepError?: (id: string, error: unknown) => void;
|
|
54
|
+
/** DOM/storage seam; defaults to the guarded browser implementation. */
|
|
55
|
+
dom?: ColdBootDom;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The guarded real-globals {@link ColdBootDom}. Every accessor tolerates a
|
|
59
|
+
* missing/throwing global (SSR, sandboxed iframe) by returning a neutral value
|
|
60
|
+
* or no-op, so the boot degrades to signed-out rather than crashing.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createBrowserColdBootDom(): ColdBootDom;
|
|
63
|
+
/**
|
|
64
|
+
* True when both hosts are same-site / same-apex. For a normal multi-label host
|
|
65
|
+
* pair, that means sharing a registrable domain. For an IP literal or a
|
|
66
|
+
* single-label host (no registrable domain), same-apex requires the two hosts
|
|
67
|
+
* to be EXACTLY equal — never grouped by a spurious trailing-label match.
|
|
68
|
+
*/
|
|
69
|
+
export declare function isSameApex(pageHost: string, apiHost: string): boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Run the device-first cold boot. Resolves to the `runColdBoot` outcome and, as
|
|
72
|
+
* a side effect, invokes `onSession` (winning session, token already planted)
|
|
73
|
+
* or `onSignedOut` (no session — unless the boot is navigating away for the
|
|
74
|
+
* cross-apex hop, in which case neither fires).
|
|
75
|
+
*/
|
|
76
|
+
export declare function runSessionColdBoot(opts: RunSessionColdBootOptions): Promise<ColdBootOutcome<DeviceBootSession>>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device-boot return-fragment consumption (web cross-apex hop).
|
|
3
|
+
*
|
|
4
|
+
* After the top-level `GET /auth/device/bootstrap` hop, the API 303s back to the
|
|
5
|
+
* RP with a `#oxy_boot=<base64url(JSON)>` fragment. This module parses and
|
|
6
|
+
* consumes it: it strips the fragment from the URL FIRST (so the opaque
|
|
7
|
+
* deviceToken / code never linger in history or a `Referer`), verifies the
|
|
8
|
+
* echoed CSRF `state` against the value the initiator stashed in
|
|
9
|
+
* `sessionStorage`, persists the deviceToken, and — when a session resolved —
|
|
10
|
+
* exchanges the single-use `code` for a token bundle.
|
|
11
|
+
*
|
|
12
|
+
* Pure/injectable: all DOM access (hash, `history.replaceState`,
|
|
13
|
+
* `sessionStorage`) is passed in as callbacks so the logic is unit-testable
|
|
14
|
+
* under the jest `node` environment and reusable by `coldBootV2`.
|
|
15
|
+
*
|
|
16
|
+
* ESM-safe (no `require()`).
|
|
17
|
+
*/
|
|
18
|
+
import { type AuthTokenBundle, type DeviceBootFragment, type DeviceBootReason } from '@oxyhq/contracts';
|
|
19
|
+
import type { AuthStateStore } from '../session/authStateStore';
|
|
20
|
+
/** The `#oxy_boot=` fragment parameter name the API appends on the return hop. */
|
|
21
|
+
export declare const BOOT_FRAGMENT_PARAM = "oxy_boot";
|
|
22
|
+
/**
|
|
23
|
+
* `sessionStorage` key under which the bootstrap-hop initiator stashes the
|
|
24
|
+
* 128-bit CSRF `state` before navigating, and which the return step reads back
|
|
25
|
+
* (single-use).
|
|
26
|
+
*/
|
|
27
|
+
export declare const BOOT_STATE_SESSION_KEY = "oxy.boot.state";
|
|
28
|
+
/** True when a location hash carries the `oxy_boot` return fragment. */
|
|
29
|
+
export declare function hashHasBootFragment(hash: string): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Extract + decode + validate the `oxy_boot` fragment from a location hash.
|
|
32
|
+
* Returns the parsed {@link DeviceBootFragment}, or `null` when the parameter
|
|
33
|
+
* is absent, not valid base64url, not JSON, or fails the contract schema.
|
|
34
|
+
*/
|
|
35
|
+
export declare function parseDeviceBootFragment(hash: string): DeviceBootFragment | null;
|
|
36
|
+
/** The winning session shape a cold-boot step reports. */
|
|
37
|
+
export interface DeviceBootSession {
|
|
38
|
+
sessionId: string;
|
|
39
|
+
userId: string;
|
|
40
|
+
accessToken: string;
|
|
41
|
+
}
|
|
42
|
+
/** Outcome of {@link consumeDeviceBootReturn}. */
|
|
43
|
+
export type DeviceBootReturnOutcome = {
|
|
44
|
+
kind: 'none';
|
|
45
|
+
} | {
|
|
46
|
+
kind: 'state-mismatch';
|
|
47
|
+
} | {
|
|
48
|
+
kind: 'session';
|
|
49
|
+
session: DeviceBootSession;
|
|
50
|
+
} | {
|
|
51
|
+
kind: 'no-session';
|
|
52
|
+
reason: DeviceBootReason;
|
|
53
|
+
};
|
|
54
|
+
export interface ConsumeDeviceBootReturnDeps {
|
|
55
|
+
/** The current location hash (e.g. `window.location.hash`). */
|
|
56
|
+
hash: string;
|
|
57
|
+
/** Strip the fragment from the URL (e.g. `history.replaceState`). */
|
|
58
|
+
stripFragment: () => void;
|
|
59
|
+
/** Read the expected CSRF state (e.g. `sessionStorage.getItem(BOOT_STATE_SESSION_KEY)`). */
|
|
60
|
+
readExpectedState: () => string | null;
|
|
61
|
+
/** Clear the expected CSRF state (single-use). */
|
|
62
|
+
clearExpectedState: () => void;
|
|
63
|
+
store: AuthStateStore;
|
|
64
|
+
/** Exchange the single-use boot code for a token bundle (`oxy.exchangeBootCode`). */
|
|
65
|
+
exchangeBootCode: (code: string) => Promise<AuthTokenBundle>;
|
|
66
|
+
/** Plant the freshly-minted access token on the owner client (`oxy.setTokens`). */
|
|
67
|
+
plantAccessToken: (accessToken: string) => void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Consume the device-boot return fragment.
|
|
71
|
+
*
|
|
72
|
+
* Order is load-bearing:
|
|
73
|
+
* 1. If no fragment is present, return `none` (no URL mutation).
|
|
74
|
+
* 2. STRIP the fragment from the URL immediately — before validation or any
|
|
75
|
+
* network — so the deviceToken/code never persist in history/referrer.
|
|
76
|
+
* 3. Verify the echoed `state` against the stashed (single-use) value; a
|
|
77
|
+
* mismatch returns `state-mismatch` without persisting or exchanging.
|
|
78
|
+
* 4. Persist the deviceToken (survives sign-out).
|
|
79
|
+
* 5. If a session resolved (`reason:'session'` + `code`), exchange the code,
|
|
80
|
+
* persist the rotated session, plant the token, and return `session`.
|
|
81
|
+
* Otherwise return `no-session` with the reason.
|
|
82
|
+
*/
|
|
83
|
+
export declare function consumeDeviceBootReturn(deps: ConsumeDeviceBootReturnDeps): Promise<DeviceBootReturnOutcome>;
|
|
@@ -157,6 +157,27 @@ export declare class KeyManager {
|
|
|
157
157
|
* @returns True if migration was successful, false if no local identity exists
|
|
158
158
|
*/
|
|
159
159
|
static migrateToSharedIdentity(): Promise<boolean>;
|
|
160
|
+
/**
|
|
161
|
+
* Store the opaque device-attribution token in the SHARED keychain so every
|
|
162
|
+
* Oxy app on this device reads the SAME token and therefore resolves to one
|
|
163
|
+
* server-side DeviceSession.
|
|
164
|
+
*
|
|
165
|
+
* Mirrors the shared-session storage options exactly (iOS keychain access
|
|
166
|
+
* group `group.so.oxy.shared`; Android shared secure store). Native-only —
|
|
167
|
+
* a no-op on web (the shared keychain does not exist there; web persists its
|
|
168
|
+
* deviceToken in the per-origin {@link AuthStateStore} instead).
|
|
169
|
+
*/
|
|
170
|
+
static setSharedDeviceToken(deviceToken: string): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Read the shared device-attribution token, or `null` when none is set (or
|
|
173
|
+
* on web). Mirrors {@link getSharedSession}'s keychain-access-group read.
|
|
174
|
+
*/
|
|
175
|
+
static getSharedDeviceToken(): Promise<string | null>;
|
|
176
|
+
/**
|
|
177
|
+
* Delete the shared device-attribution token (device signout-all). Best-effort:
|
|
178
|
+
* a keychain failure is logged, not thrown, so it cannot block a sign-out.
|
|
179
|
+
*/
|
|
180
|
+
static clearSharedDeviceToken(): Promise<void>;
|
|
160
181
|
/**
|
|
161
182
|
* Atomically persist a key pair to secure storage with verification + backup.
|
|
162
183
|
*
|
package/dist/types/index.d.ts
CHANGED
|
@@ -21,14 +21,6 @@ export { OxyServices, OxyAuthenticationError, OxyAuthenticationTimeoutError } fr
|
|
|
21
21
|
export { OXY_CLOUD_URL, oxyClient } from './OxyServices';
|
|
22
22
|
export type { LinkedHttpClient } from './OxyServices.base';
|
|
23
23
|
export type { AuthRefreshReason, AuthRefreshHandler } from './HttpService';
|
|
24
|
-
export { AuthManager, createAuthManager } from './AuthManager';
|
|
25
|
-
export type { StorageAdapter, AuthStateChangeCallback, AuthMethod, AuthManagerConfig, } from './AuthManager';
|
|
26
|
-
export type { AuthManagerAccount, RestoreFromCookiesResult, RestoreFromCookiesOptions, SwitchAuthuserResult, } from './AuthManagerTypes';
|
|
27
|
-
export { CrossDomainAuth, createCrossDomainAuth } from './CrossDomainAuth';
|
|
28
|
-
export type { CrossDomainAuthOptions } from './CrossDomainAuth';
|
|
29
|
-
export type { FedCMAuthOptions, FedCMConfig, AuthorizedApp } from './mixins/OxyServices.fedcm';
|
|
30
|
-
export type { SilentAuthOptions } from './mixins/OxyServices.silent';
|
|
31
|
-
export type { RedirectAuthOptions } from './mixins/OxyServices.redirect';
|
|
32
24
|
export { ServiceCredentialMismatchError } from './mixins/OxyServices.auth';
|
|
33
25
|
export type { ServiceTokenResponse } from './mixins/OxyServices.auth';
|
|
34
26
|
export type { CommonsSignInHandle, CommonsSignInStatus, CommonsApprovalInfo, CommonsSignInActionResult, } from './mixins/OxyServices.auth';
|
|
@@ -53,7 +45,6 @@ export { SessionSyncRequiredError, AuthenticationFailedError, ensureValidToken,
|
|
|
53
45
|
export type { HandleApiErrorOptions } from './utils/authHelpers';
|
|
54
46
|
export { mergeSessions, normalizeAndSortSessions, sessionsArraysEqual, } from './utils/sessionUtils';
|
|
55
47
|
export type { ClientSession, StorageKeys, MinimalUserData, SessionLoginResponse, } from './models/session';
|
|
56
|
-
export type { RefreshAllResponse, RefreshAllAccount, RefreshAllAccountUser, RefreshCookieResponse, } from './models/interfaces';
|
|
57
48
|
export { KeyManager, IdentityAlreadyExistsError, IdentityPersistError, } from './crypto/keyManager';
|
|
58
49
|
export type { KeyPair } from './crypto/keyManager';
|
|
59
50
|
export { SignatureService } from './crypto/signatureService';
|
|
@@ -68,7 +59,7 @@ export { TopicType, TopicSource } from './models/Topic';
|
|
|
68
59
|
export type { TopicData, TopicTranslation } from './models/Topic';
|
|
69
60
|
export { SUPPORTED_LANGUAGES, getLanguageMetadata, getLanguageName, getNativeLanguageName, normalizeLanguageCode, isRTLLocale, } from './utils/languageUtils';
|
|
70
61
|
export type { LanguageMetadata } from './utils/languageUtils';
|
|
71
|
-
export { getPlatformOS, setPlatformOS, isWeb, isNative, isIOS, isAndroid, } from './utils/platform';
|
|
62
|
+
export { getPlatformOS, setPlatformOS, isWeb, isNative, isIOS, isAndroid, isWebBrowser, } from './utils/platform';
|
|
72
63
|
export type { PlatformOS } from './utils/platform';
|
|
73
64
|
export { darkenColor, lightenColor, hexToRgb, rgbToHex, withOpacity, isLightColor, getContrastTextColor, } from './shared/utils/colorUtils';
|
|
74
65
|
export { normalizeTheme, normalizeColorScheme, getOppositeTheme, systemPrefersDarkMode, getSystemColorScheme, } from './shared/utils/themeUtils';
|
|
@@ -82,21 +73,15 @@ export { buildSearchParams, buildUrl, buildPaginationParams, safeJsonParse, } fr
|
|
|
82
73
|
export type { PaginationParams, ApiResponse, ErrorResponse, } from './utils/apiUtils';
|
|
83
74
|
export { ErrorCodes, createApiError, handleHttpError, validateRequiredFields, } from './utils/errorUtils';
|
|
84
75
|
export { retryAsync } from './utils/asyncUtils';
|
|
85
|
-
export { EMAIL_REGEX, USERNAME_REGEX, PASSWORD_REGEX, isValidEmail, isValidUsername, isValidPassword, isRequiredString, isRequiredNumber, isRequiredBoolean, isValidArray, isValidObject, isValidUUID, isValidURL, isValidDate, isValidFileSize, isValidFileType, sanitizeString, sanitizeHTML, isValidObjectId, validateAndSanitizeUserInput, } from './utils/validationUtils';
|
|
76
|
+
export { EMAIL_REGEX, USERNAME_REGEX, PASSWORD_REGEX, isValidEmail, isValidUsername, isValidPassword, isValidDisplayName, isRequiredString, isRequiredNumber, isRequiredBoolean, isValidArray, isValidObject, isValidUUID, isValidURL, isValidDate, isValidFileSize, isValidFileType, sanitizeString, sanitizeHTML, isValidObjectId, validateAndSanitizeUserInput, } from './utils/validationUtils';
|
|
86
77
|
export { logger, LogLevel, logAuth, logApi, logSession, logUser, logDevice, logPayment, logPerformance, } from './utils/loggerUtils';
|
|
87
78
|
export type { LogContext } from './utils/loggerUtils';
|
|
88
79
|
export { updateAvatarVisibility } from './utils/avatarUtils';
|
|
89
|
-
export { buildAccountsArray, createQuickAccount, getAccountDisplayName, getAccountFallbackHandle, formatPublicKeyHandle,
|
|
80
|
+
export { buildAccountsArray, createQuickAccount, getAccountDisplayName, getAccountFallbackHandle, formatPublicKeyHandle, getAccountColor, } from './utils/accountUtils';
|
|
90
81
|
export type { QuickAccount, DisplayNameUserShape } from './utils/accountUtils';
|
|
91
|
-
export {
|
|
92
|
-
export {
|
|
93
|
-
export {
|
|
94
|
-
export type { SsoReturnKind, SsoReturnResult, ConsumeSsoReturnDeps } from './utils/ssoReturn';
|
|
95
|
-
export { generateSsoState } from './mixins/OxyServices.sso';
|
|
96
|
-
export { establishIdpSessionAfterClaim } from './utils/ssoEstablish';
|
|
97
|
-
export type { SsoEstablishClient, EstablishAfterClaimDeps } from './utils/ssoEstablish';
|
|
98
|
-
export { SSO_CALLBACK_PATH, SSO_GUARD_TTL_MS, ssoStateKey, ssoGuardKey, ssoDestKey, ssoNoSessionKey, ssoAttemptedKey, ssoPriorSessionKey, ssoSignedOutKey, ssoOutcomeKey, ssoCallbackBootstrapKey, ssoNavigate, getSsoCallbackBootstrapScript, buildSsoBounceUrl, isCentralIdPOrigin, guardActive, silentRestoreSuppressed, allowSsoBounce, } from './utils/ssoBounce';
|
|
99
|
-
export type { SsoBounceGate } from './utils/ssoBounce';
|
|
82
|
+
export { registrableApex } from './utils/registrableApex';
|
|
83
|
+
export { CENTRAL_IDP_APEX } from './utils/authWebUrl';
|
|
84
|
+
export { SSO_CALLBACK_PATH } from './utils/ssoBounce';
|
|
100
85
|
export { runColdBoot } from './utils/coldBoot';
|
|
101
86
|
export type { ColdBootStep, ColdBootStepResult, ColdBootSession, ColdBootSkip, ColdBootOutcome, RunColdBootOptions, } from './utils/coldBoot';
|
|
102
87
|
export { SessionClient } from './session/SessionClient';
|
|
@@ -105,6 +90,14 @@ export type { SocketIOFactory, MinimalSocket } from './session/socketLoader';
|
|
|
105
90
|
export { createSessionClientHost } from './session/sessionClientHost';
|
|
106
91
|
export { createSessionClient } from './session/createSessionClient';
|
|
107
92
|
export { deviceStateToClientSessions, activeSessionIdOf, activeUserOf, accountIdsOf, } from './session/projectSessionState';
|
|
93
|
+
export { createWebAuthStateStore, createNativeAuthStateStore, createMemoryAuthStateStore, AUTH_STATE_STORAGE_KEY, DEVICE_TOKEN_STORAGE_KEY, } from './session/authStateStore';
|
|
94
|
+
export type { PersistedAuthState, AuthStateStore, NativeKeyValueStorage, } from './session/authStateStore';
|
|
95
|
+
export { refreshPersistedSession, createAuthRefreshHandler, installAuthRefreshHandler, startTokenRefreshScheduler, TOKEN_REFRESH_LEAD_MS, } from './session/refresh';
|
|
96
|
+
export type { RefreshDeps, TokenRefreshSchedulerHandle } from './session/refresh';
|
|
97
|
+
export { runSessionColdBoot, createBrowserColdBootDom, isSameApex, BOOT_ATTEMPTED_KEY, } from './boot/coldBootV2';
|
|
98
|
+
export type { RunSessionColdBootOptions, ColdBootDom, SignedOutReason, } from './boot/coldBootV2';
|
|
99
|
+
export { consumeDeviceBootReturn, parseDeviceBootFragment, hashHasBootFragment, BOOT_FRAGMENT_PARAM, BOOT_STATE_SESSION_KEY, } from './boot/deviceBootReturn';
|
|
100
|
+
export type { DeviceBootSession, DeviceBootReturnOutcome, ConsumeDeviceBootReturnDeps, } from './boot/deviceBootReturn';
|
|
108
101
|
export { packageInfo } from './constants/version';
|
|
109
102
|
import { OxyServices } from './OxyServices';
|
|
110
103
|
export default OxyServices;
|
|
@@ -28,8 +28,9 @@
|
|
|
28
28
|
* SWITCHING INTO AN ACCOUNT: `switchToAccount(accountId)` mints a REAL session
|
|
29
29
|
* for the target account and plants it as the active session — there is no
|
|
30
30
|
* per-request "acting-as" header. Identity is carried by the session/token, not
|
|
31
|
-
* a delegation header, so a switch propagates through reload and
|
|
32
|
-
* exactly like a login
|
|
31
|
+
* a delegation header, so a switch propagates through reload and cross-domain
|
|
32
|
+
* exactly like a login, via the device-first session model (the server
|
|
33
|
+
* registers the switched session into the operator's device-set directly).
|
|
33
34
|
*/
|
|
34
35
|
import type { User } from '../models/interfaces';
|
|
35
36
|
import type { SessionLoginResponse } from '../models/session';
|
|
@@ -387,22 +388,22 @@ export interface AccountSuccessResult {
|
|
|
387
388
|
/**
|
|
388
389
|
* Result of {@link OxyServicesAccountsMixin.switchToAccount} — the freshly
|
|
389
390
|
* minted session for the target account, in the SAME shape the canonical login
|
|
390
|
-
* / `claimSessionByToken` responses use (`SessionLoginResponse`)
|
|
391
|
-
* device-local refresh-cookie slot index.
|
|
391
|
+
* / `claimSessionByToken` responses use (`SessionLoginResponse`).
|
|
392
392
|
*
|
|
393
393
|
* `accessToken` is the first access token for the new session (already planted
|
|
394
|
-
* as the active token by `switchToAccount`). The
|
|
395
|
-
*
|
|
396
|
-
*
|
|
397
|
-
*
|
|
394
|
+
* as the active token by `switchToAccount`). The switched session's survival
|
|
395
|
+
* across reload and cross-domain sync is device-first: the server registers
|
|
396
|
+
* it into the operator's `DeviceSession` set directly
|
|
397
|
+
* (`deviceSessionService.addAccount`, broadcast to the device room) — there is
|
|
398
|
+
* no client-side refresh-cookie slot to establish. `user` is the target
|
|
399
|
+
* account.
|
|
398
400
|
*/
|
|
399
401
|
export interface SwitchAccountResult extends SessionLoginResponse {
|
|
400
402
|
/**
|
|
401
|
-
*
|
|
402
|
-
*
|
|
403
|
-
*
|
|
404
|
-
*
|
|
405
|
-
* switch itself still succeeds).
|
|
403
|
+
* Legacy device-local refresh-cookie slot index. The current server switch
|
|
404
|
+
* response never sets this field (device-set registration replaced the
|
|
405
|
+
* cookie-slot model) — kept optional for backward type-compatibility with
|
|
406
|
+
* any caller still reading it, but always `undefined` in practice.
|
|
406
407
|
*/
|
|
407
408
|
authuser?: number;
|
|
408
409
|
}
|
|
@@ -432,24 +433,18 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
|
|
|
432
433
|
* target, directly or inherited — else 403; 404 if missing/archived; 403 if
|
|
433
434
|
* the target is a personal account), then mints a REAL session for the
|
|
434
435
|
* target account and returns it in the canonical login / `claimSessionByToken`
|
|
435
|
-
* shape (`{ sessionId, deviceId, expiresAt, accessToken, user
|
|
436
|
+
* shape (`{ sessionId, deviceId, expiresAt, accessToken, user }`).
|
|
436
437
|
*
|
|
437
438
|
* Unlike the removed `X-Acting-As` delegation header, the returned session
|
|
438
439
|
* IS the new identity: this plants `accessToken` as the active token —
|
|
439
440
|
* exactly like `claimSessionByToken` / `verifyChallenge` — so every
|
|
440
441
|
* subsequent request authenticates as the target account.
|
|
441
442
|
*
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
*
|
|
445
|
-
*
|
|
446
|
-
*
|
|
447
|
-
* would clobber slot 0 (destroying the operator's own session). `/auth/session`
|
|
448
|
-
* runs where those cookies ARE visible, so the server allocates a NEW slot that
|
|
449
|
-
* coexists with the operator's and returns its `authuser`. This step is
|
|
450
|
-
* web-only (native multi-account uses stored sessions, not cookies) and
|
|
451
|
-
* best-effort — a failure leaves the in-session switch intact; the switched
|
|
452
|
-
* account simply won't survive a reload until the cookie is next established.
|
|
443
|
+
* A single call is all that's needed: the server registers the switched
|
|
444
|
+
* session into the operator's `DeviceSession` set directly, inheriting the
|
|
445
|
+
* operator's central `deviceId` so the switch survives a reload and syncs
|
|
446
|
+
* cross-domain via the same device-first session model as a normal login —
|
|
447
|
+
* there is no separate client-side cookie/slot step to make it stick.
|
|
453
448
|
*
|
|
454
449
|
* After planting, the SDK's identity-scoped GET cache is fully cleared so
|
|
455
450
|
* every cached read re-fetches as the new account. (The consuming
|
|
@@ -459,7 +454,7 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
|
|
|
459
454
|
* same-user silent refreshes, so the sweep here is explicit.)
|
|
460
455
|
*
|
|
461
456
|
* @param accountId - The target account's Mongo `_id`.
|
|
462
|
-
* @returns The minted session
|
|
457
|
+
* @returns The minted session, already planted as the active session.
|
|
463
458
|
*/
|
|
464
459
|
switchToAccount(accountId: string): Promise<SwitchAccountResult>;
|
|
465
460
|
/**
|
|
@@ -655,7 +650,6 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
|
|
|
655
650
|
__resetTokensForTests(): void;
|
|
656
651
|
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
657
652
|
getBaseURL(): string;
|
|
658
|
-
getSessionBaseUrl(): string;
|
|
659
653
|
getClient(): import("../HttpService").HttpService;
|
|
660
654
|
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
661
655
|
getMetrics(): {
|
|
@@ -684,7 +678,6 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
|
|
|
684
678
|
getCurrentUserId(): string | null;
|
|
685
679
|
hasValidToken(): boolean;
|
|
686
680
|
getAccessToken(): string | null;
|
|
687
|
-
establishDeviceRefreshSlot(): Promise<number | null>;
|
|
688
681
|
getAccessTokenExpiry(): number | null;
|
|
689
682
|
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
690
683
|
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
@@ -696,7 +689,9 @@ export declare function OxyServicesAccountsMixin<T extends typeof OxyServicesBas
|
|
|
696
689
|
handleError(error: unknown): Error;
|
|
697
690
|
healthCheck(): Promise<{
|
|
698
691
|
status: string;
|
|
699
|
-
users
|
|
692
|
+
users
|
|
693
|
+
/** Aggregate totals for an application over the requested period. */
|
|
694
|
+
? /** Aggregate totals for an application over the requested period. */: number;
|
|
700
695
|
timestamp?: string;
|
|
701
696
|
[key: string]: any;
|
|
702
697
|
}>;
|
|
@@ -25,7 +25,6 @@ export declare function OxyServicesAnalyticsMixin<T extends typeof OxyServicesBa
|
|
|
25
25
|
__resetTokensForTests(): void;
|
|
26
26
|
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
27
27
|
getBaseURL(): string;
|
|
28
|
-
getSessionBaseUrl(): string;
|
|
29
28
|
getClient(): import("../HttpService").HttpService;
|
|
30
29
|
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
31
30
|
getMetrics(): {
|
|
@@ -54,7 +53,6 @@ export declare function OxyServicesAnalyticsMixin<T extends typeof OxyServicesBa
|
|
|
54
53
|
getCurrentUserId(): string | null;
|
|
55
54
|
hasValidToken(): boolean;
|
|
56
55
|
getAccessToken(): string | null;
|
|
57
|
-
establishDeviceRefreshSlot(): Promise<number | null>;
|
|
58
56
|
getAccessTokenExpiry(): number | null;
|
|
59
57
|
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
60
58
|
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
@@ -61,7 +61,6 @@ export declare function OxyServicesAppDataMixin<T extends typeof OxyServicesBase
|
|
|
61
61
|
__resetTokensForTests(): void;
|
|
62
62
|
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
63
63
|
getBaseURL(): string;
|
|
64
|
-
getSessionBaseUrl(): string;
|
|
65
64
|
getClient(): import("../HttpService").HttpService;
|
|
66
65
|
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
67
66
|
getMetrics(): {
|
|
@@ -90,7 +89,6 @@ export declare function OxyServicesAppDataMixin<T extends typeof OxyServicesBase
|
|
|
90
89
|
getCurrentUserId(): string | null;
|
|
91
90
|
hasValidToken(): boolean;
|
|
92
91
|
getAccessToken(): string | null;
|
|
93
|
-
establishDeviceRefreshSlot(): Promise<number | null>;
|
|
94
92
|
getAccessTokenExpiry(): number | null;
|
|
95
93
|
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
96
94
|
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
@@ -180,7 +180,6 @@ export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>
|
|
|
180
180
|
__resetTokensForTests(): void;
|
|
181
181
|
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
182
182
|
getBaseURL(): string;
|
|
183
|
-
getSessionBaseUrl(): string;
|
|
184
183
|
getClient(): import("../HttpService").HttpService;
|
|
185
184
|
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
186
185
|
getMetrics(): {
|
|
@@ -209,7 +208,6 @@ export declare function OxyServicesAssetsMixin<T extends typeof OxyServicesBase>
|
|
|
209
208
|
getCurrentUserId(): string | null;
|
|
210
209
|
hasValidToken(): boolean;
|
|
211
210
|
getAccessToken(): string | null;
|
|
212
|
-
establishDeviceRefreshSlot(): Promise<number | null>;
|
|
213
211
|
getAccessTokenExpiry(): number | null;
|
|
214
212
|
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
215
213
|
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|