mirror of
https://github.com/WorldEditAxe/eaglerproxy.git
synced 2024-12-21 23:04:13 -08:00
Online mode fix & npm package updates
This commit is contained in:
parent
67c3e0bbda
commit
375a275442
910
package-lock.json
generated
910
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
33
package.json
33
package.json
|
@ -9,22 +9,23 @@
|
||||||
"author": "WorldEditAxe, q13x",
|
"author": "WorldEditAxe, q13x",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@thi.ng/leb128": "^3.0.5",
|
"@thi.ng/leb128": "3.0.5",
|
||||||
"@types/node": "^18.11.18",
|
"@types/node": "18.11.18",
|
||||||
"@types/semver": "^7.3.13",
|
"@types/semver": "7.3.13",
|
||||||
"@types/sharp": "^0.31.1",
|
"@types/sharp": "0.31.1",
|
||||||
"@types/ws": "^8.5.4",
|
"@types/ws": "8.5.4",
|
||||||
"chalk": "^5.2.0",
|
"chalk": "5.2.0",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "16.0.3",
|
||||||
"minecraft-protocol": "^1.40.2",
|
"minecraft-protocol": "^1.26.5",
|
||||||
"node-fetch": "^3.3.1",
|
"node-fetch": "3.3.1",
|
||||||
"parse-domain": "^7.0.1",
|
"parse-domain": "7.0.1",
|
||||||
"prismarine-block": "^1.16.3",
|
"prismarine-auth": "^2.4.1",
|
||||||
"prismarine-chunk": "^1.33.0",
|
"prismarine-block": "1.16.3",
|
||||||
"prismarine-registry": "^1.6.0",
|
"prismarine-chunk": "1.33.0",
|
||||||
"semver": "^7.3.8",
|
"prismarine-registry": "1.6.0",
|
||||||
"sharp": "^0.31.3",
|
"semver": "^7.6.0",
|
||||||
"ws": "^8.12.0"
|
"sharp": "^0.33.2",
|
||||||
|
"ws": "8.12.0"
|
||||||
},
|
},
|
||||||
"type": "module"
|
"type": "module"
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,41 +12,23 @@ import XboxTokenManager from "prismarine-auth/src/TokenManagers/XboxTokenManager
|
||||||
import MsaTokenManager from "prismarine-auth/src/TokenManagers/MsaTokenManager.js";
|
import MsaTokenManager from "prismarine-auth/src/TokenManagers/MsaTokenManager.js";
|
||||||
import BedrockTokenManager from "prismarine-auth/src/TokenManagers/MinecraftBedrockTokenManager.js";
|
import BedrockTokenManager from "prismarine-auth/src/TokenManagers/MinecraftBedrockTokenManager.js";
|
||||||
|
|
||||||
/*
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2020 PrismarineJS
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
async function retry(methodFn, beforeRetry, times) {
|
async function retry(methodFn, beforeRetry, times) {
|
||||||
for (let attempts = 0; attempts < times; attempts++) {
|
while (times--) {
|
||||||
try {
|
if (times !== 0) {
|
||||||
return await methodFn();
|
try {
|
||||||
} catch (err) {
|
return await methodFn();
|
||||||
if (err instanceof URIError) {
|
} catch (e) {
|
||||||
throw err;
|
if (e instanceof URIError) {
|
||||||
|
throw e;
|
||||||
|
} else {
|
||||||
|
// debug(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||||
|
await beforeRetry();
|
||||||
|
} else {
|
||||||
|
return await methodFn();
|
||||||
}
|
}
|
||||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
|
||||||
await beforeRetry();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +45,7 @@ export class CustomAuthflow {
|
||||||
constructor(username = "", cache, options, codeCallback) {
|
constructor(username = "", cache, options, codeCallback) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
if (options && !options.flow) {
|
if (options && !options.flow) {
|
||||||
throw new Error(
|
throw new Error("Missing 'flow' argument in options. See docs for more information.");
|
||||||
"Missing 'flow' argument in options. See docs for more information."
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
this.options = options || { flow: "msal" };
|
this.options = options || { flow: "msal" };
|
||||||
this.initTokenManagers(username, cache);
|
this.initTokenManagers(username, cache);
|
||||||
|
@ -74,48 +54,32 @@ export class CustomAuthflow {
|
||||||
|
|
||||||
initTokenManagers(username, cache) {
|
initTokenManagers(username, cache) {
|
||||||
if (this.options.flow === "live" || this.options.flow === "sisu") {
|
if (this.options.flow === "live" || this.options.flow === "sisu") {
|
||||||
if (!this.options.authTitle)
|
if (!this.options.authTitle) throw new Error(`Please specify an "authTitle" in Authflow constructor when using ${this.options.flow} flow`);
|
||||||
throw new Error(
|
this.msa = new LiveTokenManager(this.options.authTitle, ["service::user.auth.xboxlive.com::MBI_SSL"], cache({ cacheName: this.options.flow, username }));
|
||||||
`Please specify an "authTitle" in Authflow constructor when using ${this.options.flow} flow`
|
|
||||||
);
|
|
||||||
this.msa = new LiveTokenManager(
|
|
||||||
this.options.authTitle,
|
|
||||||
["service::user.auth.xboxlive.com::MBI_SSL"],
|
|
||||||
cache({ cacheName: this.options.flow, username })
|
|
||||||
);
|
|
||||||
this.doTitleAuth = true;
|
this.doTitleAuth = true;
|
||||||
} else if (this.options.flow === "msal") {
|
} else if (this.options.flow === "msal") {
|
||||||
const config = Object.assign(
|
const config = Object.assign({ ...msalConfig }, this.options.authTitle ? { auth: { ...msalConfig.auth, clientId: this.options.authTitle } } : {});
|
||||||
{ ...msalConfig },
|
this.msa = new MsaTokenManager(config, ["XboxLive.signin", "offline_access"], cache({ cacheName: "msal", username }));
|
||||||
this.options.authTitle
|
|
||||||
? { auth: { ...msalConfig.auth, clientId: this.options.authTitle } }
|
|
||||||
: {}
|
|
||||||
);
|
|
||||||
this.msa = new MsaTokenManager(
|
|
||||||
config,
|
|
||||||
["XboxLive.signin", "offline_access"],
|
|
||||||
cache({ cacheName: "msal", username })
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error(
|
throw new Error(`Unknown flow: ${this.options.flow} (expected "live", "sisu", or "msal")`);
|
||||||
`Unknown flow: ${this.options.flow} (expected "live", "sisu", or "msal")`
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const keyPair = crypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
|
const keyPair = crypto.generateKeyPairSync("ec", { namedCurve: "P-256" });
|
||||||
this.xbl = new XboxTokenManager(
|
this.xbl = new XboxTokenManager(keyPair, cache({ cacheName: "xbl", username }));
|
||||||
keyPair,
|
|
||||||
cache({ cacheName: "xbl", username })
|
|
||||||
);
|
|
||||||
this.mba = new BedrockTokenManager(cache({ cacheName: "bed", username }));
|
this.mba = new BedrockTokenManager(cache({ cacheName: "bed", username }));
|
||||||
this.mca = new JavaTokenManager(cache({ cacheName: "mca", username }));
|
this.mca = new JavaTokenManager(cache({ cacheName: "mca", username }));
|
||||||
}
|
}
|
||||||
|
|
||||||
static resetTokenCaches(cache) {
|
static resetTokenCaches(cache) {
|
||||||
if (!cache) throw new Error("You must provide a cache directory to reset.");
|
if (!cache) throw new Error("You must provide a cache directory to reset.");
|
||||||
if (fs.existsSync(cache)) {
|
try {
|
||||||
fs.rmSync(cache, { recursive: true });
|
if (fs.existsSync(cache)) {
|
||||||
return true;
|
fs.rmSync(cache, { recursive: true });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Failed to clear cache dir", e);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,70 +94,58 @@ export class CustomAuthflow {
|
||||||
console.info(response.message);
|
console.info(response.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (ret.account) {
|
||||||
|
console.info(`[msa] Signed in as ${ret.account.username}`);
|
||||||
|
} else {
|
||||||
|
// We don't get extra account data here per scope
|
||||||
|
console.info("[msa] Signed in with Microsoft");
|
||||||
|
}
|
||||||
|
|
||||||
return ret.accessToken;
|
return ret.accessToken;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getXboxToken(
|
async getXboxToken(relyingParty = this.options.relyingParty || Endpoints.XboxRelyingParty, forceRefresh = false) {
|
||||||
relyingParty = this.options.relyingParty || Endpoints.XboxRelyingParty
|
|
||||||
) {
|
|
||||||
const options = { ...this.options, relyingParty };
|
const options = { ...this.options, relyingParty };
|
||||||
if (await this.xbl.verifyTokens(relyingParty)) {
|
|
||||||
const { data } = await this.xbl.getCachedXstsToken(relyingParty);
|
|
||||||
return data;
|
|
||||||
} else if (options.password) {
|
|
||||||
const xsts = await this.xbl.doReplayAuth(
|
|
||||||
this.username,
|
|
||||||
options.password,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
return xsts;
|
|
||||||
} else {
|
|
||||||
return await retry(
|
|
||||||
async () => {
|
|
||||||
const msaToken = await this.getMsaToken();
|
|
||||||
|
|
||||||
if (options.flow === "sisu") {
|
const { xstsToken, userToken, deviceToken, titleToken } = await this.xbl.getCachedTokens(relyingParty);
|
||||||
const deviceToken = await this.xbl.getDeviceToken(options);
|
|
||||||
const sisu = await this.xbl.doSisuAuth(
|
|
||||||
msaToken,
|
|
||||||
deviceToken,
|
|
||||||
options
|
|
||||||
);
|
|
||||||
return sisu;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userToken = await this.xbl.getUserToken(
|
if (xstsToken.valid && !forceRefresh) {
|
||||||
msaToken,
|
return xstsToken.data;
|
||||||
options.flow === "msal"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.doTitleAuth) {
|
|
||||||
const deviceToken = await this.xbl.getDeviceToken(options);
|
|
||||||
const titleToken = await this.xbl.getTitleToken(
|
|
||||||
msaToken,
|
|
||||||
deviceToken
|
|
||||||
);
|
|
||||||
const xsts = await this.xbl.getXSTSToken(
|
|
||||||
{ userToken, deviceToken, titleToken },
|
|
||||||
options
|
|
||||||
);
|
|
||||||
return xsts;
|
|
||||||
} else {
|
|
||||||
const xsts = await this.xbl.getXSTSToken({ userToken }, options);
|
|
||||||
return xsts;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
this.msa.forceRefresh = true;
|
|
||||||
},
|
|
||||||
2
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.password) {
|
||||||
|
const xsts = await this.xbl.doReplayAuth(this.username, options.password, options);
|
||||||
|
return xsts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await retry(
|
||||||
|
async () => {
|
||||||
|
const msaToken = await this.getMsaToken();
|
||||||
|
|
||||||
|
// sisu flow generates user and title tokens differently to other flows and should also be used to refresh them if they are invalid
|
||||||
|
if (options.flow === "sisu" && (!userToken.valid || !deviceToken.valid || !titleToken.valid)) {
|
||||||
|
const dt = await this.xbl.getDeviceToken(options);
|
||||||
|
const sisu = await this.xbl.doSisuAuth(msaToken, dt, options);
|
||||||
|
return sisu;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ut = userToken.token ?? (await this.xbl.getUserToken(msaToken, options.flow === "msal"));
|
||||||
|
const dt = deviceToken.token ?? (await this.xbl.getDeviceToken(options));
|
||||||
|
const tt = titleToken.token ?? (this.doTitleAuth ? await this.xbl.getTitleToken(msaToken, dt) : undefined);
|
||||||
|
|
||||||
|
const xsts = await this.xbl.getXSTSToken({ userToken: ut, deviceToken: dt, titleToken: tt }, options);
|
||||||
|
return xsts;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.msa.forceRefresh = true;
|
||||||
|
},
|
||||||
|
2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMinecraftJavaToken(options: any = {}) {
|
async getMinecraftJavaToken(options: any = {}) {
|
||||||
const response: any = { token: "", entitlements: {}, profile: {} };
|
const response: any = { token: "", entitlements: {} as any, profile: {} as any };
|
||||||
if (await this.mca.verifyTokens()) {
|
if (await this.mca.verifyTokens()) {
|
||||||
const { token } = await this.mca.getCachedAccessToken();
|
const { token } = await this.mca.getCachedAccessToken();
|
||||||
response.token = token;
|
response.token = token;
|
||||||
|
@ -211,15 +163,43 @@ export class CustomAuthflow {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.fetchEntitlements) {
|
if (options.fetchEntitlements) {
|
||||||
response.entitlements = await this.mca.fetchEntitlements(response.token);
|
response.entitlements = await this.mca.fetchEntitlements(response.token).catch((e) => {});
|
||||||
}
|
}
|
||||||
if (options.fetchProfile) {
|
if (options.fetchProfile) {
|
||||||
response.profile = await this.mca.fetchProfile(response.token);
|
response.profile = await this.mca.fetchProfile(response.token).catch((e) => {});
|
||||||
}
|
}
|
||||||
if (options.fetchCertificates) {
|
if (options.fetchCertificates) {
|
||||||
response.certificates = await this.mca.fetchCertificates(response.token);
|
response.certificates = await this.mca.fetchCertificates(response.token).catch((e) => []);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getMinecraftBedrockToken(publicKey) {
|
||||||
|
// TODO: Fix cache, in order to do cache we also need to cache the ECDH keys so disable it
|
||||||
|
// is this even a good idea to cache?
|
||||||
|
if ((await this.mba.verifyTokens()) && false) {
|
||||||
|
// eslint-disable-line
|
||||||
|
const { chain } = this.mba.getCachedAccessToken();
|
||||||
|
return chain;
|
||||||
|
} else {
|
||||||
|
if (!publicKey) throw new Error("Need to specifiy a ECDH x509 URL encoded public key");
|
||||||
|
return await retry(
|
||||||
|
async () => {
|
||||||
|
const xsts = await this.getXboxToken(Endpoints.BedrockXSTSRelyingParty);
|
||||||
|
const token = await this.mba.getAccessToken(publicKey, xsts);
|
||||||
|
// If we want to auth with a title ID, make sure there's a TitleID in the response
|
||||||
|
const body = JSON.parse(Buffer.from(token.chain[1].split(".")[1], "base64").toString());
|
||||||
|
if (!body.extraData.titleId && this.doTitleAuth) {
|
||||||
|
throw Error("missing titleId in response");
|
||||||
|
}
|
||||||
|
return token.chain;
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.xbl.forceRefresh = true;
|
||||||
|
},
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user