@lvce-editor/auth-worker 1.15.0 → 1.16.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.
@@ -1718,16 +1718,6 @@ async function tokenEndpointRequest(as, client, clientAuthentication, grantType,
1718
1718
  }
1719
1719
  const idTokenClaims = new WeakMap();
1720
1720
  const jwtRefs = new WeakMap();
1721
- function getValidatedIdTokenClaims(ref) {
1722
- if (!ref.id_token) {
1723
- return undefined;
1724
- }
1725
- const claims = idTokenClaims.get(ref);
1726
- if (!claims) {
1727
- throw CodedTypeError('"ref" was already garbage collected or did not resolve from the proper sources', ERR_INVALID_ARG_VALUE);
1728
- }
1729
- return claims;
1730
- }
1731
1721
  async function processGenericAccessTokenResponse(as, client, response, additionalRequiredIdTokenClaims, decryptFn, recognizedTokenTypes) {
1732
1722
  assertAs(as);
1733
1723
  assertClient(client);
@@ -1773,9 +1763,6 @@ async function processGenericAccessTokenResponse(as, client, response, additiona
1773
1763
  assertNumber(client.default_max_age, true, '"client.default_max_age"');
1774
1764
  requiredClaims.push('auth_time');
1775
1765
  }
1776
- if (additionalRequiredIdTokenClaims?.length) {
1777
- requiredClaims.push(...additionalRequiredIdTokenClaims);
1778
- }
1779
1766
  const {
1780
1767
  claims,
1781
1768
  jwt
@@ -1853,27 +1840,6 @@ function validateIssuer(as, result) {
1853
1840
  return result;
1854
1841
  }
1855
1842
  const branded = new WeakSet();
1856
- const nopkce = Symbol();
1857
- async function authorizationCodeGrantRequest(as, client, clientAuthentication, callbackParameters, redirectUri, codeVerifier, options) {
1858
- assertAs(as);
1859
- assertClient(client);
1860
- if (!branded.has(callbackParameters)) {
1861
- throw CodedTypeError('"callbackParameters" must be an instance of URLSearchParams obtained from "validateAuthResponse()", or "validateJwtAuthResponse()', ERR_INVALID_ARG_VALUE);
1862
- }
1863
- assertString(redirectUri, '"redirectUri"');
1864
- const code = getURLSearchParameter(callbackParameters, 'code');
1865
- if (!code) {
1866
- throw OPE('no authorization code in "callbackParameters"', INVALID_RESPONSE);
1867
- }
1868
- const parameters = new URLSearchParams(options?.additionalParameters);
1869
- parameters.set('redirect_uri', redirectUri);
1870
- parameters.set('code', code);
1871
- if (codeVerifier !== nopkce) {
1872
- assertString(codeVerifier, '"codeVerifier"');
1873
- parameters.set('code_verifier', codeVerifier);
1874
- }
1875
- return tokenEndpointRequest(as, client, clientAuthentication, 'authorization_code', parameters, options);
1876
- }
1877
1843
  const jwtClaimNames = {
1878
1844
  aud: 'audience',
1879
1845
  c_hash: 'code hash',
@@ -1901,98 +1867,6 @@ function validatePresence(required, result) {
1901
1867
  }
1902
1868
  return result;
1903
1869
  }
1904
- const expectNoNonce = Symbol();
1905
- const skipAuthTimeCheck = Symbol();
1906
- async function processAuthorizationCodeResponse(as, client, response, options) {
1907
- if (typeof options?.expectedNonce === 'string' || typeof options?.maxAge === 'number' || options?.requireIdToken) {
1908
- return processAuthorizationCodeOpenIDResponse(as, client, response, options.expectedNonce, options.maxAge, options[jweDecrypt], options.recognizedTokenTypes);
1909
- }
1910
- return processAuthorizationCodeOAuth2Response(as, client, response, options?.[jweDecrypt], options?.recognizedTokenTypes);
1911
- }
1912
- async function processAuthorizationCodeOpenIDResponse(as, client, response, expectedNonce, maxAge, decryptFn, recognizedTokenTypes) {
1913
- const additionalRequiredClaims = [];
1914
- switch (expectedNonce) {
1915
- case undefined:
1916
- expectedNonce = expectNoNonce;
1917
- break;
1918
- case expectNoNonce:
1919
- break;
1920
- default:
1921
- assertString(expectedNonce, '"expectedNonce" argument');
1922
- additionalRequiredClaims.push('nonce');
1923
- }
1924
- maxAge ??= client.default_max_age;
1925
- switch (maxAge) {
1926
- case undefined:
1927
- maxAge = skipAuthTimeCheck;
1928
- break;
1929
- case skipAuthTimeCheck:
1930
- break;
1931
- default:
1932
- assertNumber(maxAge, true, '"maxAge" argument');
1933
- additionalRequiredClaims.push('auth_time');
1934
- }
1935
- const result = await processGenericAccessTokenResponse(as, client, response, additionalRequiredClaims, decryptFn, recognizedTokenTypes);
1936
- assertString(result.id_token, '"response" body "id_token" property', INVALID_RESPONSE, {
1937
- body: result
1938
- });
1939
- const claims = getValidatedIdTokenClaims(result);
1940
- if (maxAge !== skipAuthTimeCheck) {
1941
- const now = epochTime() + getClockSkew(client);
1942
- const tolerance = getClockTolerance(client);
1943
- if (claims.auth_time + maxAge < now - tolerance) {
1944
- throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, {
1945
- claims,
1946
- now,
1947
- tolerance,
1948
- claim: 'auth_time'
1949
- });
1950
- }
1951
- }
1952
- if (expectedNonce === expectNoNonce) {
1953
- if (claims.nonce !== undefined) {
1954
- throw OPE('unexpected ID Token "nonce" claim value', JWT_CLAIM_COMPARISON, {
1955
- expected: undefined,
1956
- claims,
1957
- claim: 'nonce'
1958
- });
1959
- }
1960
- } else if (claims.nonce !== expectedNonce) {
1961
- throw OPE('unexpected ID Token "nonce" claim value', JWT_CLAIM_COMPARISON, {
1962
- expected: expectedNonce,
1963
- claims,
1964
- claim: 'nonce'
1965
- });
1966
- }
1967
- return result;
1968
- }
1969
- async function processAuthorizationCodeOAuth2Response(as, client, response, decryptFn, recognizedTokenTypes) {
1970
- const result = await processGenericAccessTokenResponse(as, client, response, undefined, decryptFn, recognizedTokenTypes);
1971
- const claims = getValidatedIdTokenClaims(result);
1972
- if (claims) {
1973
- if (client.default_max_age !== undefined) {
1974
- assertNumber(client.default_max_age, true, '"client.default_max_age"');
1975
- const now = epochTime() + getClockSkew(client);
1976
- const tolerance = getClockTolerance(client);
1977
- if (claims.auth_time + client.default_max_age < now - tolerance) {
1978
- throw OPE('too much time has elapsed since the last End-User authentication', JWT_TIMESTAMP_CHECK, {
1979
- claims,
1980
- now,
1981
- tolerance,
1982
- claim: 'auth_time'
1983
- });
1984
- }
1985
- }
1986
- if (claims.nonce !== undefined) {
1987
- throw OPE('unexpected ID Token "nonce" claim value', JWT_CLAIM_COMPARISON, {
1988
- expected: undefined,
1989
- claims,
1990
- claim: 'nonce'
1991
- });
1992
- }
1993
- }
1994
- return result;
1995
- }
1996
1870
  const WWW_AUTHENTICATE_CHALLENGE = 'OAUTH_WWW_AUTHENTICATE_CHALLENGE';
1997
1871
  const RESPONSE_BODY_ERROR = 'OAUTH_RESPONSE_BODY_ERROR';
1998
1872
  const UNSUPPORTED_OPERATION = 'OAUTH_UNSUPPORTED_OPERATION';
@@ -2006,6 +1880,15 @@ const JWT_TIMESTAMP_CHECK = 'OAUTH_JWT_TIMESTAMP_CHECK_FAILED';
2006
1880
  const JWT_CLAIM_COMPARISON = 'OAUTH_JWT_CLAIM_COMPARISON_FAILED';
2007
1881
  const MISSING_SERVER_METADATA = 'OAUTH_MISSING_SERVER_METADATA';
2008
1882
  const INVALID_SERVER_METADATA = 'OAUTH_INVALID_SERVER_METADATA';
1883
+ async function genericTokenEndpointRequest(as, client, clientAuthentication, grantType, parameters, options) {
1884
+ assertAs(as);
1885
+ assertClient(client);
1886
+ assertString(grantType, '"grantType"');
1887
+ return tokenEndpointRequest(as, client, clientAuthentication, grantType, new URLSearchParams(parameters), options);
1888
+ }
1889
+ async function processGenericTokenEndpointResponse(as, client, response, options) {
1890
+ return processGenericAccessTokenResponse(as, client, response, undefined, options?.[jweDecrypt], options?.recognizedTokenTypes);
1891
+ }
2009
1892
  function assertReadableResponse(response) {
2010
1893
  if (response.bodyUsed) {
2011
1894
  throw CodedTypeError('"response" body has been used already', ERR_INVALID_ARG_VALUE);
@@ -2155,16 +2038,6 @@ function checkSigningAlgorithm(client, issuer, fallback, header) {
2155
2038
  fallback
2156
2039
  });
2157
2040
  }
2158
- function getURLSearchParameter(parameters, name) {
2159
- const {
2160
- 0: value,
2161
- length
2162
- } = parameters.getAll(name);
2163
- if (length > 1) {
2164
- throw OPE(`"${name}" parameter must be provided only once`, INVALID_RESPONSE);
2165
- }
2166
- return value;
2167
- }
2168
2041
  async function getResponseJsonBody(response, check = assertApplicationJson) {
2169
2042
  let json;
2170
2043
  try {
@@ -2518,6 +2391,60 @@ const isLoginResponse = value => {
2518
2391
  return true;
2519
2392
  };
2520
2393
 
2394
+ const databaseName = 'auth-worker';
2395
+ const objectStoreName = 'auth';
2396
+ const memoryStorage = new Map();
2397
+ let databasePromise;
2398
+
2399
+ // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types
2400
+ const transactionToPromise = transaction => {
2401
+ return new Promise((resolve, reject) => {
2402
+ transaction.addEventListener('complete', () => {
2403
+ resolve();
2404
+ });
2405
+ transaction.addEventListener('abort', () => {
2406
+ reject(transaction.error ?? new Error('Persistent storage transaction failed.'));
2407
+ });
2408
+ transaction.addEventListener('error', () => {
2409
+ reject(transaction.error ?? new Error('Persistent storage transaction failed.'));
2410
+ });
2411
+ });
2412
+ };
2413
+ const getDatabase = async () => {
2414
+ if (typeof indexedDB === 'undefined') {
2415
+ return undefined;
2416
+ }
2417
+ if (!databasePromise) {
2418
+ databasePromise = new Promise((resolve, reject) => {
2419
+ const request = indexedDB.open(databaseName, 1);
2420
+ request.addEventListener('upgradeneeded', () => {
2421
+ const database = request.result;
2422
+ if (!database.objectStoreNames.contains(objectStoreName)) {
2423
+ database.createObjectStore(objectStoreName);
2424
+ }
2425
+ });
2426
+ request.addEventListener('success', () => {
2427
+ resolve(request.result);
2428
+ });
2429
+ request.addEventListener('error', () => {
2430
+ reject(request.error ?? new Error('Failed to open persistent auth storage.'));
2431
+ });
2432
+ });
2433
+ }
2434
+ return databasePromise;
2435
+ };
2436
+ const setPersistentAuthValue = async (key, value) => {
2437
+ memoryStorage.set(key, value);
2438
+ const database = await getDatabase();
2439
+ if (!database) {
2440
+ return;
2441
+ }
2442
+ const transaction = database.transaction(objectStoreName, 'readwrite');
2443
+ const objectStore = transaction.objectStore(objectStoreName);
2444
+ objectStore.put(value, key);
2445
+ await transactionToPromise(transaction);
2446
+ };
2447
+
2521
2448
  const getBackendOidcTokenUrl = backendUrl => {
2522
2449
  return getBackendAuthUrl(backendUrl, '/oidc/token');
2523
2450
  };
@@ -2534,15 +2461,15 @@ const getClient = () => {
2534
2461
  client_id: oidcClientId
2535
2462
  };
2536
2463
  };
2537
- const exchangeElectronAuthorizationCode = async (backendUrl, code, redirectUri, codeVerifier, nonce, requestAuthorizationCodeGrant = authorizationCodeGrantRequest, processAuthorizationCodeGrantResponse = processAuthorizationCodeResponse) => {
2464
+ const exchangeElectronAuthorizationCode = async (backendUrl, code, redirectUri, codeVerifier, requestTokenEndpoint = genericTokenEndpointRequest, processTokenEndpointResponse = processGenericTokenEndpointResponse) => {
2538
2465
  const authorizationServer = getAuthorizationServer(backendUrl);
2539
2466
  const client = getClient();
2540
- const response = await requestAuthorizationCodeGrant(authorizationServer, client, None(), new URLSearchParams({
2541
- code
2542
- }), redirectUri, codeVerifier);
2543
- const tokenResponse = await processAuthorizationCodeGrantResponse(authorizationServer, client, response, {
2544
- expectedNonce: nonce
2545
- });
2467
+ const response = await requestTokenEndpoint(authorizationServer, client, None(), 'authorization_code', new URLSearchParams({
2468
+ code,
2469
+ code_verifier: codeVerifier,
2470
+ redirect_uri: redirectUri
2471
+ }));
2472
+ const tokenResponse = await processTokenEndpointResponse(authorizationServer, client, response);
2546
2473
  return {
2547
2474
  accessToken: tokenResponse.access_token,
2548
2475
  refreshToken: typeof tokenResponse.refresh_token === 'string' ? tokenResponse.refresh_token : ''
@@ -2555,12 +2482,12 @@ const hasAuthorizationCode = value => {
2555
2482
  const getElectronAuthorizationCode = async uid => {
2556
2483
  return invoke$2('OAuthServer.getCode', String(uid));
2557
2484
  };
2558
- const waitForElectronBackendLogin = async (backendUrl, uid, redirectUri, nonce, codeVerifier, timeoutMs = 30_000, pollIntervalMs = 1000, getAuthorizationCode = getElectronAuthorizationCode, exchangeAuthorizationCode = exchangeElectronAuthorizationCode) => {
2485
+ const waitForElectronBackendLogin = async (backendUrl, uid, redirectUri, codeVerifier, timeoutMs = 30_000, pollIntervalMs = 1000, getAuthorizationCode = getElectronAuthorizationCode, exchangeAuthorizationCode = exchangeElectronAuthorizationCode) => {
2559
2486
  const deadline = Date.now() + timeoutMs;
2560
2487
  while (Date.now() < deadline) {
2561
2488
  const authorizationCode = await getAuthorizationCode(uid);
2562
2489
  if (hasAuthorizationCode(authorizationCode)) {
2563
- const tokenResponse = await exchangeAuthorizationCode(backendUrl, authorizationCode, redirectUri, codeVerifier, nonce);
2490
+ const tokenResponse = await exchangeAuthorizationCode(backendUrl, authorizationCode, redirectUri, codeVerifier);
2564
2491
  return {
2565
2492
  authAccessToken: tokenResponse.accessToken,
2566
2493
  authErrorMessage: '',
@@ -2573,6 +2500,14 @@ const waitForElectronBackendLogin = async (backendUrl, uid, redirectUri, nonce,
2573
2500
  return getLoggedOutBackendAuthState('Timed out waiting for backend login.');
2574
2501
  };
2575
2502
 
2503
+ const persistLoginResult = async loginResult => {
2504
+ if (loginResult.userState !== 'loggedIn') {
2505
+ return loginResult;
2506
+ }
2507
+ await setPersistentAuthValue('accessToken', loginResult.authAccessToken ?? '');
2508
+ await setPersistentAuthValue('refreshToken', loginResult.authRefreshToken ?? '');
2509
+ return loginResult;
2510
+ };
2576
2511
  const handleClickLogin = async options => {
2577
2512
  const {
2578
2513
  authUseRedirect,
@@ -2604,20 +2539,17 @@ const handleClickLogin = async options => {
2604
2539
  userState: 'loggedOut'
2605
2540
  };
2606
2541
  }
2607
- return getLoggedInState(signingInState, response);
2542
+ return persistLoginResult(getLoggedInState(signingInState, response));
2608
2543
  }
2609
2544
  const uid = 0;
2610
2545
  const {
2611
2546
  codeVerifier,
2612
2547
  loginUrl,
2613
- nonce,
2614
2548
  redirectUri
2615
2549
  } = await getBackendLoginRequest(backendUrl, platform, uid);
2616
2550
  await invoke$1('Open.openUrl', loginUrl, platform, authUseRedirect);
2617
- const authState = platform === Electron ? await waitForElectronBackendLogin(backendUrl, uid, redirectUri, nonce, codeVerifier) : await waitForBackendLogin(backendUrl);
2618
- return {
2619
- ...authState
2620
- };
2551
+ const authState = platform === Electron ? await waitForElectronBackendLogin(backendUrl, uid, redirectUri, codeVerifier) : await waitForBackendLogin(backendUrl);
2552
+ return persistLoginResult(authState);
2621
2553
  } catch (error) {
2622
2554
  const errorMessage = error instanceof Error && error.message ? error.message : 'Backend authentication failed.';
2623
2555
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/auth-worker",
3
- "version": "1.15.0",
3
+ "version": "1.16.0",
4
4
  "description": "Auth Worker",
5
5
  "repository": {
6
6
  "type": "git",