aboutsummaryrefslogtreecommitdiff
path: root/mcsh.sh
diff options
context:
space:
mode:
Diffstat (limited to 'mcsh.sh')
-rwxr-xr-xmcsh.sh91
1 files changed, 90 insertions, 1 deletions
diff --git a/mcsh.sh b/mcsh.sh
index d3e57cb..5a41cbb 100755
--- a/mcsh.sh
+++ b/mcsh.sh
@@ -8,6 +8,92 @@ NATIVES_DIR="natives"
ASSETS_DIR="assets"
GAME_DIR="run"
+function auth (
+ CLIENT_ID="9e97542c-b7d5-4a02-a656-4559dad4590a"
+ DEVICE_CODE_URL="https://login.microsoftonline.com/consumers/oauth2/v2.0/devicecode"
+ TOKEN_URL="https://login.microsoftonline.com/consumers/oauth2/v2.0/token"
+ XBL_AUTH_URL="https://user.auth.xboxlive.com/user/authenticate"
+ XSTS_TOKEN_URL="https://xsts.auth.xboxlive.com/xsts/authorize"
+ MC_AUTH_URL="https://api.minecraftservices.com/authentication/login_with_xbox"
+
+ function login (
+ printf 'getting device code\n' >&2
+ res="$(curl -s -X POST "$DEVICE_CODE_URL" -H 'Content-Type: application/x-www-form-urlencoded' -d "client_id=$CLIENT_ID&scope=XboxLive.signin%20offline_access")"
+ device_code="$(<<<"$res" jq -r '.device_code')"
+ message="$(<<<"$res" jq -r '.message')"
+
+ printf '%s\n' "$message" >&2
+
+ printf 'waiting for token...\n' >&2
+ pending=true
+ while [[ "$pending" == true ]]; do
+ res="$(curl -s -X POST "$TOKEN_URL" -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=urn:ietf:params:oauth:grant-type:device_code&client_id=$CLIENT_ID&device_code=$device_code")"
+ pending="$(<<<"$res" jq -r '.error == "authorization_pending"')"
+ sleep 1
+ done
+
+ printf '%s\n' "$res"
+ )
+
+ if [[ -z "$(jq -r '.refresh_token // ""' auth.json)" ]]; then
+ printf 'logging in\n' >&2
+ res="$(login)"
+ else
+ printf 'refreshing msa auth\n' >&2
+ refresh_token="$(jq -r '.refresh_token' auth.json)"
+ res="$(curl -s -X POST "$TOKEN_URL" -H 'Content-Type: application/x-www-form-urlencoded' -d "grant_type=refresh_token&client_id=$CLIENT_ID&refresh_token=$refresh_token")"
+ fi
+
+ refresh_token="$(<<<"$res" jq -r '.refresh_token')"
+ msa_token="$(<<<"$res" jq -r '.access_token')"
+
+ auth="$(jq --arg token "$refresh_token" '. + {"refresh_token": $token}' auth.json)"
+ <<<"$auth" cat > auth.json
+
+ printf 'authenticating with xbox live\n' >&2
+ req="$(jq -n --arg token "$msa_token" '{"Properties": {"AuthMethod": "RPS", "SiteName": "user.auth.xboxlive.com", "RpsTicket": "d=\($token)"}, "RelyingParty": "http://auth.xboxlive.com", "TokenType": "JWT"}')"
+ res="$(curl -s -X POST "$XBL_AUTH_URL" -H 'Content-Type: application/json' -H 'Accept: application/json' -d "$req")"
+ xuid="$(<<<"$res" jq -r '.DisplayClaims.xui[0].uhs')"
+ xbl_token="$(<<<"$res" jq -r '.Token')"
+
+ # not 100% sure this is *actually* the xuid, but the game doesnt seem to
+ # care, even if passed a nonsense value
+ auth="$(jq --arg xuid "$xuid" '. + {"xuid": $xuid}' auth.json)"
+ <<<"$auth" cat > auth.json
+
+ printf 'getting xsts token\n' >&2
+ req="$(jq -n --arg token "$xbl_token" '{"Properties": {"SandboxId": "RETAIL", "UserTokens": [ $token ]}, "RelyingParty": "rp://api.minecraftservices.com/", "TokenType": "JWT"}')"
+ res="$(curl -s -X POST "$XSTS_TOKEN_URL" -H 'Content-Type: application/json' -H 'Accept: application/json' -d "$req")"
+ xsts_token="$(<<<"$res" jq -r '.Token')"
+
+ printf 'authenticating with mincraft\n' >&2
+ req="$(jq -n --arg xuid "$xuid" --arg token "$xsts_token" '{"identityToken": "XBL3.0 x=\($xuid);\($token)"}')"
+ res="$(curl -s -X POST "$MC_AUTH_URL" -H 'Content-Type: application/json' -H 'Accept: application/json' -d "$req")"
+ mc_token="$(<<<"$res" jq -r '.access_token')"
+
+ auth="$(jq --arg token "$mc_token" '. + {"access_token": $token}' auth.json)"
+ <<<"$auth" cat > auth.json
+
+ printf '%s\n' "$mc_token"
+)
+
+function update_profile (
+ MC_PROFILE_URL="https://api.minecraftservices.com/minecraft/profile"
+
+ token="$1"
+
+ printf 'getting minecraft profile\n' >&2
+ res="$(curl -s -X GET "$MC_PROFILE_URL" -H "Authorization: Bearer $token")"
+ if [[ -n "$(<<<"$res" jq -r '.error // ""')" ]]; then
+ printf 'error: user does not own minecraft\n' >&2
+ exit 1
+ fi
+
+ #TODO: hyphenate uuid, for :sparkles: style :sparkles:
+ auth="$(<<<"$res" jq --slurpfile auth auth.json '$auth[0] + {"player_name": .name, "uuid": .id}')"
+ <<<"$auth" cat > auth.json
+)
+
function update_metadata (
printf 'updating version manifest\n' >&2
mkdir -p "$VERSIONS_DIR"
@@ -29,6 +115,9 @@ function update_metadata (
)
function launch (
+ update_profile "$(auth)"
+ printf '\n' >&2
+
meta="$(update_metadata "${1:-}")"
export LIBRARIES_DIR
@@ -81,7 +170,7 @@ function launch (
-e "s/\${launcher_version}/v0.1.0/g"
}
- printf 'starting game :3\n' >&2
+ printf '\nstarting game :3\n\n' >&2
<<<"$meta" jq -r '.args.jvm + [.main_class] + .args.game | join(" ")' | replace_placeholders | xargs java
)