bukson / steampy

A Steam trading library for python 3
MIT License
577 stars 157 forks source link

Login problem. Looks like the value of steamLoginSecure cookie is wrong #359

Open patap opened 10 months ago

patap commented 10 months ago

Hello everyone! I have troubleshot with login.

This code executed without errors

steam_client = SteamClient(api_key)
steam_client.login(username, password, guard)

But steam_client.is_session_alive() has returned False. I verified html content - it is Steam's index page with login form.

I analyzed cookies that had occurred after steam_client.login() execution in the self._session. And found out the problem with the "steamLoginSecure" cookie. Because, if I make usual login with browser and take "steamLoginSecure" cookie's value, then put it into next CURL query - everything is perfect.

curl https://steamcommunity.com/ \
  -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' \
  -H 'Accept-Language: en-US,en;q=0.9' \
  -H 'Cache-Control: max-age=0' \
  -H 'Connection: keep-alive' \
  -H 'Cookie: steamLoginSecure=<my cookie value>' \
  -H 'Sec-Fetch-Dest: document' \
  -H 'Sec-Fetch-Mode: navigate' \
  -H 'Sec-Fetch-Site: none' \
  -H 'Sec-Fetch-User: ?1' \
  -H 'Upgrade-Insecure-Requests: 1' \
  -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: "Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Linux"' \
  --compressed

But if I put value from self._session cookie - it doesn't authorize me. Does anyone know what this could be?

Aarab228 commented 10 months ago

check #343 (fix by @xidios)

Aarab228 commented 10 months ago

check #343 (fix by @xidios)

i use all of this fix

client.py #fix cookies login

def set_login_cookies(self, cookies: dict) -> None:
        self._session.cookies.update(cookies)
        self.was_login_executed = True
        if self.steam_guard is None:
            self.steam_guard = {'steamid': str(self.get_steam_id())}
        self.market._set_login_executed(self.steam_guard, self._get_session_id())

 @login_required #fix trade offer
    def accept_trade_offer(self, trade_offer_id: str) -> dict:
        trade = self.get_trade_offer(trade_offer_id)
        trade_offer_state = TradeOfferState(trade['response']['offer']['trade_offer_state'])
        if trade_offer_state is not TradeOfferState.Active:
            raise ApiException(f'Invalid trade offer state: {trade_offer_state.name} ({trade_offer_state.value})')

        partner = self._fetch_trade_partner_id(trade_offer_id)
        session_id = self._session.cookies.get_dict("steamcommunity.com")['sessionid']
        accept_url = f'{SteamUrl.COMMUNITY_URL}/tradeoffer/{trade_offer_id}/accept'
        params = {
            'sessionid': session_id,
            'tradeofferid': trade_offer_id,
            'serverid': '1',
            'partner': partner,
            'captcha': '',
        }
        headers = {'Referer': self._get_trade_offer_url(trade_offer_id)}

        response = self._session.post(accept_url, data=params, headers=headers).json()
        if response.get('needs_mobile_confirmation', False):
            return self._confirm_transaction(trade_offer_id)

        return response

--------------------------------------------------------------------------------------------------------------------------

login.py # fix cookie login

def set_sessionid_cookies(self):
        community_domain = SteamUrl.COMMUNITY_URL[8:]
        store_domain = SteamUrl.STORE_URL[8:]
        community_cookie_dic = self.session.cookies.get_dict(domain = community_domain)
        store_cookie_dic = self.session.cookies.get_dict(domain = store_domain)
        for name in ('steamLoginSecure', 'sessionid', 'steamRefresh_steam', 'steamCountry'):
            cookie = self.session.cookies.get_dict()[name]
            if name in ["steamLoginSecure"]:
                store_cookie = create_cookie(name, store_cookie_dic[name], store_domain)
            else:
                store_cookie = create_cookie(name, cookie, store_domain)

            if name in ["sessionid", "steamLoginSecure"]:
                community_cookie = create_cookie(name, community_cookie_dic[name], community_domain)
            else:
                community_cookie = create_cookie(name, cookie, community_domain)

            self.session.cookies.set(**community_cookie)
            self.session.cookies.set(**store_cookie)

--------------------------------------------------------------------------------------------------------------------------

market.py #fix create_buy_order

