@oxyhq/core 5.5.0 → 6.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 +6 -3
- 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 +47 -44
- package/dist/cjs/mixins/OxyServices.accounts.js +6 -13
- package/dist/cjs/mixins/OxyServices.auth.js +66 -201
- package/dist/cjs/mixins/OxyServices.authorizedApps.js +38 -0
- package/dist/cjs/mixins/OxyServices.deviceBoot.js +119 -0
- package/dist/cjs/mixins/index.js +13 -17
- 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/utils/accountUtils.js +1 -55
- package/dist/cjs/utils/authWebUrl.js +6 -15
- package/dist/cjs/utils/fapiAutoDetect.js +16 -64
- package/dist/cjs/utils/platform.js +19 -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 +6 -3
- 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 +28 -18
- package/dist/esm/mixins/OxyServices.accounts.js +6 -13
- package/dist/esm/mixins/OxyServices.auth.js +66 -201
- package/dist/esm/mixins/OxyServices.authorizedApps.js +35 -0
- package/dist/esm/mixins/OxyServices.deviceBoot.js +116 -0
- package/dist/esm/mixins/index.js +13 -17
- 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/utils/accountUtils.js +0 -53
- package/dist/esm/utils/authWebUrl.js +6 -14
- package/dist/esm/utils/fapiAutoDetect.js +16 -63
- package/dist/esm/utils/platform.js +18 -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 +13 -0
- 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 +15 -21
- package/dist/types/mixins/OxyServices.accounts.d.ts +0 -2
- 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.redirect.d.ts → OxyServices.authorizedApps.d.ts} +35 -33
- 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 +6 -9
- package/dist/types/models/interfaces.d.ts +0 -67
- package/dist/types/session/SessionClient.d.ts +25 -0
- package/dist/types/session/authStateStore.d.ts +119 -0
- package/dist/types/session/refresh.d.ts +93 -0
- package/dist/types/utils/accountUtils.d.ts +0 -14
- package/dist/types/utils/authWebUrl.d.ts +6 -12
- package/dist/types/utils/fapiAutoDetect.d.ts +15 -38
- package/dist/types/utils/platform.d.ts +14 -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 +19 -3
- 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 +74 -65
- package/src/mixins/OxyServices.accounts.ts +6 -13
- package/src/mixins/OxyServices.auth.ts +78 -253
- package/src/mixins/OxyServices.authorizedApps.ts +75 -0
- 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__/authorizedApps.test.ts +63 -0
- package/src/mixins/__tests__/passwordSignIn.test.ts +91 -0
- package/src/mixins/index.ts +16 -22
- package/src/models/interfaces.ts +0 -79
- package/src/session/SessionClient.ts +52 -1
- 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/utils/__tests__/authWebUrl.test.ts +5 -29
- package/src/utils/__tests__/fapiAutoDetect.test.ts +5 -126
- package/src/utils/__tests__/validationUtils.test.ts +30 -0
- package/src/utils/accountUtils.ts +0 -62
- package/src/utils/authWebUrl.ts +6 -15
- package/src/utils/fapiAutoDetect.ts +16 -60
- package/src/utils/platform.ts +21 -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/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/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.silent.d.ts +0 -132
- package/dist/types/mixins/OxyServices.sso.d.ts +0 -138
- 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__/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/ssoEstablish.ts +0 -174
- package/src/utils/ssoReturn.ts +0 -389
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AuthManager — public types for the multi-account cookie path.
|
|
3
|
-
*
|
|
4
|
-
* Lives in its own module (rather than the 670-line `models/interfaces.ts`)
|
|
5
|
-
* so consumers can `import type` exactly the multi-account surface without
|
|
6
|
-
* pulling in the full interfaces graph, and so `AuthManager.ts` stays
|
|
7
|
-
* decoupled from the wire shapes — these types re-state the wire as the
|
|
8
|
-
* AuthManager's in-memory representation.
|
|
9
|
-
*
|
|
10
|
-
* @module core/AuthManagerTypes
|
|
11
|
-
*/
|
|
12
|
-
import type { RefreshAllAccountUser } from './models/interfaces';
|
|
13
|
-
/**
|
|
14
|
-
* One device-local account known to `AuthManager` in the cookie path.
|
|
15
|
-
*
|
|
16
|
-
* Built from a `POST /auth/refresh-all` entry, OR from a single
|
|
17
|
-
* `POST /auth/refresh?authuser=N` rotation after a switch, OR from a
|
|
18
|
-
* `handleAuthSuccess` call after a fresh login. The `accessToken` is held in
|
|
19
|
-
* memory only — the refresh token never enters JS (it lives in the httpOnly
|
|
20
|
-
* `oxy_rt_${authuser}` cookie).
|
|
21
|
-
*/
|
|
22
|
-
export interface AuthManagerAccount {
|
|
23
|
-
/** Device-local cookie slot index (0..N-1). */
|
|
24
|
-
authuser: number;
|
|
25
|
-
/** Server-side session id this slot is bound to. */
|
|
26
|
-
sessionId: string;
|
|
27
|
-
/**
|
|
28
|
-
* Projected user shape from the wire (username/avatar/color/email).
|
|
29
|
-
*
|
|
30
|
-
* `null` when a refresh-via-cookie planted a fresh access token for a slot
|
|
31
|
-
* that the AuthManager has no prior in-memory user metadata for. Callers (or
|
|
32
|
-
* the AuthManager itself) are expected to hydrate the user shape via
|
|
33
|
-
* `getCurrentUser()` after the token is planted; the chooser UI must render
|
|
34
|
-
* the public-key fallback handle until the hydration completes.
|
|
35
|
-
*/
|
|
36
|
-
user: RefreshAllAccountUser | null;
|
|
37
|
-
/** Currently-valid access token for this slot (in-memory only). */
|
|
38
|
-
accessToken: string;
|
|
39
|
-
/** ISO-8601 expiry of the access token. */
|
|
40
|
-
expiresAt: string;
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Outcome of `AuthManager.restoreFromCookies()`.
|
|
44
|
-
*
|
|
45
|
-
* `accounts` is sorted by `authuser` ascending (matching the server's
|
|
46
|
-
* canonical ordering). `activeAuthuser` is whichever slot the AuthManager
|
|
47
|
-
* picked as active — usually the persisted `oxy_active_authuser` if it
|
|
48
|
-
* matched a returned slot, otherwise the lowest returned `authuser`, or
|
|
49
|
-
* `null` if no accounts were restored.
|
|
50
|
-
*/
|
|
51
|
-
export interface RestoreFromCookiesResult {
|
|
52
|
-
accounts: AuthManagerAccount[];
|
|
53
|
-
activeAuthuser: number | null;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Options for `AuthManager.restoreFromCookies()` / `AuthManager.initialize()`.
|
|
57
|
-
*/
|
|
58
|
-
export interface RestoreFromCookiesOptions {
|
|
59
|
-
/**
|
|
60
|
-
* Abort the underlying `POST /auth/refresh-all` after this many milliseconds
|
|
61
|
-
* and treat it as "no signed-in accounts" instead of hanging. Forwarded
|
|
62
|
-
* verbatim to `OxyServices.refreshAllSessions({ timeout })`.
|
|
63
|
-
*
|
|
64
|
-
* Intended for the cold-boot cookie-restore step on a cross-domain RP, where
|
|
65
|
-
* the `Domain=oxy.so` refresh cookie never reaches `api.<apex>` and the
|
|
66
|
-
* request can stall with no useful answer. Omit (the default) to wait
|
|
67
|
-
* indefinitely — the warm cross-tab cascade path passes nothing, preserving
|
|
68
|
-
* its existing behaviour.
|
|
69
|
-
*/
|
|
70
|
-
timeout?: number;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Outcome of `AuthManager.switchAuthuser()`.
|
|
74
|
-
*
|
|
75
|
-
* Mirrors the wire `RefreshCookieResponse`.
|
|
76
|
-
*/
|
|
77
|
-
export interface SwitchAuthuserResult {
|
|
78
|
-
accessToken: string;
|
|
79
|
-
expiresAt: string;
|
|
80
|
-
authuser: number;
|
|
81
|
-
}
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-Domain Authentication Helper
|
|
3
|
-
*
|
|
4
|
-
* Provides a simplified API for cross-domain SSO authentication. The
|
|
5
|
-
* automatic sign-in path uses a full-page redirect through the central IdP
|
|
6
|
-
* (`auth.oxy.so`) — a tokenless, universal mechanism that works in every
|
|
7
|
-
* browser.
|
|
8
|
-
*
|
|
9
|
-
* FedCM (`signInWithFedCM`) is intentionally NOT part of the automatic
|
|
10
|
-
* (`'auto'`) path: it is a Chrome-only browser API, and a misconfigured or
|
|
11
|
-
* unreachable FedCM endpoint fails fast and silently, which — combined with a
|
|
12
|
-
* caller's auth-guard effect re-invoking `signIn()` whenever the user is still
|
|
13
|
-
* unauthenticated — produced a real production incident (an accelerating
|
|
14
|
-
* `autoSignIn` → FedCM-fails → redirect retry loop). `signInWithFedCM` remains
|
|
15
|
-
* available for callers that want to opt into it EXPLICITLY
|
|
16
|
-
* (`signIn({ method: 'fedcm' })`).
|
|
17
|
-
*
|
|
18
|
-
* Usage:
|
|
19
|
-
* ```typescript
|
|
20
|
-
* import { CrossDomainAuth } from '@oxyhq/core';
|
|
21
|
-
*
|
|
22
|
-
* const auth = new CrossDomainAuth(oxyServices);
|
|
23
|
-
*
|
|
24
|
-
* // Automatic method selection (always redirect)
|
|
25
|
-
* const session = await auth.signIn();
|
|
26
|
-
*
|
|
27
|
-
* // Or use a specific method
|
|
28
|
-
* auth.signInWithRedirect();
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
import type { OxyServices } from './OxyServices';
|
|
32
|
-
import type { SessionLoginResponse } from './models/session';
|
|
33
|
-
export interface CrossDomainAuthOptions {
|
|
34
|
-
/**
|
|
35
|
-
* Preferred authentication method
|
|
36
|
-
* - 'auto': Automatically select best method (default)
|
|
37
|
-
* - 'fedcm': Use FedCM (browser-native)
|
|
38
|
-
* - 'redirect': Use full-page redirect
|
|
39
|
-
*/
|
|
40
|
-
method?: 'auto' | 'fedcm' | 'redirect';
|
|
41
|
-
/**
|
|
42
|
-
* Custom redirect URI (for redirect method)
|
|
43
|
-
*/
|
|
44
|
-
redirectUri?: string;
|
|
45
|
-
/**
|
|
46
|
-
* Whether to open signup page instead of login
|
|
47
|
-
*/
|
|
48
|
-
isSignup?: boolean;
|
|
49
|
-
/**
|
|
50
|
-
* Callback when auth method is selected
|
|
51
|
-
*/
|
|
52
|
-
onMethodSelected?: (method: 'fedcm' | 'redirect') => void;
|
|
53
|
-
}
|
|
54
|
-
export declare class CrossDomainAuth {
|
|
55
|
-
private oxyServices;
|
|
56
|
-
constructor(oxyServices: OxyServices);
|
|
57
|
-
/**
|
|
58
|
-
* Sign in with automatic method selection.
|
|
59
|
-
*
|
|
60
|
-
* Auto mode always uses the full-page redirect (see the class doc comment
|
|
61
|
-
* for why FedCM was removed from this path). Pass `{ method: 'fedcm' }` to
|
|
62
|
-
* opt into FedCM explicitly.
|
|
63
|
-
*
|
|
64
|
-
* @param options - Authentication options
|
|
65
|
-
* @returns Session with user data and access token
|
|
66
|
-
*/
|
|
67
|
-
signIn(options?: CrossDomainAuthOptions): Promise<SessionLoginResponse | null>;
|
|
68
|
-
/**
|
|
69
|
-
* Automatic sign-in.
|
|
70
|
-
*
|
|
71
|
-
* Goes straight to the full-page redirect — the sole automatic method.
|
|
72
|
-
* FedCM is deliberately NOT attempted here (see the class doc comment):
|
|
73
|
-
* it is Chrome-only, and its fast/silent failure mode combined with a
|
|
74
|
-
* caller's auth-guard effect re-invoking `signIn()` produced a real
|
|
75
|
-
* production sign-in loop. Use `signIn({ method: 'fedcm' })` to opt in
|
|
76
|
-
* explicitly.
|
|
77
|
-
*
|
|
78
|
-
* @private
|
|
79
|
-
*/
|
|
80
|
-
private autoSignIn;
|
|
81
|
-
/**
|
|
82
|
-
* Sign in using FedCM (Federated Credential Management)
|
|
83
|
-
*
|
|
84
|
-
* Best method - browser-native, Google-like experience
|
|
85
|
-
*/
|
|
86
|
-
signInWithFedCM(options?: CrossDomainAuthOptions): Promise<SessionLoginResponse>;
|
|
87
|
-
/**
|
|
88
|
-
* Sign in using full-page redirect
|
|
89
|
-
*
|
|
90
|
-
* Fallback method - works everywhere but loses app state
|
|
91
|
-
*/
|
|
92
|
-
signInWithRedirect(options?: CrossDomainAuthOptions): void;
|
|
93
|
-
/**
|
|
94
|
-
* Handle redirect callback
|
|
95
|
-
*
|
|
96
|
-
* Call this on app startup to check if we're returning from auth redirect
|
|
97
|
-
*/
|
|
98
|
-
handleRedirectCallback(): SessionLoginResponse | null;
|
|
99
|
-
/**
|
|
100
|
-
* Silent sign-in (check for existing session)
|
|
101
|
-
*
|
|
102
|
-
* Tries to automatically sign in without user interaction, via the
|
|
103
|
-
* iframe-based silent auth against the per-apex `/auth/silent` IdP host.
|
|
104
|
-
* FedCM is deliberately NOT attempted here (see the class doc comment).
|
|
105
|
-
*
|
|
106
|
-
* @returns Session if user is already signed in, null otherwise
|
|
107
|
-
*/
|
|
108
|
-
silentSignIn(): Promise<SessionLoginResponse | null>;
|
|
109
|
-
/**
|
|
110
|
-
* Restore session from storage.
|
|
111
|
-
*
|
|
112
|
-
* Access tokens are no longer persisted in browser storage; providers restore
|
|
113
|
-
* through refresh cookies / SSO code exchange instead.
|
|
114
|
-
*/
|
|
115
|
-
restoreSession(): boolean;
|
|
116
|
-
/**
|
|
117
|
-
* Check if FedCM is supported in current browser
|
|
118
|
-
*/
|
|
119
|
-
isFedCMSupported(): boolean;
|
|
120
|
-
/**
|
|
121
|
-
* Get recommended authentication method for current environment
|
|
122
|
-
*
|
|
123
|
-
* Redirect is the sole recommended automatic method — it works in every
|
|
124
|
-
* browser, unlike FedCM (Chrome-only). Callers that want FedCM must opt in
|
|
125
|
-
* explicitly via `signIn({ method: 'fedcm' })`.
|
|
126
|
-
*
|
|
127
|
-
* @returns Recommended method name and reason
|
|
128
|
-
*/
|
|
129
|
-
getRecommendedMethod(): {
|
|
130
|
-
method: 'redirect';
|
|
131
|
-
reason: string;
|
|
132
|
-
};
|
|
133
|
-
/**
|
|
134
|
-
* Initialize cross-domain auth on app startup
|
|
135
|
-
*
|
|
136
|
-
* This handles:
|
|
137
|
-
* 1. Redirect callback (if returning from auth.oxy.so)
|
|
138
|
-
* 2. Silent sign-in (check for existing SSO session)
|
|
139
|
-
*
|
|
140
|
-
* @returns Session if user is authenticated, null otherwise
|
|
141
|
-
*/
|
|
142
|
-
initialize(): Promise<SessionLoginResponse | null>;
|
|
143
|
-
}
|
|
144
|
-
/**
|
|
145
|
-
* Helper function to create CrossDomainAuth instance
|
|
146
|
-
*
|
|
147
|
-
* @example
|
|
148
|
-
* ```typescript
|
|
149
|
-
* import { createCrossDomainAuth } from '@oxyhq/core';
|
|
150
|
-
*
|
|
151
|
-
* const oxyServices = new OxyServices({ baseURL: 'https://api.oxy.so' });
|
|
152
|
-
* const auth = createCrossDomainAuth(oxyServices);
|
|
153
|
-
*
|
|
154
|
-
* // On app startup
|
|
155
|
-
* const session = await auth.initialize();
|
|
156
|
-
* if (session) {
|
|
157
|
-
* console.log('User is signed in:', session.user);
|
|
158
|
-
* }
|
|
159
|
-
*
|
|
160
|
-
* // Sign in button click
|
|
161
|
-
* const session = await auth.signIn();
|
|
162
|
-
* ```
|
|
163
|
-
*/
|
|
164
|
-
export declare function createCrossDomainAuth(oxyServices: OxyServices): CrossDomainAuth;
|
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
import type { OxyServicesBase } from '../OxyServices.base';
|
|
2
|
-
import type { SessionLoginResponse } from '../models/session';
|
|
3
|
-
export interface FedCMAuthOptions {
|
|
4
|
-
nonce?: string;
|
|
5
|
-
context?: 'signin' | 'signup' | 'continue' | 'use';
|
|
6
|
-
loginHint?: string;
|
|
7
|
-
}
|
|
8
|
-
export interface FedCMConfig {
|
|
9
|
-
enabled: boolean;
|
|
10
|
-
configURL: string;
|
|
11
|
-
clientId?: string;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* FedCM request mode values.
|
|
15
|
-
*
|
|
16
|
-
* The W3C FedCM spec renamed the `IdentityCredentialRequestOptions.mode` enum:
|
|
17
|
-
* `'widget'` → `'passive'` and `'button'` → `'active'`. Modern Chrome only
|
|
18
|
-
* accepts `'active'`/`'passive'` and throws a synchronous `TypeError` for the
|
|
19
|
-
* legacy values, while Chrome 125–131 only understands `'button'`/`'widget'`.
|
|
20
|
-
* Callers should use the modern values; the legacy values are accepted for
|
|
21
|
-
* convenience and normalised internally.
|
|
22
|
-
*/
|
|
23
|
-
export type FedCMRequestMode = 'active' | 'passive' | 'button' | 'widget';
|
|
24
|
-
/**
|
|
25
|
-
* Normalised result of a FedCM credential request: the IdP-issued ID token plus
|
|
26
|
-
* whether the browser auto-selected the account (no explicit user choice).
|
|
27
|
-
*/
|
|
28
|
-
interface FedCMTokenResult {
|
|
29
|
-
token: string;
|
|
30
|
-
isAutoSelected: boolean;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Federated Credential Management (FedCM) Authentication Mixin
|
|
34
|
-
*
|
|
35
|
-
* Implements the modern browser-native identity federation API that enables
|
|
36
|
-
* Google-style cross-domain authentication without third-party cookies.
|
|
37
|
-
*
|
|
38
|
-
* Browser Support:
|
|
39
|
-
* - Chrome 108+
|
|
40
|
-
* - Safari 16.4+
|
|
41
|
-
* - Edge 108+
|
|
42
|
-
* - Firefox: Not yet supported (fallback required)
|
|
43
|
-
*
|
|
44
|
-
* Key Features:
|
|
45
|
-
* - No redirects or secondary windows required
|
|
46
|
-
* - Browser-native UI prompts
|
|
47
|
-
* - Privacy-preserving (IdP can't track users)
|
|
48
|
-
* - Automatic SSO across domains
|
|
49
|
-
* - Silent re-authentication support
|
|
50
|
-
*
|
|
51
|
-
* @see https://developer.mozilla.org/en-US/docs/Web/API/FedCM_API
|
|
52
|
-
*/
|
|
53
|
-
export declare function OxyServicesFedCMMixin<T extends typeof OxyServicesBase>(Base: T): {
|
|
54
|
-
new (...args: any[]): {
|
|
55
|
-
resolveFedcmConfigUrl(): string;
|
|
56
|
-
/**
|
|
57
|
-
* Instance method to check FedCM support
|
|
58
|
-
*/
|
|
59
|
-
isFedCMSupported(): boolean;
|
|
60
|
-
/**
|
|
61
|
-
* Sign in using FedCM (Federated Credential Management API)
|
|
62
|
-
*
|
|
63
|
-
* This provides a Google-style authentication experience:
|
|
64
|
-
* - Browser shows native "Sign in with Oxy" prompt
|
|
65
|
-
* - No redirect or secondary window required
|
|
66
|
-
* - User approves → credential exchange happens in browser
|
|
67
|
-
* - All apps automatically get SSO after first sign-in
|
|
68
|
-
*
|
|
69
|
-
* @param options - Authentication options
|
|
70
|
-
* @returns Session with access token and user data
|
|
71
|
-
* @throws {OxyAuthenticationError} If FedCM not supported or user cancels
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```typescript
|
|
75
|
-
* try {
|
|
76
|
-
* const session = await oxyServices.signInWithFedCM();
|
|
77
|
-
* const user = session.user;
|
|
78
|
-
* } catch (error) {
|
|
79
|
-
* // Fallback to redirect auth
|
|
80
|
-
* oxyServices.signInWithRedirect();
|
|
81
|
-
* }
|
|
82
|
-
* ```
|
|
83
|
-
*/
|
|
84
|
-
signInWithFedCM(options?: FedCMAuthOptions): Promise<SessionLoginResponse>;
|
|
85
|
-
/**
|
|
86
|
-
* Run a single interactive FedCM credential request + token exchange for the
|
|
87
|
-
* given (possibly undefined) loginHint. A successful exchange plants the
|
|
88
|
-
* access token and persists the user id as the future loginHint — the hint is
|
|
89
|
-
* therefore only ever stored after a GENUINELY successful sign-in, never
|
|
90
|
-
* speculatively.
|
|
91
|
-
*
|
|
92
|
-
* @private
|
|
93
|
-
*/
|
|
94
|
-
attemptInteractiveSignIn(options: FedCMAuthOptions, loginHint: string | undefined): Promise<SessionLoginResponse>;
|
|
95
|
-
/**
|
|
96
|
-
* Map a raw FedCM/exchange failure to a user-facing {@link OxyAuthenticationError}
|
|
97
|
-
* (or pass it through). Extracted so the clear-and-retry path can reuse the
|
|
98
|
-
* exact same error normalisation as the first attempt.
|
|
99
|
-
*
|
|
100
|
-
* @private
|
|
101
|
-
*/
|
|
102
|
-
normalizeInteractiveSignInError(error: unknown): unknown;
|
|
103
|
-
/**
|
|
104
|
-
* Silent sign-in using FedCM
|
|
105
|
-
*
|
|
106
|
-
* Attempts to automatically re-authenticate the user without any UI.
|
|
107
|
-
* This is what enables "instant sign-in" across all Oxy domains after
|
|
108
|
-
* the user has signed in once.
|
|
109
|
-
*
|
|
110
|
-
* The browser will:
|
|
111
|
-
* 1. Check if user has previously signed in to Oxy
|
|
112
|
-
* 2. Check if user is still signed in at auth.oxy.so
|
|
113
|
-
* 3. If yes, automatically provide credential without prompting
|
|
114
|
-
*
|
|
115
|
-
* @returns Session if user is already signed in, null otherwise
|
|
116
|
-
*
|
|
117
|
-
* @example
|
|
118
|
-
* ```typescript
|
|
119
|
-
* // On app startup
|
|
120
|
-
* useEffect(() => {
|
|
121
|
-
* const checkAuth = async () => {
|
|
122
|
-
* const session = await oxyServices.silentSignInWithFedCM();
|
|
123
|
-
* if (session) {
|
|
124
|
-
* setUser(session.user);
|
|
125
|
-
* } else {
|
|
126
|
-
* // Show sign-in button
|
|
127
|
-
* }
|
|
128
|
-
* };
|
|
129
|
-
* checkAuth();
|
|
130
|
-
* }, []);
|
|
131
|
-
* ```
|
|
132
|
-
*/
|
|
133
|
-
silentSignInWithFedCM(): Promise<SessionLoginResponse | null>;
|
|
134
|
-
/**
|
|
135
|
-
* Request identity credential from browser using FedCM API
|
|
136
|
-
*
|
|
137
|
-
* Uses a global lock to prevent concurrent requests, as FedCM only
|
|
138
|
-
* allows one navigator.credentials.get request at a time.
|
|
139
|
-
*
|
|
140
|
-
* Interactive requests (optional/required) wait for any silent request to finish first.
|
|
141
|
-
*
|
|
142
|
-
* @private
|
|
143
|
-
*/
|
|
144
|
-
requestIdentityCredential(options: {
|
|
145
|
-
configURL: string;
|
|
146
|
-
clientId: string;
|
|
147
|
-
nonce: string;
|
|
148
|
-
context?: string;
|
|
149
|
-
loginHint?: string;
|
|
150
|
-
mediation?: "silent" | "optional" | "required";
|
|
151
|
-
/**
|
|
152
|
-
* FedCM request mode. The W3C spec values are `'active'` (user-gesture
|
|
153
|
-
* button flow) and `'passive'` (browser-initiated widget flow). Chrome
|
|
154
|
-
* 125–131 used the legacy names `'button'`/`'widget'`; those are accepted
|
|
155
|
-
* here and mapped to the modern values, with an automatic legacy retry if
|
|
156
|
-
* the running browser only understands the old enum.
|
|
157
|
-
*/
|
|
158
|
-
mode?: FedCMRequestMode;
|
|
159
|
-
}): Promise<FedCMTokenResult | null>;
|
|
160
|
-
/**
|
|
161
|
-
* Exchange FedCM ID token for Oxy session
|
|
162
|
-
*
|
|
163
|
-
* The ID token is a JWT issued by auth.oxy.so that proves the user's
|
|
164
|
-
* identity. We exchange it for a full Oxy session with access token.
|
|
165
|
-
*
|
|
166
|
-
* @private
|
|
167
|
-
*/
|
|
168
|
-
exchangeIdTokenForSession(idToken: string): Promise<SessionLoginResponse>;
|
|
169
|
-
/**
|
|
170
|
-
* Revoke FedCM credential (sign out)
|
|
171
|
-
*
|
|
172
|
-
* Uses IdentityCredential.disconnect() to tell the browser to forget
|
|
173
|
-
* the RP-IdP-account association. This resets the "returning account"
|
|
174
|
-
* state, which is required for silent mediation to work again.
|
|
175
|
-
*/
|
|
176
|
-
revokeFedCMCredential(): Promise<void>;
|
|
177
|
-
/**
|
|
178
|
-
* Get configuration for FedCM
|
|
179
|
-
*
|
|
180
|
-
* @returns FedCM configuration with browser support info
|
|
181
|
-
*/
|
|
182
|
-
getFedCMConfig(): FedCMConfig;
|
|
183
|
-
/**
|
|
184
|
-
* Generate a cryptographically secure local nonce for FedCM.
|
|
185
|
-
*
|
|
186
|
-
* NOTE: this is a *local* fallback only. The server-side `/fedcm/exchange`
|
|
187
|
-
* endpoint requires the nonce embedded in the ID token to have been minted
|
|
188
|
-
* by `POST /fedcm/nonce` (see {@link mintServerNonce}) and bound to this
|
|
189
|
-
* origin. A purely local nonce will be rejected with `invalid_nonce`. Use
|
|
190
|
-
* {@link getFedcmNonce}, which prefers a server-minted nonce and only falls
|
|
191
|
-
* back to this generator when the mint endpoint is unreachable.
|
|
192
|
-
*
|
|
193
|
-
* @private
|
|
194
|
-
*/
|
|
195
|
-
generateNonce(): string;
|
|
196
|
-
/**
|
|
197
|
-
* Mint a single-use, origin-bound nonce from the Oxy API.
|
|
198
|
-
*
|
|
199
|
-
* The FedCM ID token issued by the IdP embeds this nonce as the `nonce`
|
|
200
|
-
* claim. When the consuming app calls `POST /fedcm/exchange`, the API burns
|
|
201
|
-
* the nonce (atomic `usedAt` transition) and verifies it was minted for the
|
|
202
|
-
* same origin as the token `aud`. This is the anti-replay binding required
|
|
203
|
-
* by the API's H9 hardening — without a server-minted nonce the exchange
|
|
204
|
-
* always fails.
|
|
205
|
-
*
|
|
206
|
-
* The browser attaches the `Origin` header automatically on this
|
|
207
|
-
* cross-origin request, so the API binds the nonce to the calling app's
|
|
208
|
-
* origin (which also becomes the FedCM `clientId`/token `aud`).
|
|
209
|
-
*
|
|
210
|
-
* @private
|
|
211
|
-
*/
|
|
212
|
-
mintServerNonce(): Promise<string>;
|
|
213
|
-
/**
|
|
214
|
-
* Resolve the nonce to use for a FedCM credential request.
|
|
215
|
-
*
|
|
216
|
-
* Prefers a server-minted, origin-bound nonce (required for the token
|
|
217
|
-
* exchange to succeed). If the mint endpoint is unreachable we fall back to
|
|
218
|
-
* a locally generated nonce so the browser flow can still proceed; the
|
|
219
|
-
* exchange may then fail server-side, but that is strictly better than
|
|
220
|
-
* throwing before the browser ever shows its UI.
|
|
221
|
-
*
|
|
222
|
-
* @private
|
|
223
|
-
*/
|
|
224
|
-
getFedcmNonce(): Promise<string>;
|
|
225
|
-
/**
|
|
226
|
-
* Get the client ID for this origin
|
|
227
|
-
*
|
|
228
|
-
* @private
|
|
229
|
-
*/
|
|
230
|
-
getClientId(): string;
|
|
231
|
-
/** @internal */
|
|
232
|
-
getStoredLoginHint(): string | undefined;
|
|
233
|
-
/** @internal */
|
|
234
|
-
storeLoginHint(userId: string): void;
|
|
235
|
-
/** @internal */
|
|
236
|
-
clearLoginHint(): void;
|
|
237
|
-
/**
|
|
238
|
-
* List the authenticated user's authorized RP apps.
|
|
239
|
-
*
|
|
240
|
-
* Returns the intersection of the user's FedCM grants and the currently-
|
|
241
|
-
* approved RP catalog — what powers the "Connected apps" management UI in
|
|
242
|
-
* @oxyhq/services. Requires a real user session; service tokens are
|
|
243
|
-
* rejected by the underlying endpoint.
|
|
244
|
-
*/
|
|
245
|
-
listAuthorizedApps(): Promise<AuthorizedApp[]>;
|
|
246
|
-
/**
|
|
247
|
-
* Revoke the authenticated user's authorization for a specific RP origin.
|
|
248
|
-
*
|
|
249
|
-
* The next FedCM sign-in from that origin will require explicit re-consent.
|
|
250
|
-
* The corresponding cache entry is invalidated so a subsequent
|
|
251
|
-
* `listAuthorizedApps()` call sees fresh data.
|
|
252
|
-
*/
|
|
253
|
-
revokeAuthorizedApp(origin: string): Promise<void>;
|
|
254
|
-
httpService: import("../HttpService").HttpService;
|
|
255
|
-
cloudURL: string;
|
|
256
|
-
config: import("../OxyServices.base").OxyConfig;
|
|
257
|
-
__resetTokensForTests(): void;
|
|
258
|
-
makeRequest<T_1>(method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", url: string, data?: any, options?: import("../HttpService").RequestOptions): Promise<T_1>;
|
|
259
|
-
getBaseURL(): string;
|
|
260
|
-
getSessionBaseUrl(): string;
|
|
261
|
-
getClient(): import("../HttpService").HttpService;
|
|
262
|
-
createLinkedClient(config: import("../OxyServices.base").OxyConfig): import("..").LinkedHttpClient;
|
|
263
|
-
getMetrics(): {
|
|
264
|
-
totalRequests: number;
|
|
265
|
-
successfulRequests: number;
|
|
266
|
-
failedRequests: number;
|
|
267
|
-
cacheHits: number;
|
|
268
|
-
cacheMisses: number;
|
|
269
|
-
averageResponseTime: number;
|
|
270
|
-
};
|
|
271
|
-
clearCache(): void;
|
|
272
|
-
clearCacheEntry(key: string): void;
|
|
273
|
-
clearCacheByPrefix(prefix: string): number;
|
|
274
|
-
getCacheStats(): {
|
|
275
|
-
size: number;
|
|
276
|
-
hits: number;
|
|
277
|
-
misses: number;
|
|
278
|
-
hitRate: number;
|
|
279
|
-
};
|
|
280
|
-
getCloudURL(): string;
|
|
281
|
-
setTokens(accessToken: string): void;
|
|
282
|
-
clearTokens(): void;
|
|
283
|
-
onTokensChanged(listener: (accessToken: string | null) => void): () => void;
|
|
284
|
-
_cachedUserId: string | null | undefined;
|
|
285
|
-
_cachedAccessToken: string | null;
|
|
286
|
-
getCurrentUserId(): string | null;
|
|
287
|
-
hasValidToken(): boolean;
|
|
288
|
-
getAccessToken(): string | null;
|
|
289
|
-
establishDeviceRefreshSlot(): Promise<number | null>;
|
|
290
|
-
getAccessTokenExpiry(): number | null;
|
|
291
|
-
waitForAuth(timeoutMs?: number): Promise<boolean>;
|
|
292
|
-
withAuthRetry<T_1>(operation: () => Promise<T_1>, operationName: string, options?: {
|
|
293
|
-
maxRetries?: number;
|
|
294
|
-
retryDelay?: number;
|
|
295
|
-
authTimeoutMs?: number;
|
|
296
|
-
}): Promise<T_1>;
|
|
297
|
-
validate(): Promise<boolean>;
|
|
298
|
-
handleError(error: unknown): Error;
|
|
299
|
-
healthCheck(): Promise<{
|
|
300
|
-
status: string;
|
|
301
|
-
users?: number;
|
|
302
|
-
timestamp?: string;
|
|
303
|
-
[key: string]: any;
|
|
304
|
-
}>;
|
|
305
|
-
};
|
|
306
|
-
readonly DEFAULT_CONFIG_URL: "https://auth.oxy.so/fedcm.json";
|
|
307
|
-
readonly FEDCM_TIMEOUT: 15000;
|
|
308
|
-
readonly FEDCM_SILENT_TIMEOUT: 4000;
|
|
309
|
-
readonly FEDCM_ABORT_SETTLE_GRACE_MS: 500;
|
|
310
|
-
/**
|
|
311
|
-
* Check if FedCM is supported in the current browser
|
|
312
|
-
*/
|
|
313
|
-
isFedCMSupported(): boolean;
|
|
314
|
-
} & T;
|
|
315
|
-
/**
|
|
316
|
-
* Public summary of an RP application the user has authorized — mirrors the
|
|
317
|
-
* `AuthorizedAppSummary` shape returned by `GET /fedcm/me/authorized-apps`.
|
|
318
|
-
*/
|
|
319
|
-
export interface AuthorizedApp {
|
|
320
|
-
/** Normalised RP origin. */
|
|
321
|
-
origin: string;
|
|
322
|
-
/** Friendly display name. */
|
|
323
|
-
name: string;
|
|
324
|
-
/** Optional human-readable description. */
|
|
325
|
-
description?: string;
|
|
326
|
-
/** ISO-8601 timestamp of when the user first authorized this RP. */
|
|
327
|
-
firstGrantedAt: string;
|
|
328
|
-
/** ISO-8601 timestamp of the most recent FedCM exchange for this user+RP. */
|
|
329
|
-
lastUsedAt: string;
|
|
330
|
-
}
|
|
331
|
-
export { OxyServicesFedCMMixin as FedCMMixin };
|