@lvce-editor/auth-worker 1.11.0 → 1.13.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/authWorkerMain.js +157 -66
- package/package.json +1 -1
package/dist/authWorkerMain.js
CHANGED
|
@@ -968,7 +968,7 @@ const createMockRpc = ({
|
|
|
968
968
|
};
|
|
969
969
|
|
|
970
970
|
const rpcs = Object.create(null);
|
|
971
|
-
const set$
|
|
971
|
+
const set$2 = (id, rpc) => {
|
|
972
972
|
rpcs[id] = rpc;
|
|
973
973
|
};
|
|
974
974
|
const get = id => {
|
|
@@ -1001,7 +1001,7 @@ const create = rpcId => {
|
|
|
1001
1001
|
const mockRpc = createMockRpc({
|
|
1002
1002
|
commandMap
|
|
1003
1003
|
});
|
|
1004
|
-
set$
|
|
1004
|
+
set$2(rpcId, mockRpc);
|
|
1005
1005
|
// @ts-ignore
|
|
1006
1006
|
mockRpc[Symbol.dispose] = () => {
|
|
1007
1007
|
remove(rpcId);
|
|
@@ -1010,14 +1010,14 @@ const create = rpcId => {
|
|
|
1010
1010
|
return mockRpc;
|
|
1011
1011
|
},
|
|
1012
1012
|
set(rpc) {
|
|
1013
|
-
set$
|
|
1013
|
+
set$2(rpcId, rpc);
|
|
1014
1014
|
}
|
|
1015
1015
|
};
|
|
1016
1016
|
};
|
|
1017
1017
|
|
|
1018
1018
|
const {
|
|
1019
1019
|
invoke: invoke$2,
|
|
1020
|
-
set: set$
|
|
1020
|
+
set: set$1
|
|
1021
1021
|
} = create(6040);
|
|
1022
1022
|
|
|
1023
1023
|
const Electron = 2;
|
|
@@ -1027,32 +1027,26 @@ const RendererWorker = 1;
|
|
|
1027
1027
|
|
|
1028
1028
|
const {
|
|
1029
1029
|
invoke: invoke$1,
|
|
1030
|
-
set
|
|
1030
|
+
set
|
|
1031
1031
|
} = create(OpenerWorker);
|
|
1032
1032
|
|
|
1033
1033
|
const {
|
|
1034
1034
|
invoke,
|
|
1035
|
-
invokeAndTransfer
|
|
1036
|
-
set
|
|
1037
|
-
} = create(RendererWorker);
|
|
1035
|
+
invokeAndTransfer} = create(RendererWorker);
|
|
1038
1036
|
const sendMessagePortToOpenerWorker$1 = async (port, rpcId) => {
|
|
1039
1037
|
const command = 'HandleMessagePort.handleMessagePort';
|
|
1040
1038
|
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToOpenerWorker', port, command, rpcId);
|
|
1041
1039
|
};
|
|
1042
|
-
const sendMessagePortToSharedProcess = async port => {
|
|
1043
|
-
const command = 'HandleElectronMessagePort.handleElectronMessagePort';
|
|
1044
|
-
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToSharedProcess', port, command, 0);
|
|
1045
|
-
};
|
|
1046
1040
|
|
|
1047
1041
|
const sendMessagePortToAuthProcess = async port => {
|
|
1048
|
-
await sendMessagePortToSharedProcess
|
|
1042
|
+
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToSharedProcess', port, 'HandleMessagePortForAuthProcess.handleMessagePortForAuthProcess');
|
|
1049
1043
|
};
|
|
1050
1044
|
const initializeAuthProcess = async () => {
|
|
1051
1045
|
const rpc = await create$2({
|
|
1052
1046
|
commandMap: {},
|
|
1053
1047
|
send: sendMessagePortToAuthProcess
|
|
1054
1048
|
});
|
|
1055
|
-
set$
|
|
1049
|
+
set$1(rpc);
|
|
1056
1050
|
};
|
|
1057
1051
|
|
|
1058
1052
|
const sendMessagePortToOpenerWorker = async port => {
|
|
@@ -1063,7 +1057,7 @@ const initializeOpenerWorker = async () => {
|
|
|
1063
1057
|
commandMap: {},
|
|
1064
1058
|
send: sendMessagePortToOpenerWorker
|
|
1065
1059
|
});
|
|
1066
|
-
set
|
|
1060
|
+
set(rpc);
|
|
1067
1061
|
};
|
|
1068
1062
|
|
|
1069
1063
|
const handleMessagePort = async (port, rpcId) => {
|
|
@@ -1073,7 +1067,7 @@ const handleMessagePort = async (port, rpcId) => {
|
|
|
1073
1067
|
messagePort: port
|
|
1074
1068
|
});
|
|
1075
1069
|
if (rpcId) {
|
|
1076
|
-
set$
|
|
1070
|
+
set$2(rpcId, rpc);
|
|
1077
1071
|
}
|
|
1078
1072
|
};
|
|
1079
1073
|
|
|
@@ -1267,6 +1261,115 @@ const waitForBackendLogin = async (backendUrl, timeoutMs = 30_000, pollIntervalM
|
|
|
1267
1261
|
return getLoggedOutBackendAuthState(lastErrorMessage);
|
|
1268
1262
|
};
|
|
1269
1263
|
|
|
1264
|
+
if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) ;
|
|
1265
|
+
const ERR_INVALID_ARG_VALUE = 'ERR_INVALID_ARG_VALUE';
|
|
1266
|
+
const ERR_INVALID_ARG_TYPE = 'ERR_INVALID_ARG_TYPE';
|
|
1267
|
+
function CodedTypeError(message, code, cause) {
|
|
1268
|
+
const err = new TypeError(message, {
|
|
1269
|
+
cause
|
|
1270
|
+
});
|
|
1271
|
+
Object.assign(err, {
|
|
1272
|
+
code
|
|
1273
|
+
});
|
|
1274
|
+
return err;
|
|
1275
|
+
}
|
|
1276
|
+
const encoder = new TextEncoder();
|
|
1277
|
+
const decoder = new TextDecoder();
|
|
1278
|
+
function buf(input) {
|
|
1279
|
+
if (typeof input === 'string') {
|
|
1280
|
+
return encoder.encode(input);
|
|
1281
|
+
}
|
|
1282
|
+
return decoder.decode(input);
|
|
1283
|
+
}
|
|
1284
|
+
let encodeBase64Url;
|
|
1285
|
+
if (Uint8Array.prototype.toBase64) {
|
|
1286
|
+
encodeBase64Url = input => {
|
|
1287
|
+
if (input instanceof ArrayBuffer) {
|
|
1288
|
+
input = new Uint8Array(input);
|
|
1289
|
+
}
|
|
1290
|
+
return input.toBase64({
|
|
1291
|
+
alphabet: 'base64url',
|
|
1292
|
+
omitPadding: true
|
|
1293
|
+
});
|
|
1294
|
+
};
|
|
1295
|
+
} else {
|
|
1296
|
+
const CHUNK_SIZE = 0x8000;
|
|
1297
|
+
encodeBase64Url = input => {
|
|
1298
|
+
if (input instanceof ArrayBuffer) {
|
|
1299
|
+
input = new Uint8Array(input);
|
|
1300
|
+
}
|
|
1301
|
+
const arr = [];
|
|
1302
|
+
for (let i = 0; i < input.byteLength; i += CHUNK_SIZE) {
|
|
1303
|
+
arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
1304
|
+
}
|
|
1305
|
+
return btoa(arr.join('')).replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
let decodeBase64Url;
|
|
1309
|
+
if (Uint8Array.fromBase64) {
|
|
1310
|
+
decodeBase64Url = input => {
|
|
1311
|
+
try {
|
|
1312
|
+
return Uint8Array.fromBase64(input, {
|
|
1313
|
+
alphabet: 'base64url'
|
|
1314
|
+
});
|
|
1315
|
+
} catch (cause) {
|
|
1316
|
+
throw CodedTypeError('The input to be decoded is not correctly encoded.', ERR_INVALID_ARG_VALUE, cause);
|
|
1317
|
+
}
|
|
1318
|
+
};
|
|
1319
|
+
} else {
|
|
1320
|
+
decodeBase64Url = input => {
|
|
1321
|
+
try {
|
|
1322
|
+
const binary = atob(input.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''));
|
|
1323
|
+
const bytes = new Uint8Array(binary.length);
|
|
1324
|
+
for (let i = 0; i < binary.length; i++) {
|
|
1325
|
+
bytes[i] = binary.charCodeAt(i);
|
|
1326
|
+
}
|
|
1327
|
+
return bytes;
|
|
1328
|
+
} catch (cause) {
|
|
1329
|
+
throw CodedTypeError('The input to be decoded is not correctly encoded.', ERR_INVALID_ARG_VALUE, cause);
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
function b64u(input) {
|
|
1334
|
+
if (typeof input === 'string') {
|
|
1335
|
+
return decodeBase64Url(input);
|
|
1336
|
+
}
|
|
1337
|
+
return encodeBase64Url(input);
|
|
1338
|
+
}
|
|
1339
|
+
function assertString(input, it, code, cause) {
|
|
1340
|
+
try {
|
|
1341
|
+
if (typeof input !== 'string') {
|
|
1342
|
+
throw CodedTypeError(`${it} must be a string`, ERR_INVALID_ARG_TYPE, cause);
|
|
1343
|
+
}
|
|
1344
|
+
if (input.length === 0) {
|
|
1345
|
+
throw CodedTypeError(`${it} must not be empty`, ERR_INVALID_ARG_VALUE, cause);
|
|
1346
|
+
}
|
|
1347
|
+
} catch (err) {
|
|
1348
|
+
throw err;
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
function randomBytes() {
|
|
1352
|
+
return b64u(crypto.getRandomValues(new Uint8Array(32)));
|
|
1353
|
+
}
|
|
1354
|
+
function generateRandomCodeVerifier() {
|
|
1355
|
+
return randomBytes();
|
|
1356
|
+
}
|
|
1357
|
+
async function calculatePKCECodeChallenge(codeVerifier) {
|
|
1358
|
+
assertString(codeVerifier, 'codeVerifier');
|
|
1359
|
+
return b64u(await crypto.subtle.digest('SHA-256', buf(codeVerifier)));
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
// cspell:ignore pkce
|
|
1363
|
+
|
|
1364
|
+
const createPkceValues = async () => {
|
|
1365
|
+
const codeVerifier = generateRandomCodeVerifier();
|
|
1366
|
+
const codeChallenge = await calculatePKCECodeChallenge(codeVerifier);
|
|
1367
|
+
return {
|
|
1368
|
+
codeChallenge,
|
|
1369
|
+
codeVerifier
|
|
1370
|
+
};
|
|
1371
|
+
};
|
|
1372
|
+
|
|
1270
1373
|
const getCurrentHref = async () => {
|
|
1271
1374
|
try {
|
|
1272
1375
|
return await invoke('Layout.getHref');
|
|
@@ -1527,7 +1630,7 @@ const errorHtml = `<!doctype html>
|
|
|
1527
1630
|
|
|
1528
1631
|
const getElectronRedirectUri = async uid => {
|
|
1529
1632
|
const localOauthServerPort = await invoke$2('OAuthServer.create', String(uid), successHtml, errorHtml);
|
|
1530
|
-
return `http://localhost:${localOauthServerPort}`;
|
|
1633
|
+
return `http://localhost:${localOauthServerPort}/callback`;
|
|
1531
1634
|
};
|
|
1532
1635
|
|
|
1533
1636
|
const getEffectiveRedirectUri = async (platform, uid, redirectUri) => {
|
|
@@ -1540,13 +1643,31 @@ const getEffectiveRedirectUri = async (platform, uid, redirectUri) => {
|
|
|
1540
1643
|
return getCurrentHref();
|
|
1541
1644
|
};
|
|
1542
1645
|
|
|
1543
|
-
const
|
|
1544
|
-
|
|
1646
|
+
const oidcClientId = 'lvce-editor-native';
|
|
1647
|
+
const oidcScope = 'openid offline_access profile email';
|
|
1648
|
+
|
|
1649
|
+
// cspell:ignore pkce
|
|
1650
|
+
|
|
1651
|
+
const getBackendLoginRequest = async (backendUrl, platform = 0, uid = 0, redirectUri = '', createPkceValuesFn = createPkceValues, createRandomUuid = () => globalThis.crypto.randomUUID()) => {
|
|
1545
1652
|
const effectiveRedirectUri = await getEffectiveRedirectUri(platform, uid, redirectUri);
|
|
1653
|
+
const {
|
|
1654
|
+
codeChallenge,
|
|
1655
|
+
codeVerifier
|
|
1656
|
+
} = await createPkceValuesFn();
|
|
1657
|
+
const loginUrl = new URL(getBackendAuthUrl(backendUrl, '/oidc/auth'));
|
|
1658
|
+
loginUrl.searchParams.set('client_id', oidcClientId);
|
|
1659
|
+
loginUrl.searchParams.set('code_challenge', codeChallenge);
|
|
1660
|
+
loginUrl.searchParams.set('code_challenge_method', 'S256');
|
|
1661
|
+
loginUrl.searchParams.set('nonce', createRandomUuid());
|
|
1662
|
+
loginUrl.searchParams.set('prompt', 'consent');
|
|
1663
|
+
loginUrl.searchParams.set('response_type', 'code');
|
|
1664
|
+
loginUrl.searchParams.set('scope', oidcScope);
|
|
1665
|
+
loginUrl.searchParams.set('state', createRandomUuid());
|
|
1546
1666
|
if (effectiveRedirectUri) {
|
|
1547
1667
|
loginUrl.searchParams.set('redirect_uri', effectiveRedirectUri);
|
|
1548
1668
|
}
|
|
1549
1669
|
return {
|
|
1670
|
+
codeVerifier,
|
|
1550
1671
|
loginUrl: loginUrl.toString(),
|
|
1551
1672
|
redirectUri: effectiveRedirectUri
|
|
1552
1673
|
};
|
|
@@ -1572,52 +1693,23 @@ const isLoginResponse = value => {
|
|
|
1572
1693
|
return true;
|
|
1573
1694
|
};
|
|
1574
1695
|
|
|
1575
|
-
const getBackendNativeExchangeUrl = backendUrl => {
|
|
1576
|
-
return getBackendAuthUrl(backendUrl, '/auth/native/exchange');
|
|
1577
|
-
};
|
|
1578
|
-
|
|
1579
|
-
const getExchangeErrorMessage = async response => {
|
|
1580
|
-
try {
|
|
1581
|
-
const payload = await response.json();
|
|
1582
|
-
if (payload && typeof payload === 'object' && typeof payload.error === 'string' && payload.error) {
|
|
1583
|
-
return payload.error;
|
|
1584
|
-
}
|
|
1585
|
-
} catch {
|
|
1586
|
-
// ignore
|
|
1587
|
-
}
|
|
1588
|
-
return 'Backend authentication failed.';
|
|
1589
|
-
};
|
|
1590
|
-
const exchangeElectronAuthorizationCode = async (backendUrl, code, redirectUri) => {
|
|
1591
|
-
const response = await fetch(getBackendNativeExchangeUrl(backendUrl), {
|
|
1592
|
-
body: JSON.stringify({
|
|
1593
|
-
code,
|
|
1594
|
-
redirectUri
|
|
1595
|
-
}),
|
|
1596
|
-
credentials: 'include',
|
|
1597
|
-
headers: {
|
|
1598
|
-
Accept: 'application/json',
|
|
1599
|
-
'Content-Type': 'application/json'
|
|
1600
|
-
},
|
|
1601
|
-
method: 'POST'
|
|
1602
|
-
});
|
|
1603
|
-
if (!response.ok) {
|
|
1604
|
-
throw new Error(await getExchangeErrorMessage(response));
|
|
1605
|
-
}
|
|
1606
|
-
};
|
|
1607
|
-
|
|
1608
1696
|
const hasAuthorizationCode = value => {
|
|
1609
1697
|
return typeof value === 'string' && value.length > 0;
|
|
1610
1698
|
};
|
|
1611
|
-
const
|
|
1612
|
-
|
|
1613
|
-
|
|
1699
|
+
const getElectronAuthorizationCode = async uid => {
|
|
1700
|
+
return invoke$2('OAuthServer.getCode', String(uid));
|
|
1701
|
+
};
|
|
1702
|
+
const waitForElectronBackendLogin = async (uid, codeVerifier, timeoutMs = 30_000, pollIntervalMs = 1000, getAuthorizationCode = getElectronAuthorizationCode) => {
|
|
1703
|
+
const deadline = Date.now() + timeoutMs;
|
|
1614
1704
|
while (Date.now() < deadline) {
|
|
1615
|
-
const authorizationCode = await
|
|
1705
|
+
const authorizationCode = await getAuthorizationCode(uid);
|
|
1616
1706
|
if (hasAuthorizationCode(authorizationCode)) {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1707
|
+
return {
|
|
1708
|
+
authCode: authorizationCode,
|
|
1709
|
+
authCodeVerifier: codeVerifier,
|
|
1710
|
+
authErrorMessage: '',
|
|
1711
|
+
userState: 'loggedOut'
|
|
1712
|
+
};
|
|
1621
1713
|
}
|
|
1622
1714
|
await delay(pollIntervalMs);
|
|
1623
1715
|
}
|
|
@@ -1659,11 +1751,11 @@ const handleClickLogin = async options => {
|
|
|
1659
1751
|
}
|
|
1660
1752
|
const uid = 0;
|
|
1661
1753
|
const {
|
|
1662
|
-
|
|
1663
|
-
|
|
1754
|
+
codeVerifier,
|
|
1755
|
+
loginUrl
|
|
1664
1756
|
} = await getBackendLoginRequest(backendUrl, platform, uid);
|
|
1665
1757
|
await invoke$1('Open.openUrl', loginUrl, platform, authUseRedirect);
|
|
1666
|
-
const authState = platform === Electron ? await waitForElectronBackendLogin(
|
|
1758
|
+
const authState = platform === Electron ? await waitForElectronBackendLogin(uid, codeVerifier) : await waitForBackendLogin(backendUrl);
|
|
1667
1759
|
return {
|
|
1668
1760
|
...authState
|
|
1669
1761
|
};
|
|
@@ -1701,14 +1793,13 @@ const commandMap = {
|
|
|
1701
1793
|
'Auth.setNextRefreshResponse': setNextRefreshResponse,
|
|
1702
1794
|
'Auth.syncBackendAuth': syncBackendAuth,
|
|
1703
1795
|
'HandleMessagePort.handleMessagePort': handleMessagePort,
|
|
1704
|
-
initialize: (_, port) => handleMessagePort(port)
|
|
1796
|
+
initialize: (_, port) => handleMessagePort(port, RendererWorker)
|
|
1705
1797
|
};
|
|
1706
1798
|
|
|
1707
1799
|
const initializeRendererWorker = async () => {
|
|
1708
|
-
|
|
1800
|
+
await create$1({
|
|
1709
1801
|
commandMap: commandMap
|
|
1710
1802
|
});
|
|
1711
|
-
set(rpc);
|
|
1712
1803
|
};
|
|
1713
1804
|
|
|
1714
1805
|
const listen = async () => {
|