@login_required
    def create_buy_order(
        self,
        market_name: str,
        price_single_item: str,
        quantity: int,
        game: GameOptions,
        currency: Currency = Currency.USD,
    ) -> dict:
    data = {
            #'sessionid': self._session.cookies.get_dict("steamcommunity.com")['sessionid'],
            'sessionid': self._session_id,
            'currency': currency.value,
            'appid': game.app_id,
            'market_hash_name': market_name,
            'price_total': str(Decimal(price_single_item) * Decimal(quantity)),
            'quantity': quantity,
        }
patap commented 9 months ago

@Aarab228 thank you mate! it's perfect) when will this issue be released?

reliponj commented 9 months ago

@Aarab228 you are the best! Really helped me! This fix must be committed very much

I would only do some refactoring, like

def _get_session_id(self) -> str: return self._session.cookies.get_dict("steamcommunity.com")['sessionid']

and don't change accept_trade_offer method. Thix fix also removes errors in such methods like make_offer and others

Aarab228 commented 9 months ago

@Aarab228 you are the best! Really helped me! This fix must be committed very much

I would only do some refactoring, like

def _get_session_id(self) -> str:

    return self._session.cookies.get_dict("steamcommunity.com")['sessionid']

and don't change accept_trade_offer method. Thix fix also removes errors in such methods like make_offer and others

yes, but with some moments without my fix u cant send trade, i dont remember with what parameters that connected, but like with returned cookies dict with ["sessionid"] maybe. Anyway, problem with return cookies

yesworId commented 9 months ago

@Aarab228 you are the best! Really helped me! This fix must be committed very much

I would only do some refactoring, like

def _get_session_id(self) -> str: return self._session.cookies.get_dict("steamcommunity.com")['sessionid']

and don't change accept_trade_offer method. Thix fix also removes errors in such methods like make_offer and others

For me error appears.

  File "C:\Users\PycharmProjects\venv\Lib\site-packages\steampy\client.py", line 171, in _get_session_id
    return self._session.cookies.get_dict("steamcommunity.com")['sessionid']
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
KeyError: 'sessionid'

Process finished with exit code 1
Zarkxxxxx commented 9 months ago

check #343 (fix by @xidios)

i use all of this fix

client.py #fix cookies login

def set_login_cookies(self, cookies: dict) -> None:
        self._session.cookies.update(cookies)
        self.was_login_executed = True
        if self.steam_guard is None:
            self.steam_guard = {'steamid': str(self.get_steam_id())}
        self.market._set_login_executed(self.steam_guard, self._get_session_id())

 @login_required #fix trade offer
    def accept_trade_offer(self, trade_offer_id: str) -> dict:
        trade = self.get_trade_offer(trade_offer_id)
        trade_offer_state = TradeOfferState(trade['response']['offer']['trade_offer_state'])
        if trade_offer_state is not TradeOfferState.Active:
            raise ApiException(f'Invalid trade offer state: {trade_offer_state.name} ({trade_offer_state.value})')

        partner = self._fetch_trade_partner_id(trade_offer_id)
        session_id = self._session.cookies.get_dict("steamcommunity.com")['sessionid']
        accept_url = f'{SteamUrl.COMMUNITY_URL}/tradeoffer/{trade_offer_id}/accept'
        params = {
            'sessionid': session_id,
            'tradeofferid': trade_offer_id,
            'serverid': '1',
            'partner': partner,
            'captcha': '',
        }
        headers = {'Referer': self._get_trade_offer_url(trade_offer_id)}

        response = self._session.post(accept_url, data=params, headers=headers).json()
        if response.get('needs_mobile_confirmation', False):
            return self._confirm_transaction(trade_offer_id)

        return response

--------------------------------------------------------------------------------------------------------------------------

login.py # fix cookie login

def set_sessionid_cookies(self):
        community_domain = SteamUrl.COMMUNITY_URL[8:]
        store_domain = SteamUrl.STORE_URL[8:]
        community_cookie_dic = self.session.cookies.get_dict(domain = community_domain)
        store_cookie_dic = self.session.cookies.get_dict(domain = store_domain)
        for name in ('steamLoginSecure', 'sessionid', 'steamRefresh_steam', 'steamCountry'):
            cookie = self.session.cookies.get_dict()[name]
            if name in ["steamLoginSecure"]:
                store_cookie = create_cookie(name, store_cookie_dic[name], store_domain)
            else:
                store_cookie = create_cookie(name, cookie, store_domain)

            if name in ["sessionid", "steamLoginSecure"]:
                community_cookie = create_cookie(name, community_cookie_dic[name], community_domain)
            else:
                community_cookie = create_cookie(name, cookie, community_domain)

            self.session.cookies.set(**community_cookie)
            self.session.cookies.set(**store_cookie)

