@nuvlore/extension-access-okta-slack 0.1.1 → 0.1.2

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.
Files changed (75) hide show
  1. package/package.json +4 -19
  2. package/vendor/extension-sso/LICENSE +0 -202
  3. package/vendor/extension-sso/README.md +0 -35
  4. package/vendor/extension-sso/commands/okta-login.md +0 -10
  5. package/vendor/extension-sso/package.json +0 -53
  6. package/vendor/extension-sso/skills/workday-okta-auth/SKILL.md +0 -20
  7. package/vendor/extension-sso/src/autoAuth.mjs +0 -25
  8. package/vendor/extension-sso/src/browserLogin.mjs +0 -1
  9. package/vendor/extension-sso/src/chromeCookies.mjs +0 -1
  10. package/vendor/extension-sso/src/cookieJar.mjs +0 -1
  11. package/vendor/extension-sso/src/extensionAccess.mjs +0 -173
  12. package/vendor/extension-sso/src/htmlSessionExtract.mjs +0 -1
  13. package/vendor/extension-sso/src/oktaAppAccess.mjs +0 -133
  14. package/vendor/extension-sso/src/oktaAppCatalog.mjs +0 -118
  15. package/vendor/extension-sso/src/oktaAppRead.mjs +0 -119
  16. package/vendor/extension-sso/src/oktaConfig.mjs +0 -12
  17. package/vendor/extension-sso/src/oktaSession.mjs +0 -32
  18. package/vendor/extension-sso/src/serviceOperations.mjs +0 -407
  19. package/vendor/extension-sso/src/serviceReadSearch.mjs +0 -395
  20. package/vendor/extension-sso/src/serviceReads.mjs +0 -109
  21. package/vendor/extension-sso/src/serviceRegistry.mjs +0 -497
  22. package/vendor/extension-sso/src/sessionAuth.mjs +0 -339
  23. package/vendor/extension-sso/src/sessionManager.mjs +0 -212
  24. package/vendor/extension-sso/src/sessionValidate.mjs +0 -74
  25. package/vendor/extension-sso/src/ssoConfig.mjs +0 -31
  26. package/vendor/extension-sso/src/ssoHttpRead.mjs +0 -292
  27. package/vendor/extension-sso/tools/extension-access-tools.shared.mjs +0 -16
  28. package/vendor/extension-sso/tools/okta-app-tools.shared.mjs +0 -5
  29. package/vendor/extension-sso/tools/okta-tools.shared.mjs +0 -18
  30. package/vendor/extension-sso/tools/workday_extension_read.mjs +0 -51
  31. package/vendor/extension-sso/tools/workday_extension_read_access.mjs +0 -65
  32. package/vendor/extension-sso/tools/workday_list_extension_access.mjs +0 -39
  33. package/vendor/extension-sso/tools/workday_list_okta_apps.mjs +0 -18
  34. package/vendor/extension-sso/tools/workday_list_service_operations.mjs +0 -41
  35. package/vendor/extension-sso/tools/workday_list_service_read_search_capabilities.mjs +0 -34
  36. package/vendor/extension-sso/tools/workday_list_services.mjs +0 -31
  37. package/vendor/extension-sso/tools/workday_okta_app_probe_all.mjs +0 -24
  38. package/vendor/extension-sso/tools/workday_okta_app_read.mjs +0 -30
  39. package/vendor/extension-sso/tools/workday_okta_app_read_access.mjs +0 -25
  40. package/vendor/extension-sso/tools/workday_okta_auth_header.mjs +0 -58
  41. package/vendor/extension-sso/tools/workday_okta_login.mjs +0 -65
  42. package/vendor/extension-sso/tools/workday_okta_open_app.mjs +0 -63
  43. package/vendor/extension-sso/tools/workday_okta_open_service.mjs +0 -63
  44. package/vendor/extension-sso/tools/workday_okta_status.mjs +0 -35
  45. package/vendor/extension-sso/tools/workday_service_auth.mjs +0 -65
  46. package/vendor/extension-sso/tools/workday_service_operation_read.mjs +0 -51
  47. package/vendor/extension-sso/tools/workday_service_read.mjs +0 -56
  48. package/vendor/extension-sso/tools/workday_service_search.mjs +0 -62
  49. package/vendor/extension-sso/tools/workday_sso_cookie_header.mjs +0 -59
  50. package/vendor/extension-sso/vendor/extension-browser-sso/LICENSE +0 -202
  51. package/vendor/extension-sso/vendor/extension-browser-sso/README.md +0 -16
  52. package/vendor/extension-sso/vendor/extension-browser-sso/package.json +0 -47
  53. package/vendor/extension-sso/vendor/extension-browser-sso/src/autoAuth.mjs +0 -47
  54. package/vendor/extension-sso/vendor/extension-browser-sso/src/browserHttpRead.mjs +0 -76
  55. package/vendor/extension-sso/vendor/extension-browser-sso/src/browserLogin.mjs +0 -24
  56. package/vendor/extension-sso/vendor/extension-browser-sso/src/chromeCookies.mjs +0 -192
  57. package/vendor/extension-sso/vendor/extension-browser-sso/src/cookieJar.mjs +0 -132
  58. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/devops-data-paths.mjs +0 -222
  59. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/devops-diagnostics.mjs +0 -440
  60. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/enterprise-api-read.mjs +0 -180
  61. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/read-only-command-pack.mjs +0 -1
  62. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/read-only-plan.mjs +0 -45
  63. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/read-only-shell-policy.d.mts +0 -26
  64. package/vendor/extension-sso/vendor/extension-browser-sso/src/extensions/toolkit/read-only-shell-policy.mjs +0 -170
  65. package/vendor/extension-sso/vendor/extension-browser-sso/src/htmlSessionExtract.mjs +0 -64
  66. package/vendor/extension-sso/vendor/extension-read-only-toolkit/LICENSE +0 -202
  67. package/vendor/extension-sso/vendor/extension-read-only-toolkit/README.md +0 -29
  68. package/vendor/extension-sso/vendor/extension-read-only-toolkit/package.json +0 -43
  69. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/devops-data-paths.mjs +0 -222
  70. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/devops-diagnostics.mjs +0 -440
  71. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/enterprise-api-read.mjs +0 -180
  72. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/read-only-command-pack.mjs +0 -1
  73. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/read-only-plan.mjs +0 -45
  74. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/read-only-shell-policy.d.mts +0 -26
  75. package/vendor/extension-sso/vendor/extension-read-only-toolkit/src/read-only-shell-policy.mjs +0 -170
