Browse Source

SteamAuthenticator can add/verify phone number

fix #59

New methods:

* add_phone_number()
* has_phone_number()
* confirm_phone_number()
* validate_phone_number()
pull/35/merge
Rossen Georgiev 8 years ago
parent
commit
484536eff9
  1. 130
      steam/guard.py
  2. 6
      steam/webauth.py

130
steam/guard.py

@ -151,6 +151,9 @@ class SteamAuthenticator(object):
:raises: :class:`SteamAuthenticatorError`
"""
if not self.has_phone_number():
raise SteamAuthenticatorError("Account doesn't have a verified phone number")
resp = self._send_request('AddAuthenticator', {
'steamid': self.medium.steam_id,
'authenticator_time': int(time()),
@ -200,6 +203,8 @@ class SteamAuthenticator(object):
"""
if not self.secrets:
raise SteamAuthenticatorError("No authenticator secrets available?")
if not isinstance(self.medium, MobileWebAuth):
raise SteamAuthenticatorError("Only available via MobileWebAuth")
resp = self._send_request('RemoveAuthenticator', {
'steamid': self.medium.steam_id,
@ -239,6 +244,131 @@ class SteamAuthenticator(object):
"""
self._send_request('DestroyEmergencyCodes', {'steamid': self.medium.steam_id})
def _get_web_session(self):
"""
:return: authenticated web session
:rtype: :class:`requests.Session`
:raises: :class:`RuntimeError` when session is unavailable
"""
if isinstance(self.medium, MobileWebAuth):
return self.medium.session
else:
if self.medium.logged_on:
sess = self.medium.get_web_session()
if sess is None:
raise RuntimeError("Failed to get a web session. Try again in a few minutes")
else:
return sess
else:
raise RuntimeError("SteamClient instance is not connected")
def add_phone_number(self, phone_number):
"""Add phone number to account
Then confirm it via :meth:`confirm_phone_number()`
:param phone_number: phone number with country code
:type phone_number: :class:`str`
:return: success (returns ``False`` on request fail/timeout)
:rtype: :class:`bool`
"""
sess = self._get_web_session()
try:
resp = sess.post('https://steamcommunity.com/steamguard/phoneajax',
data={
'op': 'add_phone_number',
'arg': phone_number,
'checkfortos': 0,
'skipvoip': 0,
'sessionid': sess.cookies.get('sessionid', domain='steamcommunity.com'),
},
timeout=15).json()
except:
return False
return (resp or {}).get('success', False)
def confirm_phone_number(self, sms_code):
"""Confirm phone number with the recieved SMS code
:param sms_code: sms code
:type sms_code: :class:`str`
:return: success (returns ``False`` on request fail/timeout)
:rtype: :class:`bool`
"""
sess = self._get_web_session()
try:
resp = sess.post('https://steamcommunity.com/steamguard/phoneajax',
data={
'op': 'check_sms_code',
'arg': sms_code,
'checkfortos': 1,
'skipvoip': 1,
'sessionid': sess.cookies.get('sessionid', domain='steamcommunity.com'),
},
timeout=15).json()
except:
return False
return (resp or {}).get('success', False)
def has_phone_number(self):
"""Check whether the account has a verified phone number
:return: result
:rtype: :class:`bool` or :class:`None`
.. note::
Retruns `None` if the web requests fails for any reason
"""
sess = self._get_web_session()
try:
resp = sess.post('https://steamcommunity.com/steamguard/phoneajax',
data={
'op': 'has_phone',
'arg': '0',
'checkfortos': 0,
'skipvoip': 1,
'sessionid': sess.cookies.get('sessionid', domain='steamcommunity.com'),
},
timeout=15).json()
except:
raise
if resp['success'] == True:
return resp['has_phone']
def validate_phone_number(self, phone_number):
"""Test whether phone number is valid for Steam
:param phone_number: phone number with country code
:type phone_number: :class:`str`
:return: see example output below
:rtype: :class:`dict`
.. code:: python
{'is_fixed': False,
'is_valid': False,
'is_voip': True,
'number': '+1 123-555-1111',
'success': True}
"""
sess = self._get_web_session()
try:
resp = sess.get('https://store.steampowered.com//phone/validate',
params={'phoneNumber': phone_number},
timeout=15).json()
except:
resp = {}
return resp
class SteamAuthenticatorError(Exception):
pass

6
steam/webauth.py

@ -65,7 +65,7 @@ from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from steam.core.crypto import backend
from steam import SteamID, webapi
from steam.util.web import make_requests_session
from steam.util.web import make_requests_session, generate_session_id
if sys.version_info < (3,):
intBase = long
@ -77,6 +77,7 @@ class WebAuth(object):
key = None
complete = False #: whether authentication has been completed successfully
session = None #: :class:`requests.Session` (with auth cookies after auth is complete)
session_id = None #: :class:`str`, session id string
captcha_gid = -1
steam_id = None #: :class:`.SteamID` (after auth is complete)
@ -187,9 +188,12 @@ class WebAuth(object):
for domain in ['store.steampowered.com', 'help.steampowered.com', 'steamcommunity.com']:
self.session.cookies.set(cookie.name, cookie.value, domain=domain, secure=cookie.secure)
self.session_id = generate_session_id()
for domain in ['store.steampowered.com', 'help.steampowered.com', 'steamcommunity.com']:
self.session.cookies.set('Steam_Language', language, domain=domain)
self.session.cookies.set('birthtime', '-3333', domain=domain)
self.session.cookies.set('sessionid', self.session_id, domain=domain)
self._finalize_login(resp)

Loading…
Cancel
Save