--------------------------------------------------------------------------------------------------------------------------

market.py #fix create_buy_order

@login_required
    def create_buy_order(
        self,
        market_name: str,
        price_single_item: str,
        quantity: int,
        game: GameOptions,
        currency: Currency = Currency.USD,
    ) -> dict:
    data = {
            #'sessionid': self._session.cookies.get_dict("steamcommunity.com")['sessionid'],
            'sessionid': self._session_id,
            'currency': currency.value,
            'appid': game.app_id,
            'market_hash_name': market_name,
            'price_total': str(Decimal(price_single_item) * Decimal(quantity)),
            'quantity': quantity,
        }

thx, it just work! XD

luckyway7 commented 8 months ago

check #343 (fix by @xidios)

i use all of this fix

client.py #fix cookies login

def set_login_cookies(self, cookies: dict) -> None:
        self._session.cookies.update(cookies)
        self.was_login_executed = True
        if self.steam_guard is None:
            self.steam_guard = {'steamid': str(self.get_steam_id())}
        self.market._set_login_executed(self.steam_guard, self._get_session_id())

 @login_required #fix trade offer
    def accept_trade_offer(self, trade_offer_id: str) -> dict:
        trade = self.get_trade_offer(trade_offer_id)
        trade_offer_state = TradeOfferState(trade['response']['offer']['trade_offer_state'])
        if trade_offer_state is not TradeOfferState.Active:
            raise ApiException(f'Invalid trade offer state: {trade_offer_state.name} ({trade_offer_state.value})')

        partner = self._fetch_trade_partner_id(trade_offer_id)
        session_id = self._session.cookies.get_dict("steamcommunity.com")['sessionid']
        accept_url = f'{SteamUrl.COMMUNITY_URL}/tradeoffer/{trade_offer_id}/accept'
        params = {
            'sessionid': session_id,
            'tradeofferid': trade_offer_id,
            'serverid': '1',
            'partner': partner,
            'captcha': '',
        }
        headers = {'Referer': self._get_trade_offer_url(trade_offer_id)}

        response = self._session.post(accept_url, data=params, headers=headers).json()
        if response.get('needs_mobile_confirmation', False):
            return self._confirm_transaction(trade_offer_id)

        return response

--------------------------------------------------------------------------------------------------------------------------

login.py # fix cookie login

def set_sessionid_cookies(self):
        community_domain = SteamUrl.COMMUNITY_URL[8:]
        store_domain = SteamUrl.STORE_URL[8:]
        community_cookie_dic = self.session.cookies.get_dict(domain = community_domain)
        store_cookie_dic = self.session.cookies.get_dict(domain = store_domain)
        for name in ('steamLoginSecure', 'sessionid', 'steamRefresh_steam', 'steamCountry'):
            cookie = self.session.cookies.get_dict()[name]
            if name in ["steamLoginSecure"]:
                store_cookie = create_cookie(name, store_cookie_dic[name], store_domain)
            else:
                store_cookie = create_cookie(name, cookie, store_domain)

            if name in ["sessionid", "steamLoginSecure"]:
                community_cookie = create_cookie(name, community_cookie_dic[name], community_domain)
            else:
                community_cookie = create_cookie(name, cookie, community_domain)

            self.session.cookies.set(**community_cookie)
            self.session.cookies.set(**store_cookie)

--------------------------------------------------------------------------------------------------------------------------

market.py #fix create_buy_order

@login_required
    def create_buy_order(
        self,
        market_name: str,
        price_single_item: str,
        quantity: int,
        game: GameOptions,
        currency: Currency = Currency.USD,
    ) -> dict:
    data = {
            #'sessionid': self._session.cookies.get_dict("steamcommunity.com")['sessionid'],
            'sessionid': self._session_id,
            'currency': currency.value,
            'appid': game.app_id,
            'market_hash_name': market_name,
            'price_total': str(Decimal(price_single_item) * Decimal(quantity)),
            'quantity': quantity,
        }

Thank you, this really helped, I spent about 2 days solving this problem. But this is the only solution at the moment. For those who are also looking for a solution to this problem, this code will help you.