@@ -1,339 +0,0 @@
1
- import {
2
- cookiesForHost,
3
- jarSummary,
4
- loadCookieJar,
5
- mergeCookies,
6
- resolveBestCookieHost,
7
- saveCookieJar
8
- } from "./cookieJar.mjs";
9
- import { openBrowser, waitFor } from "./browserLogin.mjs";
10
-
11
- export { openBrowser };
12
- import {
13
- isAutoAuthEnabled,
14
- resolveAutoAuthOptions
15
- } from "./autoAuth.mjs";
16
-
17
- export { isAutoAuthEnabled, resolveAutoAuthOptions };
18
- import {
19
- ensureSsoSession,
20
- importCookiesFromChrome,
21
- syncOktaAppCookies
22
- } from "./sessionManager.mjs";
23
- import { getSsoConfig } from "./ssoConfig.mjs";
24
- import { getServiceDomains, getWorkdayService } from "./serviceRegistry.mjs";
25
- import { getOktaApp } from "./oktaAppCatalog.mjs";
26
- import { validateOktaAppHost, validateServiceHost } from "./sessionValidate.mjs";
27
-
28
- function hasCookiesForDomains(jar, domains) {
29
- if (!domains.length) return true;
30
- return domains.some((domain) => cookiesForHost(jar?.cookies ?? [], domain).length > 0);
31
- }
32
-
33
- async function mergeImportedCookies(config, jar, domains) {
34
- const imported = await importCookiesFromChrome(config, [config.domain, ...domains]);
35
- if (!imported?.cookies?.length) return jar;
36
- const next = {
37
- ...(jar ?? {}),
38
- cookies: mergeCookies(jar?.cookies ?? [], imported.cookies),
39
- source: imported.source ?? "chrome"
40
- };
41
- await saveCookieJar(config.cookieJarPath, next);
42
- return next;
43
- }
44
-
45
- export async function waitForChromeCookies(
46
- config,
47
- domains,
48
- { timeoutMs, pollMs = 2000, onStatus, label } = {}
49
- ) {
50
- const deadline = Date.now() + (timeoutMs ?? config.loginTimeoutMs);
51
- let jar = await loadCookieJar(config.cookieJarPath);
52
- while (Date.now() < deadline) {
53
- onStatus?.({ phase: "waiting_for_app_cookies", label, domains });
54
- jar = await mergeImportedCookies(config, jar, domains);
55
- if (hasCookiesForDomains(jar, domains)) {
56
- return { jar, ready: true };
57
- }
58
- await waitFor(pollMs);
59
- }
60
- return { jar, ready: hasCookiesForDomains(jar, domains) };
61
- }
62
-
63
- async function openAuthPageAndWait(config, { authUrl, domains, label, options }) {
64
- options.onStatus?.({ phase: "opening_auth", label, url: authUrl });
65
- await openBrowser(authUrl, { chromeProfile: config.chromeProfile });
66
- const waited = await waitForChromeCookies(config, domains, {
67
- timeoutMs: options.appAuthTimeoutMs,
68
- onStatus: options.onStatus,
69
- label
70
- });
71
- return { jar: waited.jar, ready: waited.ready, openedBrowser: true };
72
- }
73
-
74
- export function resolveServiceAuthUrl(serviceId) {
75
- const service = getWorkdayService(serviceId);
76
- const domains = getServiceDomains(serviceId);
77
- return service.readAccess?.authUrl || service.readAccess?.defaultBaseUrl || (domains[0] ? `https://${domains[0]}` : getSsoConfig().loginUrl);
78
- }
79
-
80
- export function resolveOktaAppAuthUrl(appName) {
81
- const app = getOktaApp(appName);
82
- if (app.mode === "bookmark" || app.mode === "oidc-app") {
83
- return getSsoConfig().loginUrl;
84
- }
85
- return app.agentsUrl || app.defaultBaseUrl || getSsoConfig().loginUrl;
86
- }
87
-
88
- /** Open Chrome at the Okta app URL so the user can sign in (read-only). */
89
- export async function openOktaAppForAuth(appName, options = {}) {
90
- const config = options.config ?? getSsoConfig();
91
- const app = getOktaApp(appName);
92
- const authUrl = resolveOktaAppAuthUrl(appName);
93
- const domains = app.domains ?? [];
94
- let openedBrowser = false;
95
-
96
- if (app.launchViaUserHome && options.skipUserHome !== true) {
97
- options.onStatus?.({
98
- phase: "opening_okta_userhome",
99
- oktaApp: appName,
100
- url: config.loginUrl,
101
- hint:
102
- appName === "Sana"
103
- ? 'On workday.sana.ai click "Continue with SSO" to finish login'
104
- : `Click "${appName}" on UserHome if SSO does not auto-launch`
105
- });
106
- await openBrowser(config.loginUrl, { chromeProfile: config.chromeProfile });
107
- openedBrowser = true;
108
- if (options.userHomeDelayMs !== 0) {
109
- await waitFor(options.userHomeDelayMs ?? 2500);
110
- }
111
- }
112
-
113
- const result = await openAuthPageAndWait(config, {
114
- authUrl,
115
- domains: domains.length ? domains : [config.domain],
116
- label: appName,
117
- options
118
- });
119
- return { authUrl, userHomeUrl: app.launchViaUserHome ? config.loginUrl : undefined, openedBrowser: openedBrowser || result.openedBrowser, ...result };
120
- }
121
-
122
- /** Open Chrome at the Workday service URL so the user can sign in via Okta (read-only). */
123
- export async function openServiceForAuth(serviceId, options = {}) {
124
- const config = options.config ?? getSsoConfig();
125
- const domains = getServiceDomains(serviceId);
126
- const authUrl = resolveServiceAuthUrl(serviceId);
127
- const result = await openAuthPageAndWait(config, {
128
- authUrl,
129
- domains: domains.length ? domains : [config.domain],
130
- label: serviceId,
131
- options
132
- });
133
- let serviceReady = false;
134
- for (const domain of domains) {
135
- if (await validateServiceHost(result.jar, domain).catch(() => false)) {
136
- serviceReady = true;
137
- break;
138
- }
139
- }
140
- return { authUrl, openedBrowser: true, ...result, ready: serviceReady, serviceReady };
141
- }
142
-
143
- export async function getServiceCookieHeader(serviceId, options = {}) {
144
- const authOptions = resolveAutoAuthOptions(options);
145
- const config = authOptions.config ?? getSsoConfig();
146
- const session = await ensureServiceSession(serviceId, { ...authOptions, config });
147
- const domains = getServiceDomains(serviceId);
148
- const { host, cookie, hasCookies } = resolveBestCookieHost(session.jar, domains);
149
-
150
- if (!host || !session.jar?.cookies?.length || !hasCookies) {
151
- return {
152
- ok: false,
153
- summary: session.summary,
154
- host,
155
- domains,
156
- serviceReady: session.serviceReady,
157
- openedBrowser: session.openedBrowser,
158
- authUrl: session.authUrl,
159
- message: `No cookies for ${serviceId}. Open ${session.authUrl} in Chrome via Okta, then retry.`
160
- };
161
- }
162
-
163
- const ready = session.summary.authenticated && Boolean(cookie) && session.serviceReady;
164
- return {
165
- ok: ready,
166
- summary: session.summary,
167
- host,
168
- cookie,
169
- domains,
170
- serviceReady: session.serviceReady,
171
- openedBrowser: session.openedBrowser,
172
- authUrl: session.authUrl
173
- };
174
- }
175
-
176
- export async function ensureServiceSession(serviceId, options = {}) {
177
- const authOptions = resolveAutoAuthOptions(options);
178
- const config = authOptions.config ?? getSsoConfig();
179
- const { autoAuth, openBrowserOnMissing } = authOptions;
180
- const domains = getServiceDomains(serviceId);
181
- const authUrl = resolveServiceAuthUrl(serviceId);
182
- let openedBrowser = false;
183
-
184
- let { jar, summary, openedBrowser: oktaOpened } = await ensureSsoSession({
185
- config,
186
- serviceId,
187
- openBrowserOnMissing,
188
- forceBrowser: authOptions.forceBrowser === true,
189
- onStatus: authOptions.onStatus
190
- });
191
- summary = summary ?? jarSummary(jar ?? {}, config);
192
- openedBrowser = openedBrowser || oktaOpened;
193
-
194
- jar = await mergeImportedCookies(config, jar, domains);
195
- let hasServiceCookies = hasCookiesForDomains(jar, domains);
196
- let serviceReady = false;
197
- if (summary.authenticated && hasServiceCookies) {
198
- for (const domain of domains) {
199
- if (await validateServiceHost(jar, domain).catch(() => false)) {
200
- serviceReady = true;
201
- break;
202
- }
203
- }
204
- }
205
-
206
- const needsAuth =
207
- openBrowserOnMissing && (!hasServiceCookies || (hasServiceCookies && !serviceReady));
208
-
209
- if (needsAuth) {
210
- authOptions.onStatus?.({ phase: "opening_service_auth", service: serviceId, url: authUrl });
211
- const auth = await openAuthPageAndWait(config, {
212
- authUrl,
213
- domains,
214
- label: serviceId,
215
- options: authOptions
216
- });
217
- jar = auth.jar;
218
- openedBrowser = openedBrowser || auth.openedBrowser;
219
- hasServiceCookies = hasCookiesForDomains(jar, domains);
220
- if (!auth.ready && !hasServiceCookies) {
221
- throw new Error(
222
- `Service ${serviceId} auth timed out. Complete login in Chrome at ${authUrl}, then retry.`
223
- );
224
- }
225
- summary = jarSummary(jar, config);
226
- serviceReady = false;
227
- if (summary.authenticated) {
228
- for (const domain of domains) {
229
- if (await validateServiceHost(jar, domain).catch(() => false)) {
230
- serviceReady = true;
231
- break;
232
- }
233
- }
234
- }
235
- }
236
-
237
- return {
238
- jar,
239
- summary,
240
- openedBrowser,
241
- serviceReady,
242
- hasServiceCookies,
243
- authUrl
244
- };
245
- }
246
-
247
- export async function ensureOktaAppSession(appName, options = {}) {
248
- const authOptions = resolveAutoAuthOptions(options);
249
- const config = authOptions.config ?? getSsoConfig();
250
- const { openBrowserOnMissing } = authOptions;
251
- const app = getOktaApp(appName);
252
- const domains = app.domains ?? [];
253
- const authUrl = resolveOktaAppAuthUrl(appName);
254
- let openedBrowser = false;
255
-
256
- if (app.mode === "cli-readonly") {
257
- const { jar, summary } = await ensureSsoSession({
258
- config,
259
- openBrowserOnMissing,
260
- onStatus: authOptions.onStatus
261
- });
262
- return { jar, summary, openedBrowser: false, appReady: true, authUrl };
263
- }
264
-
265
- let { jar, summary, openedBrowser: oktaOpened } = await ensureSsoSession({
266
- config,
267
- openBrowserOnMissing,
268
- forceBrowser: authOptions.forceBrowser === true,
269
- onStatus: authOptions.onStatus
270
- });
271
- openedBrowser = openedBrowser || oktaOpened;
272
-
273
- await syncOktaAppCookies(appName, { config });
274
- jar = await loadCookieJar(config.cookieJarPath);
275
- let hasAppCookies = hasCookiesForDomains(jar, domains);
276
- let appValidated =
277
- !domains.length ||
278
- app.mode === "bookmark" ||
279
- app.mode === "oidc-app" ||
280
- (hasAppCookies && (await validateOktaAppHost(jar, app, authOptions.fetchImpl).catch(() => false)));
281
-
282
- const needsAuth = openBrowserOnMissing && domains.length > 0 && (!hasAppCookies || !appValidated);
283
-
284
- if (needsAuth) {
285
- authOptions.onStatus?.({ phase: "opening_okta_app_auth", oktaApp: appName, url: authUrl });
286
- const auth = app.launchViaUserHome
287
- ? await openOktaAppForAuth(appName, { ...authOptions, config })
288
- : await openAuthPageAndWait(config, {
289
- authUrl,
290
- domains,
291
- label: appName,
292
- options: authOptions
293
- });
294
- jar = auth.jar;
295
- openedBrowser = openedBrowser || auth.openedBrowser;
296
- hasAppCookies = hasCookiesForDomains(jar, domains);
297
- appValidated = hasAppCookies && (await validateOktaAppHost(jar, app, authOptions.fetchImpl).catch(() => false));
298
- if (!auth.ready && !hasAppCookies && app.mode !== "bookmark" && app.mode !== "oidc-app") {
299
- throw new Error(
300
- `Okta app "${appName}" auth timed out. Complete login in Chrome at ${authUrl}, then retry.`
301
- );
302
- }
303
- summary = jarSummary(jar, config);
304
- }
305
-
306
- const appReady =
307
- appValidated ||
308
- app.mode === "bookmark" ||
309
- app.mode === "oidc-app" ||
310
- (domains.length === 0 && summary.authenticated);
311
-
312
- return {
313
- jar,
314
- summary,
315
- openedBrowser,
316
- appReady,
317
- hasAppCookies,
318
- authUrl
319
- };
320
- }
321
-
322
- export async function openAppsForAuth(appNames = [], options = {}) {
323
- const config = options.config ?? getSsoConfig();
324
- const opened = [];
325
- await ensureSsoSession({
326
- config,
327
- openBrowserOnMissing: true,
328
- forceBrowser: options.forceOkta === true,
329
- onStatus: options.onStatus
330
- });
331
- for (const appName of appNames) {
332
- const url = resolveOktaAppAuthUrl(appName);
333
- options.onStatus?.({ phase: "opening_app", oktaApp: appName, url });
334
- await openBrowser(url);
335
- opened.push({ app: appName, url });
336
- if (options.delayMs) await waitFor(options.delayMs);
337
- }
338
- return { opened, loginUrl: config.loginUrl };
339
- }
@@ -1,212 +0,0 @@
1
- import { existsSync, readdirSync } from "node:fs";
2
- import { dirname, join } from "node:path";
3
- import {
4
- buildCookieHeader,
5
- cookiesForHost,
6
- resolveBestCookieHost,
7
- isValidationFresh,
8
- jarSummary,
9
- loadCookieJar,
10
- mergeCookies,
11
- saveCookieJar
12
- } from "./cookieJar.mjs";
13
- import { hostPatternsForDomains, readChromeCookies, resolveChromeCookiesPath } from "./chromeCookies.mjs";
14
- import { openBrowser, waitFor } from "./browserLogin.mjs";
15
- import { validateOktaSession, validateServiceHost } from "./sessionValidate.mjs";
16
- import { getSsoConfig } from "./ssoConfig.mjs";
17
- import { getServiceDomains } from "./serviceRegistry.mjs";
18
-
19
- export async function importCookiesFromChrome(config = getSsoConfig(), domains = []) {
20
- const patterns = hostPatternsForDomains([config.domain, ...domains]);
21
- const cookiesPath = resolveChromeCookiesPath(config);
22
- let cookies = await readChromeCookies(cookiesPath, patterns);
23
- if (!cookies.length) {
24
- cookies = await readChromeCookiesFromProfileFallbacks(config, patterns);
25
- }
26
- if (!cookies.length) return null;
27
- return {
28
- cookies,
29
- authenticated: false,
30
- source: "chrome"
31
- };
32
- }
33
-
34
- async function readChromeCookiesFromProfileFallbacks(config, patterns) {
35
- if (process.env.WORKDAY_CHROME_PROFILE_FALLBACK === "false") return [];
36
- for (const cookiesPath of chromeCookieFallbackPaths(config)) {
37
- const cookies = await readChromeCookies(cookiesPath, patterns);
38
- if (cookies.length) return cookies;
39
- }
40
- return [];
41
- }
42
-
43
- export function chromeCookieFallbackPaths(config = getSsoConfig(), { readdir = readdirSync, exists = existsSync } = {}) {
44
- const primary = config.chromeCookiesPath || resolveChromeCookiesPath(config);
45
- const chromeRoot = dirname(dirname(primary));
46
- let entries;
47
- try {
48
- entries = readdir(chromeRoot);
49
- } catch {
50
- return [];
51
- }
52
- return entries
53
- .filter((entry) => entry === "Default" || /^Profile \d+$/u.test(entry))
54
- .map((entry) => join(chromeRoot, entry, "Cookies"))
55
- .filter((cookiesPath) => cookiesPath !== primary && exists(cookiesPath));
56
- }
57
-
58
- async function persistValidatedJar(config, jar) {
59
- const authenticated = await validateOktaSession(jar, config);
60
- const next = {
61
- ...jar,
62
- authenticated,
63
- validatedAt: authenticated ? new Date().toISOString() : jar.validatedAt
64
- };
65
- await saveCookieJar(config.cookieJarPath, next);
66
- return next;
67
- }
68
-
69
- function hasCookiesForDomains(jar, domains) {
70
- if (!domains.length) return true;
71
- return domains.some((domain) => cookiesForHost(jar?.cookies ?? [], domain).length > 0);
72
- }
73
-
74
- async function importAndMergeJar(config, jar, domains, { validate = true } = {}) {
75
- const imported = await importCookiesFromChrome(config, [config.domain, ...domains]);
76
- if (!imported) return jar;
77
- const next = {
78
- ...(jar ?? {}),
79
- cookies: mergeCookies(jar?.cookies ?? [], imported.cookies),
80
- source: imported.source
81
- };
82
- if (!validate) {
83
- await saveCookieJar(config.cookieJarPath, next);
84
- return next;
85
- }
86
- return persistValidatedJar(config, { ...next, authenticated: false });
87
- }
88
-
89
- export async function ensureSsoSession({
90
- config = getSsoConfig(),
91
- openBrowserOnMissing = false,
92
- forceBrowser = false,
93
- serviceId,
94
- onStatus
95
- } = {}) {
96
- let jar = await loadCookieJar(config.cookieJarPath);
97
- const serviceDomains = serviceId ? getServiceDomains(serviceId) : [];
98
- const needsServiceCookies = !hasCookiesForDomains(jar, serviceDomains);
99
-
100
- if (
101
- !forceBrowser &&
102
- jar &&
103
- isValidationFresh(jar, config.validateTtlMs) &&
104
- jar.authenticated &&
105
- !needsServiceCookies
106
- ) {
107
- return { jar, summary: jarSummary(jar, config), openedBrowser: false };
108
- }
109
-
110
- if (!forceBrowser && jar?.authenticated && needsServiceCookies) {
111
- onStatus?.({ phase: "import_service_cookies" });
112
- jar = await importAndMergeJar(config, jar, serviceDomains, { validate: false });
113
- return { jar, summary: jarSummary(jar, config), openedBrowser: false };
114
- }
115
-
116
- if (!forceBrowser) {
117
- onStatus?.({ phase: "import_from_chrome" });
118
- const imported = await importCookiesFromChrome(config, [config.domain, ...serviceDomains]);
119
- if (imported) {
120
- jar = {
121
- cookies: mergeCookies(jar?.cookies ?? [], imported.cookies),
122
- source: "chrome",
123
- authenticated: false
124
- };
125
- jar = await persistValidatedJar(config, jar);
126
- if (jar.authenticated) {
127
- return { jar, summary: jarSummary(jar, config), openedBrowser: false };
128
- }
129
- }
130
- }
131
-
132
- if (!openBrowserOnMissing && !forceBrowser) {
133
- return {
134
- jar,
135
- summary: jarSummary(jar, config),
136
- openedBrowser: false
137
- };
138
- }
139
-
140
- onStatus?.({ phase: "browser_opened", url: config.loginUrl });
141
- await openBrowser(config.loginUrl, { chromeProfile: config.chromeProfile });
142
-
143
- const deadline = Date.now() + config.loginTimeoutMs;
144
- while (Date.now() < deadline) {
145
- await waitFor(2000);
146
- onStatus?.({ phase: "waiting_for_login" });
147
- const imported = await importCookiesFromChrome(config, [config.domain, ...serviceDomains]);
148
- if (!imported?.cookies?.length) continue;
149
- jar = {
150
- cookies: mergeCookies(jar?.cookies ?? [], imported.cookies),
151
- source: "chrome-browser-login",
152
- authenticated: false
153
- };
154
- jar = await persistValidatedJar(config, jar);
155
- if (jar.authenticated) {
156
- return { jar, summary: jarSummary(jar, config), openedBrowser: true };
157
- }
158
- }
159
-
160
- throw new Error(
161
- `Okta browser login timed out after ${config.loginTimeoutMs}ms. Complete MFA in Chrome, then retry.`
162
- );
163
- }
164
-
165
- export function getOktaCookieHeader(jar, config = getSsoConfig()) {
166
- if (!jar?.cookies?.length) return "";
167
- return buildCookieHeader(jar.cookies, config.domain);
168
- }
169
-
170
- export function getCookiesForService(jar, serviceId) {
171
- const domains = getServiceDomains(serviceId);
172
- const cookies = domains.flatMap((domain) => cookiesForHost(jar?.cookies ?? [], domain));
173
- return { domains, cookies };
174
- }
175
-
176
- export async function syncOktaAppCookies(appName, options = {}) {
177
- const { getOktaApp } = await import("./oktaAppCatalog.mjs");
178
- const app = getOktaApp(appName);
179
- const config = options.config ?? getSsoConfig();
180
- const domains = [...new Set([config.domain, ...(app.domains ?? [])])];
181
- const imported = await importCookiesFromChrome(config, domains);
182
- if (!imported?.cookies?.length) return null;
183
- const jar = await loadCookieJar(config.cookieJarPath);
184
- const merged = {
185
- ...(jar ?? {}),
186
- cookies: mergeCookies(jar?.cookies ?? [], imported.cookies),
187
- source: "chrome-okta-app-sync"
188
- };
189
- await saveCookieJar(config.cookieJarPath, merged);
190
- return merged;
191
- }
192
-
193
- export async function syncAllOktaCatalogCookies(options = {}) {
194
- const { OKTA_USER_HOME_APPS } = await import("./oktaAppCatalog.mjs");
195
- const config = options.config ?? getSsoConfig();
196
- const domains = new Set([config.domain]);
197
- for (const app of Object.values(OKTA_USER_HOME_APPS)) {
198
- for (const domain of app.domains ?? []) domains.add(domain);
199
- }
200
- const imported = await importCookiesFromChrome(config, [...domains]);
201
- if (!imported?.cookies?.length) return null;
202
- const jar = await loadCookieJar(config.cookieJarPath);
203
- const merged = {
204
- ...(jar ?? {}),
205
- cookies: mergeCookies(jar?.cookies ?? [], imported.cookies),
206
- source: "chrome-okta-catalog-sync"
207
- };
208
- await saveCookieJar(config.cookieJarPath, merged);
209
- return merged;
210
- }
211
-
212
- export { jarSummary, loadCookieJar };
@@ -1,74 +0,0 @@
1
- import { buildCookieHeader, resolveBestCookieHost } from "./cookieJar.mjs";
2
-
3
- export async function validateOktaSession(jar, config) {
4
- if (!jar?.cookies?.length) return false;
5
- const cookie = buildCookieHeader(jar.cookies, config.domain);
6
- if (!cookie) return false;
7
-
8
- const response = await fetch(config.loginUrl, {
9
- method: "GET",
10
- redirect: "manual",
11
- headers: { cookie }
12
- });
13
-
14
- if (response.status === 200) return true;
15
- const location = response.headers.get("location") || "";
16
- if (response.status >= 300 && response.status < 400) {
17
- return !/login|signin|authorize/i.test(location);
18
- }
19
- return false;
20
- }
21
-
22
- export async function probeReadOnlyUrl(
23
- jar,
24
- { host, path = "/", cookie, fetchImpl = globalThis.fetch } = {}
25
- ) {
26
- if (!host || !cookie) return { ready: false, status: 0, reason: "no_cookies" };
27
- const response = await fetchImpl(`https://${host}${path}`, {
28
- method: "GET",
29
- redirect: "manual",
30
- headers: { cookie, accept: "text/html,application/json" }
31
- });
32
- const location = response.headers.get("location") || "";
33
- const loginRedirect = /login|signin|authorize|okta/i.test(location);
34
- const contentType = response.headers.get("content-type") || undefined;
35
- let loginPage = false;
36
- if (response.status === 200 && /text\/html/i.test(contentType ?? "")) {
37
- const htmlResponse = typeof response.clone === "function" ? response.clone() : response;
38
- const html = typeof htmlResponse.text === "function" ? await htmlResponse.text().catch(() => "") : "";
39
- loginPage = /<title[^>]*>\s*(?:log in|login|log into|sign in|signin)\b|data-testid=["']login|name=["']os_username/i.test(html);
40
- }
41
- return {
42
- ready:
43
- (response.status === 200 && !loginPage) ||
44
- (response.status >= 300 && response.status < 400 && !loginRedirect),
45
- status: response.status,
46
- location: location || undefined,
47
- contentType,
48
- loginPage
49
- };
50
- }
51
-
52
- export async function validateOktaAppHost(jar, app, fetchImpl = globalThis.fetch) {
53
- const domains = app?.domains ?? [];
54
- if (!domains.length) return true;
55
- if (app.mode === "bookmark" || app.mode === "oidc-app" || app.mode === "cli-readonly") return true;
56
- const { host, cookie, hasCookies } = resolveBestCookieHost(jar, domains);
57
- if (!hasCookies || !cookie || !host) return false;
58
- const probe = await probeReadOnlyUrl(jar, {
59
- host,
60
- path: app.probePath ?? "/",
61
- cookie,
62
- fetchImpl
63
- });
64
- return probe.ready;
65
- }
66
-
67
- export async function validateServiceHost(jar, host) {
68
- if (!jar?.cookies?.length || !host) return false;
69
- const cookie = buildCookieHeader(jar.cookies, host);
70
- if (!cookie) return false;
71
-
72
- const probe = await probeReadOnlyUrl(jar, { host, cookie });
73
- return probe.ready;
74
- }
@@ -1,31 +0,0 @@
1
- import { homedir } from "node:os";
2
- import { join } from "node:path";
3
-
4
- export function getSsoConfig(env = process.env) {
5
- const domain = env.WORKDAY_OKTA_DOMAIN?.trim() || "workday.okta.com";
6
- const loginUrl = env.WORKDAY_OKTA_LOGIN_URL?.trim() || `https://${domain}/app/UserHome`;
7
- const chromeProfileOverride = env.WORKDAY_CHROME_PROFILE?.trim();
8
- const chromeProfile = chromeProfileOverride || "Default";
9
- const validateTtlMs = Number(env.WORKDAY_SSO_VALIDATE_TTL_MS ?? 900_000);
10
- const loginTimeoutMs = Number(env.WORKDAY_SSO_LOGIN_TIMEOUT_MS ?? 300_000);
11
- const baseDir = join(homedir(), ".Nuvlore", "workday");
12
-
13
- return {
14
- domain,
15
- loginUrl,
16
- chromeProfile,
17
- chromeProfileExplicit: Boolean(chromeProfileOverride),
18
- validateTtlMs,
19
- loginTimeoutMs,
20
- cookieJarPath: join(baseDir, "cookie-jar.json"),
21
- chromeCookiesPath: join(
22
- homedir(),
23
- "Library",
24
- "Application Support",
25
- "Google",
26
- "Chrome",
27
- chromeProfile,
28
- "Cookies"
29
- )
30
- };
31
- }