seishun / node-steam

Interface directly with Steam servers from Node.js
MIT License
1.01k stars 180 forks source link

Problems with sentryfiles #67

Closed jorisk322 closed 10 years ago

jorisk322 commented 10 years ago

Solution: use buffers, don't log off too quickly.

I'm having problems registering/logging in with sentry files. I've tried both setting them myself and saving the one received through the sentry event. I have one bot running right now that works fine using a sentry string I generated earlier (like 6 months ago), but all attempts to enable new accounts have failed. I've reduced my code to just this, but that also doesn't work.

var steam = require('steam');

var steamClient = new steam.SteamClient();

steamClient.logOn({
   accountName: 'name',
   password: 'pass',
   authCode: 'JCXTK', // I do remove this line when trying to log in using a sentry
   shaSentryfile: 'sentrytest'
});

steamClient.on('loggedOn', function() {
    console.log('.');
});

I'm getting the 63 error (steamGuard thing required) when trying to log in with a sentry that I registered with an account. Logging in with the code Steam sends through mail does work, but is useless if I can't re-use the sentry.

Am I missing something or did Steam change their login-system? I'm guessing the first but I have no clue what I'm doing wrong.

seishun commented 10 years ago

How do you save and store the sentry hash? In your example you have 'sentrytest', but shaSentryfile should be a Buffer.

jorisk322 commented 10 years ago

Weird. The bot I'm running that does work uses a string as the shaSentryfile, so that's what I was doing here as well.

I have also tried saving it like this: fs.writeFileSync('path/file', hash); // in the sentry event and loading it like this: fs.readFileSync('path/file'); It does actually load a file (tested by logging).

seishun commented 10 years ago

But it still doesn't log on?

bontscho commented 10 years ago

i think you missed the stringify/parsing of JSON, here is my code for those events:


if (fs.existsSync('sentry')) {
    sentry = JSON.parse(fs.readFileSync('sentry'));
}

bot.on('servers', function(servers) {
    fs.writeFile('servers', JSON.stringify(servers));
});
jorisk322 commented 10 years ago

Hmm. I just placed those loading methods in my test code and it did work. I checked the sentry files and the one I was using (that wasn't working) seems to contain a newline character (displays a new line in Sublime Text and with it the file is 20 chars). It might have something to do with that. I'll play around with it a bit. How do I send a custom hash properly? Should I use something like new Buffer('hash')?

EDIT: With methods I meant the lines I posted earlier. Not what bontscho posted.

bontscho commented 10 years ago

@jorisk322 you can use a javascript array iirc:

var sentry = [123,123,123,123,123]
jorisk322 commented 10 years ago

@bontscho What should be in the array? (Can I use strings? How much data can I store at one index?)

bontscho commented 10 years ago

@jorisk322 if you logon with just username/password/authCode you should receive the event 'server' that will give you an array with 20 integer values between 0-255 (that at least how my sentries look). that array is sort of identification for steamguard that this machine is authorized to logon. if the sentry array is new to steam, it will cause to send you an auth code and let your login fail

jorisk322 commented 10 years ago

Hmm. Just tried it again. It seems like steam removes the sentry from the account when I call logOff(). If I quit (ctrl+c) the process without logging off it does work. During subsequent sessions using logOff() doesn't cause any problems.

@seishun Could you try replicate this behaviour? If it's consistent you might want to fix/document it.

EDIT: In my code I called logOff right after saving the sentry file. When I delayed it it worked fine, so I guess the client couldn't send a confirmation before the connection was destroyed. How do I close this?

majimboo commented 10 years ago

Having the same problem. After logging in successfully with an authCode and a self generated hash. I log out, after awhile, I log-in again with the hash, but I get error 63.

bontscho commented 10 years ago

@majimboo after you have generated a sentry hash, you have to login again without the authcode and then you will get a new authcode sent to that you have to use again. in my understanding, logging in with the sentry will prompt a new steam guard access. the only way to circumvent that is probably generating a sentry hash beforehand

majimboo commented 10 years ago

Yes, well this is my flow. Try to login with username and password. Catch error 63, ask for AuthCode from email, generate a 20 bytes buffer, login with the username, password, authcode and buffer.

Well, all of those above works, it does successfully login. I can even chat with it.

Now I logout, then try to login, this time it detects that a buffer/sentry is available. It tried to send username, password and sentry. But this time I get error 63.

bontscho commented 10 years ago

this is my workflow:

  1. login with username+password
  2. catch error, receive authcode per mail
  3. login with username+password+authcode
  4. receive sentry file
  5. exit
  6. login with username+password+sentry
  7. catch error, receive authcode per mail
  8. login with username+password+authcode+sentry
  9. login successfull 10 and onwards: login with username+password+sentry
majimboo commented 10 years ago

Aaah, so I was missing this steps:

  1. login with username+password+authcode
  2. receive sentry file
  3. exit
  4. login with username+password+sentry
  5. catch error, receive authcode per mail

I was thinking after registering by logging in successfully with sentry, its all good. I'll try that. Thanks.

yberreby commented 10 years ago

I have the same problem. @bontscho I tried what you said, it works until step 10, at which I get an eresult of 63 and a new guard code by email.

Also, what do you mean by "catch error" at step 7? Actually catch it with a try/catch block so that the program doesn't crash? Is that important? I just let the error happen.

yberreby commented 10 years ago

Finally got it to work using code from node-steam-trash-bot. But I don't understand what is the part that made it work.

Here's the beginning of the original code (doesn't work, I login with the authcode but if I reconnect it sends me a new code):

// Modules
var fs = require('fs');
var Steam = require('steam');
var SteamTrade = require('steam-trade');
var winston = require('winston');

// Local files
var params = require('./params.js');

// Module initialization
var logger = new winston.Logger({ 
  transports: [
    new winston.transports.Console({
      level: 'debug', // Winston levels: silly,  debug, verbose, info, warn, error (6) IN THIS ORDER
      handleExceptions: false
    })
  ],
  exitOnError: false
});

// Declarations
var serversFile = 'servers';
var sentryFile = 'sentry';
var sentryHash;

// Localization
var messages = {

}

logger.info('Filsbot launched');

if (fs.existsSync(sentryFile)) {
  logger.verbose('Reading sentry hash from file')
  sentryHash = fs.readFileSync(sentryFile);
} else if (params.guardCode != '') {
  logger.verbose('No sentry hash was found. The Steam Guard code will be used instead.')
}

if (fs.existsSync(serversFile)) {
  Steam.servers = JSON.parse(fs.readFileSync(serversFile));
} else {
  logger.warn("No servers file found, using defaults");
}

// Starting to use node-steam from here
var bot = new Steam.SteamClient();

// Logging in with supplied info
console.log(params)
var logOnInfo = {
  accountName: params.username,
  password: params.password,
  authCode: params.guardCode,
  shaSentryFile: sentryHash
};
logger.debug('Logging in with password', params.password);
bot.logOn(logOnInfo);

// Basic node-steam listeners

bot.on('loggedOn', function() { 
  winston.info("Logged in to Steam");
  bot.setPersonaState(Steam.EPersonaState.Online);
});

bot.on('error', function(error) { 
  winston.error("Caught Steam error", error);
});

bot.on('loggedOff', function() { 
  winston.error("Logged off from Steam");
});

// Save the sentry hash to a file for later use when we get one
bot.on('sentry', function(buffer) { 
  winston.info("Sentry event fired - Writing sentry hash to file...");
  fs.writeFile(sentryFile, buffer);
});

bot.on('servers', function(servers) {
  fs.writeFile(serversFile, JSON.stringify(servers));
});

Here's the same portion of code, updated to work with snippets from node-steam-trash-bot:

// Modules
var fs = require('fs');
var steam = require('steam');
var SteamTrade = require('steam-trade');
var winston = require('winston');

// Local files
var secrets = require('./params.js');

// Module initialization
var logger = new winston.Logger({ 
  transports: [
    new winston.transports.Console({
      level: 'debug', // Winston levels: silly,  debug, verbose, info, warn, error (6) IN THIS ORDER
      handleExceptions: false
    })
  ],
  exitOnError: false
});

// Declarations
var serversFile = 'servers';
var sentryFile = 'sentry';
var sentryHash;

// Localization
var messages = {

}

logger.info('Filsbot launched');

if (fs.existsSync(serversFile)) {
  steam.servers = JSON.parse(fs.readFileSync(serversFile));
}
else {
  winston.warn("No servers file found, using defaults");
}

if (fs.existsSync(sentryFile)) {
  sentryHash = fs.readFileSync(sentryFile);
}

var bot = new steam.SteamClient();

bot.logOn({ accountName: secrets.username, password: secrets.password, authCode: secrets.guardCode, shaSentryfile: sentryHash });

bot.on('loggedOn', function() { 
  winston.info("Logged on");
  bot.setPersonaState(steam.EPersonaState.Online);
  canTrade = false;
});

bot.on('error', function(error) { 
  winston.error("Caught Steam error", error);
  canTrade = false;
});

bot.on('loggedOff', function() { 
  winston.error("Logged off from Steam");
  canTrade = false;
});

bot.on('sentry', function(buffer) { 
  winston.info("Sentry event fired");
  fs.writeFile(sentryFile, buffer);
});

bot.on('servers', function(servers) {
  fs.writeFile(serversFile, JSON.stringify(servers));
});

What prevents my original code from working?