mirror of
https://github.com/PrismarineJS/node-minecraft-protocol.git
synced 2024-11-27 17:55:45 -05:00
Revert "Add token authentication (#780)"
This reverts commit 0277091ddc
.
This commits introduced a bug in offline mode.
We don't know yet how to fix it, so better revert first and fix later
This commit is contained in:
parent
7be60af77d
commit
14c4886ac4
4 changed files with 11 additions and 130 deletions
|
@ -74,7 +74,7 @@ Returns a `Client` instance and perform login.
|
||||||
`options` is an object containing the properties :
|
`options` is an object containing the properties :
|
||||||
* username
|
* username
|
||||||
* port : default to 25565
|
* port : default to 25565
|
||||||
* password : can be omitted (if the tokens and profilesFolder are also omitted then it tries to connect in offline mode)
|
* password : can be omitted (if the tokens are also omitted then it tries to connect in offline mode)
|
||||||
* host : default to localhost
|
* host : default to localhost
|
||||||
* clientToken : generated if a password is given
|
* clientToken : generated if a password is given
|
||||||
* accessToken : generated if a password is given
|
* accessToken : generated if a password is given
|
||||||
|
@ -92,7 +92,6 @@ Returns a `Client` instance and perform login.
|
||||||
* connect : a function taking the client as parameter and that should client.setSocket(socket)
|
* connect : a function taking the client as parameter and that should client.setSocket(socket)
|
||||||
and client.emit('connect') when appropriate (see the proxy examples for an example of use)
|
and client.emit('connect') when appropriate (see the proxy examples for an example of use)
|
||||||
* agent : a http agent that can be used to set proxy settings for yggdrasil authentication (see proxy-agent on npm)
|
* agent : a http agent that can be used to set proxy settings for yggdrasil authentication (see proxy-agent on npm)
|
||||||
* profilesFolder : the path to the folder that contains your `launcher_profiles.json`. defaults to your minecraft folder if it exists, otherwise the local directory. set to `false` to disable managing profiles
|
|
||||||
|
|
||||||
## mc.Client(isServer,version,[customPackets])
|
## mc.Client(isServer,version,[customPackets])
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,15 @@
|
||||||
const mc = require('minecraft-protocol')
|
const mc = require('minecraft-protocol')
|
||||||
|
|
||||||
if (process.argv.length !== 4) {
|
if (process.argv.length < 4 || process.argv.length > 6) {
|
||||||
console.log('Usage : node echo.js <host> <port> [<name>]')
|
console.log('Usage : node echo.js <host> <port> [<name>] [<password>]')
|
||||||
process.exit(1)
|
process.exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
const client = mc.createClient({
|
const client = mc.createClient({
|
||||||
host: process.argv[2],
|
host: process.argv[2],
|
||||||
port: parseInt(process.argv[3]),
|
port: parseInt(process.argv[3]),
|
||||||
username: process.argv[4] ? process.argv[4] : 'echo'
|
username: process.argv[4] ? process.argv[4] : 'echo',
|
||||||
})
|
password: process.argv[5]
|
||||||
client.on('error', function (err) {
|
|
||||||
console.error(err)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
client.on('connect', function () {
|
client.on('connect', function () {
|
||||||
|
|
|
@ -44,18 +44,17 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aes-js": "^3.1.2",
|
"aes-js": "^3.1.2",
|
||||||
|
"yggdrasil": "^1.3.0",
|
||||||
"buffer-equal": "^1.0.0",
|
"buffer-equal": "^1.0.0",
|
||||||
"debug": "^4.1.0",
|
"debug": "^4.1.0",
|
||||||
"endian-toggle": "^0.0.0",
|
"endian-toggle": "^0.0.0",
|
||||||
"lodash.get": "^4.1.2",
|
"lodash.get": "^4.1.2",
|
||||||
"lodash.merge": "^4.3.0",
|
"lodash.merge": "^4.3.0",
|
||||||
"minecraft-data": "^2.70.0",
|
"minecraft-data": "^2.70.0",
|
||||||
"minecraft-folder-path": "^1.1.0",
|
|
||||||
"node-rsa": "^0.4.2",
|
"node-rsa": "^0.4.2",
|
||||||
"prismarine-nbt": "^1.3.0",
|
"prismarine-nbt": "^1.3.0",
|
||||||
"protodef": "^1.8.0",
|
"protodef": "^1.8.0",
|
||||||
"readable-stream": "^3.0.6",
|
"readable-stream": "^3.0.6",
|
||||||
"uuid-1345": "^1.0.1",
|
"uuid-1345": "^1.0.1"
|
||||||
"yggdrasil": "^1.4.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,98 +1,16 @@
|
||||||
const UUID = require('uuid-1345')
|
const UUID = require('uuid-1345')
|
||||||
const yggdrasil = require('yggdrasil')
|
const yggdrasil = require('yggdrasil')
|
||||||
const fs = require('fs').promises
|
|
||||||
const mcDefaultFolderPath = require('minecraft-folder-path')
|
|
||||||
const path = require('path')
|
|
||||||
|
|
||||||
module.exports = async function (client, options) {
|
|
||||||
if (!options.profilesFolder && options.profilesFolder !== false) { // not defined, but not explicitly false. fallback to default
|
|
||||||
let mcFolderExists = true
|
|
||||||
try {
|
|
||||||
await fs.access(mcDefaultFolderPath)
|
|
||||||
} catch (ignoreErr) {
|
|
||||||
mcFolderExists = false
|
|
||||||
}
|
|
||||||
options.profilesFolder = mcFolderExists ? mcDefaultFolderPath : '.' // local folder if mc folder doesn't exist
|
|
||||||
}
|
|
||||||
|
|
||||||
|
module.exports = function (client, options) {
|
||||||
const yggdrasilClient = yggdrasil({ agent: options.agent, host: options.authServer || 'https://authserver.mojang.com' })
|
const yggdrasilClient = yggdrasil({ agent: options.agent, host: options.authServer || 'https://authserver.mojang.com' })
|
||||||
const clientToken = options.clientToken || (options.session && options.session.clientToken) || (options.profilesFolder && (await getLauncherProfiles()).clientToken) || UUID.v4().toString().replace(/-/g, '')
|
const clientToken = options.clientToken || (options.session && options.session.clientToken) || UUID.v4().toString()
|
||||||
const skipValidation = false || options.skipValidation
|
const skipValidation = false || options.skipValidation
|
||||||
options.accessToken = null
|
options.accessToken = null
|
||||||
options.haveCredentials = options.password != null || (clientToken != null && options.session != null) || (options.profilesFolder && await hasProfileCredentials())
|
options.haveCredentials = options.password != null || (clientToken != null && options.session != null)
|
||||||
|
|
||||||
async function getLauncherProfiles () { // get launcher profiles
|
|
||||||
try {
|
|
||||||
return JSON.parse(await fs.readFile(path.join(options.profilesFolder, 'launcher_profiles.json'), 'utf8'))
|
|
||||||
} catch (err) {
|
|
||||||
await fs.mkdir(options.profilesFolder, { recursive: true })
|
|
||||||
await fs.writeFile(path.join(options.profilesFolder, 'launcher_profiles.json'), '{}')
|
|
||||||
return { authenticationDatabase: {} }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function hasProfileCredentials () {
|
|
||||||
try {
|
|
||||||
const auths = await getLauncherProfiles()
|
|
||||||
|
|
||||||
const lowerUsername = options.username.toLowerCase()
|
|
||||||
return !!Object.keys(auths.authenticationDatabase).find(key =>
|
|
||||||
auths.authenticationDatabase[key].username.toLowerCase() === lowerUsername ||
|
|
||||||
Object.values(auths.authenticationDatabase[key].profiles)[0].displayName.toLowerCase() === lowerUsername
|
|
||||||
)
|
|
||||||
} catch (err) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.haveCredentials) {
|
if (options.haveCredentials) {
|
||||||
// make a request to get the case-correct username before connecting.
|
// make a request to get the case-correct username before connecting.
|
||||||
const cb = function (err, session) {
|
const cb = function (err, session) {
|
||||||
if (options.profilesFolder) {
|
|
||||||
getLauncherProfiles().then((auths) => {
|
|
||||||
try {
|
|
||||||
const lowerUsername = options.username.toLowerCase()
|
|
||||||
let profile = Object.keys(auths.authenticationDatabase).find(key =>
|
|
||||||
auths.authenticationDatabase[key].username.toLowerCase() === lowerUsername ||
|
|
||||||
Object.values(auths.authenticationDatabase[key].profiles)[0].displayName.toLowerCase() === lowerUsername
|
|
||||||
)
|
|
||||||
if (err) {
|
|
||||||
if (profile) { // profile is invalid, remove
|
|
||||||
delete auths.authenticationDatabase[profile]
|
|
||||||
}
|
|
||||||
} else { // successful login
|
|
||||||
if (!profile) {
|
|
||||||
profile = UUID.v4().toString().replace(/-/g, '') // create new profile
|
|
||||||
}
|
|
||||||
if (!auths.clientToken) {
|
|
||||||
auths.clientToken = clientToken
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientToken === auths.clientToken) { // only do something when we can save a new clienttoken or they match
|
|
||||||
const oldProfileObj = auths.authenticationDatabase[profile]
|
|
||||||
const newProfileObj = {
|
|
||||||
accessToken: session.accessToken,
|
|
||||||
profiles: {},
|
|
||||||
properties: oldProfileObj ? (oldProfileObj.properties || []) : [],
|
|
||||||
username: options.username
|
|
||||||
}
|
|
||||||
newProfileObj.profiles[session.selectedProfile.id] = {
|
|
||||||
displayName: session.selectedProfile.name
|
|
||||||
}
|
|
||||||
auths.authenticationDatabase[profile] = newProfileObj
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (ignoreErr) {
|
|
||||||
// again, silently fail, just don't save anything
|
|
||||||
}
|
|
||||||
fs.writeFile(path.join(options.profilesFolder, 'launcher_profiles.json'), JSON.stringify(auths, null, 2)).then(() => {}, (ignoreErr) => {
|
|
||||||
// console.warn("Couldn't save tokens:\n", err) // not any error, we just don't save the file
|
|
||||||
})
|
|
||||||
}, (ignoreErr) => {
|
|
||||||
// console.warn("Skipped saving tokens because of error\n", err) // not any error, we just don't save the file
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
client.emit('error', err)
|
client.emit('error', err)
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,38 +22,6 @@ module.exports = async function (client, options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.session && options.profilesFolder) {
|
|
||||||
try {
|
|
||||||
const auths = await getLauncherProfiles()
|
|
||||||
|
|
||||||
const lowerUsername = options.username.toLowerCase()
|
|
||||||
const profile = Object.keys(auths.authenticationDatabase).find(key =>
|
|
||||||
auths.authenticationDatabase[key].username.toLowerCase() === lowerUsername ||
|
|
||||||
Object.values(auths.authenticationDatabase[key].profiles)[0].displayName.toLowerCase() === lowerUsername
|
|
||||||
)
|
|
||||||
|
|
||||||
if (profile) {
|
|
||||||
const newUsername = auths.authenticationDatabase[profile].username
|
|
||||||
const uuid = Object.keys(auths.authenticationDatabase[profile].profiles)[0]
|
|
||||||
const displayName = auths.authenticationDatabase[profile].profiles[uuid].displayName
|
|
||||||
const newProfile = {
|
|
||||||
name: displayName,
|
|
||||||
id: uuid
|
|
||||||
}
|
|
||||||
|
|
||||||
options.session = {
|
|
||||||
accessToken: auths.authenticationDatabase[profile].accessToken,
|
|
||||||
clientToken: auths.clientToken,
|
|
||||||
selectedProfile: newProfile,
|
|
||||||
availableProfiles: [newProfile]
|
|
||||||
}
|
|
||||||
options.username = newUsername
|
|
||||||
}
|
|
||||||
} catch (ignoreErr) {
|
|
||||||
// skip the error :/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.session) {
|
if (options.session) {
|
||||||
if (!skipValidation) {
|
if (!skipValidation) {
|
||||||
yggdrasilClient.validate(options.session.accessToken, function (err) {
|
yggdrasilClient.validate(options.session.accessToken, function (err) {
|
||||||
|
@ -147,8 +33,7 @@ module.exports = async function (client, options) {
|
||||||
yggdrasilClient.auth({
|
yggdrasilClient.auth({
|
||||||
user: options.username,
|
user: options.username,
|
||||||
pass: options.password,
|
pass: options.password,
|
||||||
token: clientToken,
|
token: clientToken
|
||||||
requestUser: true
|
|
||||||
}, cb)
|
}, cb)
|
||||||
} else {
|
} else {
|
||||||
cb(err, data)
|
cb(err, data)
|
||||||
|
|
Loading…
Reference in a new issue