DoctorMcKay / node-steam-session

Node.js module for authenticating with the Steam auth server. Allows for generating refresh tokens and web auth cookies for use with steam-user and other packages.
https://www.npmjs.com/package/steam-session
MIT License
112 stars 20 forks source link

Unhandled rejection: 'Proxy connection timed out' causes app crash #21

Closed Sadzurami closed 1 year ago

Sadzurami commented 1 year ago

Describe the bug

When using a proxy, the "Proxy connection timed out" exception sometimes occurred. Try/catch does not catch this exception.

Versions

steam-session: 1.2.3 node: v18.16.0

Code

const getCookies = async (refreshToken: string, proxy: string) => {
    let loginSession: LoginSession;
    try {
        loginSession = new LoginSession(EAuthTokenPlatformType.WebBrowser, { httpProxy: proxy });
        loginSession.loginTimeout = 10000;
        loginSession.refreshToken = refreshToken;

        const cookies = await loginSession.getWebCookies();

        return cookies;
    } catch (error) {
        throw new Error('Failed to get cookies');
    } finally {
        loginSession?.cancelLoginAttempt();
    }
};

Screenshots and Error Logs

Error: Proxy connection timed out
    at ClientRequest.<anonymous> (/Users/user/Progects/project/node_modules/@doctormckay/stdlib/src/lib/http/proxyagent.ts:106:18)
    at ClientRequest.emit (node:events:513:28)
    at ClientRequest.emit (node:domain:489:12)
    at Socket.emitRequestTimeout (node:_http_client:848:9)
    at Object.onceWrapper (node:events:627:28)
    at Socket.emit (node:events:525:35)
    at Socket.emit (node:domain:489:12)
    at Socket._onTimeout (node:net:570:8)
    at listOnTimeout (node:internal/timers:569:17)
    at processTimers (node:internal/timers:512:7) {
  proxyConnecting: true
}
Sadzurami commented 1 year ago

also, there are some similar errors

Error: Client network socket disconnected before secure TLS connection was established
    at connResetException (node:internal/errors:717:14)
    at TLSSocket.onConnectEnd (node:_tls_wrap:1595:19)
    at TLSSocket.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'ECONNRESET',
  path: null,
  host: 'steamcommunity.com',
  port: 443,
  localAddress: undefined,
  proxyConnecting: false
}
Error: socket hang up
    at connResetException (node:internal/errors:717:14)
    at TLSSocket.socketOnEnd (node:_http_client:526:23)
    at TLSSocket.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  code: 'ECONNRESET'
}
DoctorMcKay commented 1 year ago

Are you handling the error event on the LoginSession? actually this wouldn't matter for your example code

DoctorMcKay commented 1 year ago

I cannot reproduce this on the latest version of steam-session:

process.env.DEBUG = '*';

import {EAuthTokenPlatformType, LoginSession} from '../src';

main();

async function main() {
    let loginSession: LoginSession;
    try {
        loginSession = new LoginSession(EAuthTokenPlatformType.WebBrowser, {httpProxy: 'http://127.0.0.1:1234'});
        loginSession.loginTimeout = 10000;
        loginSession.refreshToken = 'eyAidHlwIjogIkpXVCIsICJhbGciOiAiRWREU0EiIH0...';

        let cookies = await loginSession.getWebCookies();

        console.log(cookies);
    } catch (err) {
        throw new Error('Failed to get cookies');
    } finally {
        loginSession?.cancelLoginAttempt();
    }
}

Output:

  steam-session:LoginSession POST https://login.steampowered.com/jwt/finalizelogin { nonce: 'eyAidHlwIjogIkpXVCIsICJhbGciOiAiRWREU0EiIH0...', sessionid: '59dbd69e413d215aa2815a79', redir: 'https://steamcommunity.com/login/home/?goto=' } +0ms
D:\Libraries\Repos\Node Modules\steam-session\dev\test3.ts:18
                throw new Error('Failed to get cookies');
        ^
Error: Failed to get cookies
    at main (D:\Libraries\Repos\Node Modules\steam-session\dev\test3.ts:18:9)
    at processTicksAndRejections (node:internal/process/task_queues:95:5)

