Last active
February 4, 2021 09:01
-
-
Save astra137/4784ed9748429b01bf28414f9b90ca9c to your computer and use it in GitHub Desktop.
Demo process for getting Minecraft access token with Microsoft Account
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Experiments based on: | |
// https://github.com/PrismarineJS/node-minecraft-protocol/blob/master/src/client/microsoftAuth.js | |
const {createServer} = require('http'); | |
const {URL} = require('url'); | |
const fetch = require('node-fetch'); | |
const msal = require('@azure/msal-node'); | |
const XboxLiveAuth = require('@xboxreplay/xboxlive-auth'); | |
const prettyMilliseconds = require('pretty-ms'); | |
const XSTSRelyingParty = 'rp://api.minecraftservices.com/'; | |
const URL_LOGIN_XBOX = 'https://api.minecraftservices.com/authentication/login_with_xbox'; | |
const URL_MC_PROFILE = 'https://api.minecraftservices.com/minecraft/profile'; | |
const USER_AGENT = 'starburn/minecraft-auth-test'; | |
const scopes = ['XboxLive.signin', 'offline_access']; | |
const pca = new msal.PublicClientApplication({ | |
auth: { | |
clientId: 'PUT AZURE APP REGISTRATION Application (client) UUID HERE', | |
authority: 'https://login.microsoftonline.com/consumers' | |
} | |
}); | |
async function getAuthorizationTokenWithLocalhost(onURL) { | |
const requestUrl = await new Promise((resolve, reject) => { | |
let port; | |
const server = createServer((request, response) => { | |
resolve(new URL(request.url, `http://localhost:${port}`)); | |
response.setHeader('Location', 'https://minecraft.net'); | |
response.writeHead(303); | |
response.end(); | |
server.close(); | |
}); | |
server.listen(null, '127.0.0.1', () => { | |
port = server.address().port; | |
pca.getAuthCodeUrl({ | |
redirectUri: `http://localhost:${port}`, | |
scopes | |
}) | |
.then(onURL) | |
.catch(reject); | |
}); | |
}); | |
return pca.acquireTokenByCode({ | |
code: requestUrl.searchParams.get('code'), | |
redirectUri: requestUrl.origin, | |
scopes | |
}); | |
} | |
Promise.resolve() | |
.then(async () => { | |
// Probably cache all of these tokens, like minecraft-protocol does | |
// alternatively use pca.acquireTokenByDeviceCode() | |
// for acquisition of microsoft account auth | |
// https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-common/docs/request.md | |
const msaAccessToken = await getAuthorizationTokenWithLocalhost(console.log); | |
console.log('msaAccessToken'); | |
console.log(msaAccessToken.account.username); | |
console.log('expiresOn', prettyMilliseconds(new Date(msaAccessToken.expiresOn) - Date.now())); | |
console.log(''); | |
const xblUserToken = await XboxLiveAuth.exchangeRpsTicketForUserToken('d=' + msaAccessToken.accessToken); | |
console.log('xblUserToken'); | |
console.log('NotAfter', prettyMilliseconds(new Date(xblUserToken.NotAfter) - Date.now())); | |
console.log(''); | |
const xsts = await XboxLiveAuth.exchangeUserTokenForXSTSIdentity( | |
xblUserToken.Token, {XSTSRelyingParty, raw: false} | |
); | |
console.log('xsts'); | |
console.log('expiresOn', prettyMilliseconds(new Date(xsts.expiresOn) - Date.now())); | |
console.log(''); | |
const mcaResponse = await fetch(URL_LOGIN_XBOX, { | |
method: 'post', | |
headers: { | |
'Content-Type': 'application/json', | |
'User-Agent': USER_AGENT | |
}, | |
body: JSON.stringify({identityToken: `XBL3.0 x=${xsts.userHash};${xsts.XSTSToken}`}) | |
}); | |
const mca = await mcaResponse.json(); | |
console.log('mca'); | |
console.log(mca.username); | |
console.log(prettyMilliseconds(mca.expires_in * 1000)); | |
console.log(''); | |
const profileResponse = await fetch(URL_MC_PROFILE, { | |
headers: { | |
'Content-Type': 'application/json', | |
'User-Agent': USER_AGENT, | |
Authorization: `Bearer ${mca.access_token}` | |
} | |
}); | |
const profile = await profileResponse.json(); | |
console.log('profile'); | |
console.log(profile.name); | |
console.log(''); | |
}) | |
.catch(console.error); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment