fix fetch, some refactor, still wip ms

This commit is contained in:
creeper123123321 2021-01-20 17:50:35 -03:00
parent 4d061a7efe
commit 05671b3da8
2 changed files with 120 additions and 95 deletions

View File

@ -20,31 +20,35 @@ var connectionStatus = document.getElementById("connection_status");
var content = document.getElementById("content");
var acounts = document.getElementById("accounts");
isSuccess = status => status >= 200 && status < 300;
function getCorsProxy() {
return localStorage.getItem("cors-proxy") || "http://localhost:8080/";
}
function loginMc() {
function loginMc(user, pass) {
var clientToken = uuid.v4();
fetch(getCorsProxy() + "https://authserver.mojang.com/authenticate", {method: "post",
body: JSON.stringify({
agent: {name: "Minecraft", version: 1},
username: $("#email").val(),
password: $("#password").val(),
username: user,
password: pass,
clientToken: clientToken,
}),
headers: {"content-type": "application/json"}
}).then((data) => {
if (data.status != 200) throw "not 200";
storeMcAccount(data.json().accessToken, data.json().clientToken, data.json().selectedProfile.name, data.json().selectedProfile.id);
}).catch(() => alert("Failed to login"));
if (!isSuccess(data.status)) throw "not success code";
return data.json();
}).then((data) => {
storeMcAccount(data.accessToken, data.clientToken, data.selectedProfile.name, data.selectedProfile.id);
}).catch((e) => alert("Failed to login: " + e));
$("#email").val("");
$("#password").val("");
}
function storeMcAccount(accessToken, clientToken, name, id) {
function storeMcAccount(accessToken, clientToken, name, id, msUser = null) {
let accounts = JSON.parse(localStorage.getItem("mc_accounts")) || [];
let account = {accessToken: accessToken, clientToken: clientToken, name: name, id: id};
let account = {accessToken: accessToken, clientToken: clientToken, name: name, id: id, msUser: msUser};
accounts.push(account);
localStorage.setItem("mc_accounts", JSON.stringify(accounts));
refreshAccountList();
@ -58,12 +62,15 @@ function removeMcAccount(id) {
refreshAccountList();
}
isMojang = it => !!it.clientToken;
isNotMojang = it => !it.clientToken;
function getMcAccounts() {
return JSON.parse(localStorage.getItem("mc_accounts")) || [];
}
function logout(id) {
getMcAccounts().filter(it => it.id == id).forEach(it => {
function logoutMojang(id) {
getMcAccounts().filter(isMojang).filter(it => it.id == id).forEach(it => {
fetch(getCorsProxy() + "https://authserver.mojang.com/invalidate", {method: "post",
body: JSON.stringify({
accessToken: it.accessToken,
@ -71,46 +78,30 @@ function logout(id) {
}),
headers: {"content-type": "application/json"},
}).then((data) => {
if (data.status != 200) throw "not 200";
if (isSuccess(data.status)) throw "not success code";
removeMcAccount(id);
}).catch(() => {
if (confirm("failed to invalidate token! remove account?")) {
}).catch((e) => {
if (confirm("failed to invalidate token! error: " + e + " remove account?")) {
removeMcAccount(id);
}
});
});
}
function addMcAccountToList(id, name) {
function addMcAccountToList(id, name, msUser = null) {
let p = document.createElement("p");
let head = document.createElement("img");
let n = document.createElement("span");
let remove = document.createElement("a");
n.innerText = " " + name + " ";
remove.innerText = "Remove";
remove.href = "#";
remove.onclick = () => {
logout(id);
};
head.className = "account_head";
head.alt = name + "'s head";
head.src = "https://crafthead.net/helm/" + id;
p.append(head);
p.append(n);
p.append(remove);
accounts.appendChild(p);
}
function addMsAccountToList(id, name, msUser) {
let p = document.createElement("p");
let head = document.createElement("img");
let n = document.createElement("span");
let remove = document.createElement("a");
n.innerText = " " + name + "(MS: " + msUser + ") ";
n.innerText = " " + name + " " + (msUser == null ? "" : "(" + msUser + ") ");
remove.innerText = "Logout";
remove.href = "#";
remove.onclick = () => {
signOut(msUser);
if (msUser == null) {
logoutMojang(id);
} else {
signOut(msUser);
}
};
head.className = "account_head";
head.alt = name + "'s head";
@ -123,38 +114,66 @@ function addMsAccountToList(id, name, msUser) {
function refreshAccountList() {
accounts.innerHTML = "";
getMcAccounts().forEach(it => addMcAccountToList(it.id, it.name));
(myMSALObj.getAllAccounts() || []).forEach(it => addMsAccountToList("TODO", "TODO", it.username))
getMcAccounts().filter(isMojang).forEach(it => addMcAccountToList(it.id, it.name));
(myMSALObj.getAllAccounts() || []).forEach(msAccount => {
let mcAcc = getMcAccounts().filter(isNotMojang).filter(it => it.msUser == msAccount.username)[0] || {};
addMcAccountToList(mcAcc.id || "d3c47f6f-ae3a-45c1-ad7c-e2c762b03ae6", mcAcc.name || "[DEMO]", msAccount.username);
});
}
function refreshAccountIfNeeded(it) {
function validateToken(account) {
return fetch(getCorsProxy() + "https://authserver.mojang.com/validate", {method: "post",
body: JSON.stringify({
accessToken: account.accessToken,
clientToken: account.clientToken
}),
headers: {"content-type": "application/json"}
});
}
function joinGame(token, id, hash) {
return fetch(getCorsProxy() + "https://sessionserver.mojang.com/session/minecraft/join", {
method: "post",
body: JSON.stringify({
accessToken: token,
selectedProfile: id,
serverId: hash
}),
headers: {"content-type": "application/json"}
});
}
function getMcUserToken(account) {
return validateToken(account).then((data) => {
if (!isSuccess(data.status)) {
if (isMojang(account)) {
return refreshMojangAccount(account);
} else {
return refreshTokenMs(account.msUser);
}
}
return account;
}).catch((e) => {
alert("failed to refresh token! " + e);
});
}
function refreshMojangAccount(it) {
console.log("refreshing " + it.id);
return fetch(getCorsProxy() + "https://authserver.mojang.com/refresh", {
method: "post",
body: JSON.stringify({
accessToken: it.accessToken,
clientToken: it.clientToken
}),
headers: {"content-type": "application/json"}
}).then((data) => {
if (data.status != 200) {
console.log("refreshing " + it.id);
return fetch(getCorsProxy() + "https://authserver.mojang.com/refresh", {
method: "post",
body: JSON.stringify({
accessToken: it.accessToken,
clientToken: it.clientToken
}),
headers: {"content-type": "application/json"},
}).then(data => {
if (data.status != 200) throw "not 200 refresh";
console.log("refreshed " + data.selectedProfile.id);
removeMcAccount(data.selectedProfile.id);
const json = data.json();
return storeMcAccount(json.accessToken, json.clientToken, json.selectedProfile.name, json.selectedProfile.id);
});
}
return it;
}).catch(() => {
alert("failed to refresh token!");
headers: {"content-type": "application/json"},
}).then(data => {
if (!isSuccess(data.status)) throw "not success";
console.log("refreshed " + data.selectedProfile.id);
return data.json();
}).then((json) => {
removeMcAccount(data.selectedProfile.id);
return storeMcAccount(json.accessToken, json.clientToken, json.selectedProfile.name, json.selectedProfile.id);
});
}
@ -208,6 +227,7 @@ function showListenAccount() {
link.href = "#";
link.onclick = () => {
let user = prompt("Username (Minecraft.ID is case-sensitive): ", "");
if (!user) return;
let callbackUrl = new URL(location.origin + location.pathname + "#username=" + encodeURIComponent(user));
location = "https://api.minecraft.id/gateway/start/" + encodeURIComponent(user) + "?callback=" + encodeURIComponent(callbackUrl);
};
@ -238,22 +258,14 @@ function onSocketMsg(event) {
if (confirm("Allow auth impersonation from VIAaaS instance? info: " + JSON.stringify(parsed))) {
let account = getMcAccounts().reverse().find(it => it.name.toLowerCase() == parsed.user.toLowerCase());
if (account) {
refreshAccountIfNeeded(account).then((data) => {
return fetch(getCorsProxy() + "https://sessionserver.mojang.com/session/minecraft/join", {
method: "post",
body: JSON.stringify({
accessToken: data.accessToken,
selectedProfile: data.id,
serverId: parsed.session_hash
}),
headers: {"content-type": "application/json"}
});
getMcUserToken(account).then((data) => {
return joinGame(data.accessToken, data.id,parsed.session_hash);
}).then((data) => {
if (data.status != 200) throw "not 200";
if (!isSuccess(data.status)) throw "not success join";
}).finally(() => confirmJoin(parsed.session_hash))
.catch((e) => {
confirmJoin(parsed.session_hash);
alert("Couldn't contact session server for " + parsed.user + " account in browser.");
alert("Couldn't contact session server for " + parsed.user + " account in browser. error: " + e);
});
} else {
alert("Couldn't find " + parsed.user + " account in browser.");
@ -295,7 +307,7 @@ function connect() {
$(() => {
$("#cors-proxy").on("change", () => localStorage.setItem('cors-proxy', $("#cors-proxy").val()));
$("#cors-proxy").val(getCorsProxy());
$("#login_submit_mc").on("click", loginMc);
$("#login_submit_mc").on("click", () => loginMc($("#email").val(), $("#password").val()));
$("#login_submit_ms").on("click", loginMs);
refreshAccountList();

View File

@ -3,7 +3,6 @@
const redirectUrl = location.origin == "https://localhost:25543" ?
"https://localhost:25543/auth.html" : "https://viaversion.github.io/VIAaaS/src/main/resources/web/auth.html";
// Config object to be passed to Msal on creation
const msalConfig = {
auth: {
clientId: "a370fff9-7648-4dbf-b96e-2b4f8d539ac2",
@ -11,14 +10,13 @@ const msalConfig = {
redirectUri: redirectUrl,
},
cache: {
cacheLocation: "sessionStorage", // This configures where your cache will be stored
storeAuthStateInCookie: false, // Set this to "true" if you are having issues on IE11 or Edge
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
}
};
const myMSALObj = new msal.PublicClientApplication(msalConfig);
// Add scopes for the id token to be used at Microsoft identity platform endpoints.
const loginRequest = {
scopes: ["XboxLive.signin"]
};
@ -27,34 +25,49 @@ function loginMs() {
myMSALObj.loginRedirect(loginRequest);
}
$(() => myMSALObj.handleRedirectPromise().then(() => refreshAccountList()));
$(() => myMSALObj.handleRedirectPromise().then((resp) => {
if (resp) {
refreshTokenMs(resp.account.username).catch(e => alert("failed to get mc token: " + e));
refreshAccountList();
}
}));
function getMcToken(username) {
function refreshTokenMs(username) {
return getTokenPopup(username, loginRequest)
.then((response) => {
.then(response => {
// this supports CORS
return fetch("https://user.auth.xboxlive.com/user/authenticate", {method: "post",
body: JSON.stringify({"Properties": {"AuthMethod": "RPS", "SiteName": "user.auth.xboxlive.com",
"RpsTicket": "d=" + response.accessToken}, "RelyingParty": "http://auth.xboxlive.com", "TokenType": "JWT"}),
body: JSON.stringify({Properties: {AuthMethod: "RPS", SiteName: "user.auth.xboxlive.com",
RpsTicket: "d=" + response.accessToken}, RelyingParty: "http://auth.xboxlive.com", TokenType: "JWT"}),
headers: {"content-type": "application/json"}});
}).then(xboxResponse => {
if (xboxResponse.status != 200) throw "xbox response not 200";
// We need CORS proxy
if (isSuccess(xboxResponse.status)) throw "xbox response not success";
return xboxResponse.json();
}).then(json => {
return fetch(getCorsProxy() + "https://xsts.auth.xboxlive.com/xsts/authorize", {method: "post",
body: JSON.stringify({"Properties": {"SandboxId": "RETAIL", "UserTokens": [xboxResponse.json().Token]},
"RelyingParty": "rp://api.minecraftservices.com/", "TokenType": "JWT"}),
body: JSON.stringify({Properties: {SandboxId: "RETAIL", UserTokens: [json.Token]},
RelyingParty: "rp://api.minecraftservices.com/", TokenType: "JWT"}),
headers: {"content-type": "application/json"}});
}).then(xstsResponse => {
if (xstsResponse.status != 200) throw "xsts response not 200";
// Need CORS proxy here too
return fetch(getCorsProxy() + "https://api.minecraftservices.com/authentication/login_with_xbox", {
body: JSON.stringify({"identityToken": "XBL3.0 x=" + xstsResponse.json().DisplayClaims.xui.uhs + ";"
+ xstsResponse.json().Token}), headers: {"content-type": "application/json"}});
if (isSuccess(xstsResponse.status)) throw "xsts response not success";
return xstsResponse.json();
}).then(json => {
return fetch(getCorsProxy() + "https://api.minecraftservices.com/authentication/login_with_xbox", {method: "post",
body: JSON.stringify({identityToken: "XBL3.0 x=" + json.DisplayClaims.xui.uhs + ";" + json.Token}),
headers: {"content-type": "application/json"}});
}).then(mcResponse => {
if (mcResponse.status != 200) throw "mc response not 200";
if (isSuccess(mcResponse.status)) throw "mc response not success";
return mcResponse.json();
}).catch(error => {
console.log(error);
}).then(json => {
fetch(getCorsProxy() + "https://api.minecraftservices.com/minecraft/profile", {
method: "get", headers: {"content-type": "application/json", "authorization": "Bearer " + json.access_token}}).then(profile => {
if (profile.status == 404) throw "no profile";
if (isSuccess(profile.status)) throw "profile response not success";
return profile.json();
}).then(jsonProfile => {
removeMcAccount(jsonProfile.id);
return storeMcAccount(json.access_token, null, jsonProfile.name, jsonProfile.id, username);
});
});
}