Also, FYI: setting loginTimeout and calling cancelLoginAttempt() are both unnecessary here. They only take effect if you start a login attempt using startWithCredentials or startWithQR.

Sadzurami commented 1 year ago

I cannot reproduce this on the latest version of steam-session:

It looks like you are using stable proxies while testing.

I constantly get this errors while using mobile proxies with rotation (sometimes the connection may be interrupted).

Yep, I know this is a bad production scenario, but the expected behavior of the library - throw errors (if there is), that can be catched (even "request timed out" errors).

I can provide you with my proxies/refresh-tokens and small script for tests if you are interested in solving this issue.

Also, FYI: setting loginTimeout and calling cancelLoginAttempt() are both unnecessary here. They only take effect if you start a login attempt using startWithCredentials or startWithQR.

Thanks, I'll keep it in mind.

Sadzurami commented 1 year ago

Looks like I've found the source of the problem. @DoctorMcKay, please check pr.

DoctorMcKay commented 1 year ago

Fixed in #23

ivandrago228 commented 7 months ago

The problem is still relevant. When using proxies. Try/catch does not catch this exception. steam-session: 1.7.2 node: v16.20.2

1. /home/ubuntu/node_modules/steam-session/dist/LoginSession.js:713 return reject(new Error('No Set-Cookie header in result')); Error: No Set-Cookie header in result at /home/ubuntu/node_modules/steam-session/dist/LoginSession.js:713:31

2. /home/ubuntu/node_modules/@doctormckay/stdlib/lib/http/proxyagent.js:92 let err = new Error('Proxy connection timed out'); Error: Proxy connection timed out at ClientRequest.<anonymous> (/home/ubuntu/node_modules/@doctormckay/stdlib/lib/http/proxyagent.js:92:31) at ClientRequest.emit (node:events:513:28) at Socket.emitRequestTimeout (node:_http_client:839:9) at Object.onceWrapper (node:events:627:28) at Socket.emit (node:events:525:35) at Socket._onTimeout (node:net:550:8) at listOnTimeout (node:internal/timers:559:17) at processTimers (node:internal/timers:502:7) { proxyConnecting: true }

Number 2 I fixed it and commented it out proxyagent.js

        req.on('timeout', () => {
            if (finished) {
                return;
            }
            finished = true;
            let err = new Error('Proxy connection timed out');
            err.proxyConnecting = !didWeEverConnect;
            //callback(err);
        });
Sadzurami commented 7 months ago

The problem is still relevant. When using proxies. Try/catch does not catch this exception. steam-session: 1.7.2 node: v16.20.2

/home/ubuntu/node_modules/steam-session/dist/LoginSession.js:713 return reject(new Error('No Set-Cookie header in result')); Error: No Set-Cookie header in result at /home/ubuntu/node_modules/steam-session/dist/LoginSession.js:713:31

/home/ubuntu/node_modules/@doctormckay/stdlib/lib/http/proxyagent.js:92 let err = new Error('Proxy connection timed out'); Error: Proxy connection timed out at ClientRequest.<anonymous> (/home/ubuntu/node_modules/@doctormckay/stdlib/lib/http/proxyagent.js:92:31) at ClientRequest.emit (node:events:513:28) at Socket.emitRequestTimeout (node:_http_client:839:9) at Object.onceWrapper (node:events:627:28) at Socket.emit (node:events:525:35) at Socket._onTimeout (node:net:550:8) at listOnTimeout (node:internal/timers:559:17) at processTimers (node:internal/timers:502:7) { proxyConnecting: true }

Number 2 I fixed it and commented it out proxyagent.js

        req.on('timeout', () => {
            if (finished) {
                return;
            }
            finished = true;
            let err = new Error('Proxy connection timed out');
            err.proxyConnecting = !didWeEverConnect;
            //callback(err);
        });

show code example for case #1

ivandrago228 commented 7 months ago

I took the code from the examples


try {
    let session = new SteamSession.LoginSession(SteamSession.EAuthTokenPlatformType.WebBrowser, { httpProxy: "http://" + proxy });
    let startResult = await session.startWithCredentials({
        accountName,
        password
    });

    if (startResult.actionRequired) {
        try {
            let codeActionTypes = [SteamSession.EAuthSessionGuardType.EmailCode, SteamSession.EAuthSessionGuardType.DeviceCode];
            let codeAction = startResult.validActions.find(action => codeActionTypes.includes(action.type));
            if (codeAction) {
                let authCode = SteamTotp.getAuthCode(shared_secret);
                if (authCode) {
                    await session.submitSteamGuardCode(authCode);
                }
            }
        } catch (e) {

        }
    } else if (startResult.actionRequired) {
        throw new Error('Login action is required, but we don\'t know how to handle it');
    }

    session.on('authenticated', async () => {
        console.log(`Successfully logged in as ${session.accountName}`);
        let webCookies = await session.getWebCookies();
        if (webCookies) {
            let filteredCookies = webCookies.filter(cookie => cookie.includes('Domain=steamcommunity.com'));

            let processedCookies = filteredCookies.map(cookie => {
                let parts = cookie.split(';');
                return parts[0];
            });

            let cookiesStr = processedCookies.join('; ');
            let cookiesObj = {
                ip: "http://" + proxy,
                type_ip: "proxy",
                cookies: cookiesStr
            };
            functions.redisHSET(db_cookies, accountName, JSON.stringify(cookiesObj));

        } else {
            console.log('Error with cookies', accountName);
        }
    });

    session.on('timeout', () => {
        console.log('This login attempt has timed out.');
    });

    session.on('error', (err) => {
        console.log(`ERROR: This login attempt has failed! ${err.message}`);
    });
} catch (e) {

}

UPD1: Sorry, I can’t figure out how to make the code in the comments beautiful. UPD2: Thanks.

Sadzurami commented 7 months ago

@ivandrago228

in your code example there is an error session.on('authenticated'... fires later than try/catch block ends

so, you're not properly handle errors in event block

Sadzurami commented 7 months ago

Sorry, I can’t figure out how to make the code in the comments beautiful.

image

ivandrago228 commented 7 months ago

Thanks. But solving the second problem through commenting does not seem optimal ))

Sadzurami commented 7 months ago

Thanks. But solving the second problem through commenting does not seem optimal ))

About problem 2. Looks like you not properly handle error event. In code above you are start catching this event after actions that may cause errors. Much better to declare error handler before startWithCredentials call.

DoctorMcKay commented 7 months ago

Where the error event is attached shouldn't be an issue here. Assuming no bug in the library, it's possible that the error is originating from the getWebCookies() call, since that isn't wrapped in try/catch.

ivandrago228 commented 7 months ago

Where the error event is attached shouldn't be an issue here. Assuming no bug in the library, it's possible that the error is originating from the getWebCookies() call, since that isn't wrapped in try/catch.

Yeap, fixed. Thanks.

ivandrago228 commented 7 months ago

I touched on another error. I can't figure out how to intercept it. Try/catch does not catch this exception.


/home/ubuntu/node_modules/@doctormckay/stdlib/lib/http/proxyagent.js:91
            let err = new Error('Proxy connection timed out');
                      ^

Error: Proxy connection timed out
    at ClientRequest.<anonymous> (/home/ubuntu/node_modules/@doctormckay/stdlib/lib/http/proxyagent.js:91:23)
    at ClientRequest.emit (node:events:513:28)
    at Socket.emitRequestTimeout (node:_http_client:839:9)
    at Object.onceWrapper (node:events:627:28)
    at Socket.emit (node:events:525:35)
    at Socket._onTimeout (node:net:550:8)
    at listOnTimeout (node:internal/timers:559:17)
    at processTimers (node:internal/timers:502:7)
Emitted 'error' event on LoginSession instance at:
    at LoginSession._doPoll (/home/ubuntu/node_modules/steam-session/dist/LoginSession.js:498:22)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (node:internal/process/task_queues:96:5) {
  proxyConnecting: true
}
DoctorMcKay commented 7 months ago

Are you still listening for the error event?

ivandrago228 commented 7 months ago
        session.on('error', (err) => {
            console.log(`ERROR: This login attempt has failed! ${err.message}`);
        });

Remove this? I tried to insert try/catch inside. Didn't help.