boursorama two_authentication with BrowserToBeContinued instead of raw_input
This commit is contained in:
parent
3a05b29bc3
commit
aa721c28b8
3 changed files with 75 additions and 83 deletions
|
|
@ -44,7 +44,7 @@ class Boursorama(Browser):
|
||||||
'b290ef629c88f0508e9cc6305421c173bd4291175e3ddedbee05ee666b34c20e']
|
'b290ef629c88f0508e9cc6305421c173bd4291175e3ddedbee05ee666b34c20e']
|
||||||
ENCODING = None # refer to the HTML encoding
|
ENCODING = None # refer to the HTML encoding
|
||||||
PAGES = {
|
PAGES = {
|
||||||
'.*/connexion/securisation/index.phtml': AuthenticationPage,
|
'.*/connexion/securisation.*': AuthenticationPage,
|
||||||
'.*connexion.phtml.*': LoginPage,
|
'.*connexion.phtml.*': LoginPage,
|
||||||
'.*/comptes/synthese.phtml': AccountsList,
|
'.*/comptes/synthese.phtml': AccountsList,
|
||||||
'.*/comptes/banque/detail/mouvements.phtml.*': AccountHistory,
|
'.*/comptes/banque/detail/mouvements.phtml.*': AccountHistory,
|
||||||
|
|
@ -55,10 +55,14 @@ class Boursorama(Browser):
|
||||||
'.*/opcvm.phtml.*': InvestmentDetail
|
'.*/opcvm.phtml.*': InvestmentDetail
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, device="weboob", enable_twofactors=False,
|
__states__ = []
|
||||||
*args, **kwargs):
|
|
||||||
self.device = device
|
def __init__(self, config=None, *args, **kwargs):
|
||||||
self.enable_twofactors = enable_twofactors
|
self.config = config
|
||||||
|
self.auth_token = None
|
||||||
|
kwargs['get_home'] = False
|
||||||
|
kwargs['username'] = self.config['login'].get()
|
||||||
|
kwargs['password'] = self.config['password'].get()
|
||||||
Browser.__init__(self, *args, **kwargs)
|
Browser.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def home(self):
|
def home(self):
|
||||||
|
|
@ -72,32 +76,36 @@ class Boursorama(Browser):
|
||||||
|
|
||||||
def handle_authentication(self):
|
def handle_authentication(self):
|
||||||
if self.is_on_page(AuthenticationPage):
|
if self.is_on_page(AuthenticationPage):
|
||||||
if self.enable_twofactors:
|
if self.config['enable_twofactors'].get():
|
||||||
self.page.authenticate(self.device)
|
if not self.config['pin_code'].get() or not self.auth_token:
|
||||||
|
self.page.send_sms()
|
||||||
|
else:
|
||||||
|
self.page.authenticate()
|
||||||
else:
|
else:
|
||||||
raise BrowserIncorrectAuthenticationCode(
|
raise BrowserIncorrectAuthenticationCode(
|
||||||
"""Boursorama - activate the two factor authentication in boursorama config."""
|
"""Boursorama - activate the two factor authentication in boursorama config."""
|
||||||
""" You will receive SMS code but are limited in request per day (around 15)"""
|
""" You will receive SMS code but are limited in request per day (around 15)"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def login(self):
|
def login(self):
|
||||||
assert isinstance(self.device, basestring)
|
assert isinstance(self.config['device'].get(), basestring)
|
||||||
assert isinstance(self.enable_twofactors, bool)
|
assert isinstance(self.config['enable_twofactors'].get(), bool)
|
||||||
assert self.password.isdigit()
|
assert self.password.isdigit()
|
||||||
|
|
||||||
if not self.is_on_page(LoginPage):
|
if self.is_on_page(AuthenticationPage):
|
||||||
self.location('https://' + self.DOMAIN + '/connexion.phtml', no_login=True)
|
self.handle_authentication()
|
||||||
|
else:
|
||||||
|
if not self.is_on_page(LoginPage):
|
||||||
|
self.location('https://' + self.DOMAIN + '/connexion.phtml', no_login=True)
|
||||||
|
|
||||||
self.page.login(self.username, self.password)
|
self.page.login(self.username, self.password)
|
||||||
|
|
||||||
if self.is_on_page(LoginPage):
|
if self.is_on_page(LoginPage):
|
||||||
raise BrowserIncorrectPassword()
|
raise BrowserIncorrectPassword()
|
||||||
|
|
||||||
#after login, we might be redirected to the two factor
|
#after login, we might be redirected to the two factor
|
||||||
#authentication page
|
#authentication page
|
||||||
#print "handle authentication"
|
self.handle_authentication()
|
||||||
self.handle_authentication()
|
|
||||||
|
|
||||||
self.location('/comptes/synthese.phtml', no_login=True)
|
self.location('/comptes/synthese.phtml', no_login=True)
|
||||||
|
|
||||||
|
|
@ -107,6 +115,8 @@ class Boursorama(Browser):
|
||||||
raise BrowserIncorrectAuthenticationCode()
|
raise BrowserIncorrectAuthenticationCode()
|
||||||
|
|
||||||
def get_accounts_list(self):
|
def get_accounts_list(self):
|
||||||
|
if self.is_on_page(AuthenticationPage):
|
||||||
|
self.login()
|
||||||
if not self.is_on_page(AccountsList):
|
if not self.is_on_page(AccountsList):
|
||||||
self.location('/comptes/synthese.phtml')
|
self.location('/comptes/synthese.phtml')
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,15 +41,12 @@ class BoursoramaModule(Module, CapBank):
|
||||||
ValueBackendPassword('password', label='Mot de passe'),
|
ValueBackendPassword('password', label='Mot de passe'),
|
||||||
ValueBool('enable_twofactors', label='Send validation sms', default=False),
|
ValueBool('enable_twofactors', label='Send validation sms', default=False),
|
||||||
Value('device', label='Device name', regexp='\w*', default=''),
|
Value('device', label='Device name', regexp='\w*', default=''),
|
||||||
|
Value('pin_code', label='Sms code', required=False),
|
||||||
)
|
)
|
||||||
BROWSER = Boursorama
|
BROWSER = Boursorama
|
||||||
|
|
||||||
def create_default_browser(self):
|
def create_default_browser(self):
|
||||||
return self.create_browser(
|
return self.create_browser(self.config)
|
||||||
self.config["device"].get()
|
|
||||||
, self.config["enable_twofactors"].get()
|
|
||||||
, self.config['login'].get()
|
|
||||||
, self.config['password'].get())
|
|
||||||
|
|
||||||
def iter_accounts(self):
|
def iter_accounts(self):
|
||||||
for account in self.browser.get_accounts_list():
|
for account in self.browser.get_accounts_list():
|
||||||
|
|
|
||||||
|
|
@ -17,23 +17,55 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
# along with weboob. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from weboob.deprecated.browser import Page, BrowserIncorrectPassword
|
|
||||||
import urllib2
|
|
||||||
import re
|
import re
|
||||||
|
import urllib2
|
||||||
|
|
||||||
|
from weboob.exceptions import BrowserToBeContinued
|
||||||
|
from weboob.deprecated.browser import Page, BrowserIncorrectPassword
|
||||||
|
|
||||||
class BrowserAuthenticationCodeMaxLimit(BrowserIncorrectPassword):
|
class BrowserAuthenticationCodeMaxLimit(BrowserIncorrectPassword):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationPage(Page):
|
class AuthenticationPage(Page):
|
||||||
MAX_LIMIT = "vous avez atteint le nombre maximum "\
|
MAX_LIMIT = r"vous avez atteint le nombre maximum "\
|
||||||
"d'utilisation de l'authentification forte."
|
"d'utilisation de l'authentification forte."
|
||||||
|
SECURE_PAGE = "https://www.boursorama.com/comptes/connexion/securisation/index.phtml"
|
||||||
|
REFERER = SECURE_PAGE
|
||||||
|
|
||||||
|
headers = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows "
|
||||||
|
"NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"
|
||||||
|
" GTB7.1 (.NET CLR 3.5.30729)",
|
||||||
|
"Referer": REFERER,
|
||||||
|
}
|
||||||
|
|
||||||
|
headers_ajax = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows "
|
||||||
|
"NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"
|
||||||
|
" GTB7.1 (.NET CLR 3.5.30729)",
|
||||||
|
"Accept": "application/json",
|
||||||
|
"X-Requested-With": "XMLHttpRequest",
|
||||||
|
"X-Request": "JSON",
|
||||||
|
"X-Brs-Xhr-Request": "true",
|
||||||
|
"X-Brs-Xhr-Schema": "DATA+OUT",
|
||||||
|
"Referer": REFERER,
|
||||||
|
}
|
||||||
|
|
||||||
def on_loaded(self):
|
def on_loaded(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def authenticate(self, device):
|
def authenticate(self):
|
||||||
|
url = "https://" + self.browser.DOMAIN + "/ajax/banque/otp.phtml"
|
||||||
|
data = "authentificationforteToken=%s&authentificationforteStep=otp&alertType=10100&org=%s&otp=%s&validate=" % (self.browser.auth_token, self.REFERER, self.browser.config['pin_code'].get())
|
||||||
|
req = urllib2.Request(url, data, self.headers_ajax)
|
||||||
|
response = self.browser.open(req)
|
||||||
|
|
||||||
|
url = "%s?" % (self.SECURE_PAGE)
|
||||||
|
data = "org=/&device=%s" % (self.browser.config['device'].get())
|
||||||
|
req = urllib2.Request(url, data, headers=self.headers)
|
||||||
|
response = self.browser.open(req)
|
||||||
|
self.browser.auth_token = None
|
||||||
|
|
||||||
|
def send_sms(self):
|
||||||
"""This function simulates the registration of a device on
|
"""This function simulates the registration of a device on
|
||||||
boursorama two factor authentification web page.
|
boursorama two factor authentification web page.
|
||||||
I
|
I
|
||||||
|
|
@ -41,73 +73,26 @@ class AuthenticationPage(Page):
|
||||||
@exception BrowserAuthenticationCodeMaxLimit when daily limit is consumed
|
@exception BrowserAuthenticationCodeMaxLimit when daily limit is consumed
|
||||||
@exception BrowserIncorrectAuthenticationCode when code is not correct
|
@exception BrowserIncorrectAuthenticationCode when code is not correct
|
||||||
"""
|
"""
|
||||||
DOMAIN = self.browser.DOMAIN
|
url = "https://%s/ajax/banque/otp.phtml?org=%s&alertType=10100" % (self.browser.DOMAIN, self.REFERER)
|
||||||
SECURE_PAGE = "https://www.boursorama.com/comptes/connexion/securisation/index.phtml"
|
req = urllib2.Request(url, headers=self.headers_ajax)
|
||||||
REFERER = SECURE_PAGE
|
|
||||||
|
|
||||||
#print "Need to authenticate for device", device
|
|
||||||
#print "Domain information", DOMAIN
|
|
||||||
|
|
||||||
url = "https://%s/ajax/banque/otp.phtml?org=%s&alertType=10100" % (DOMAIN, REFERER)
|
|
||||||
#print url
|
|
||||||
headers = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows "
|
|
||||||
"NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"
|
|
||||||
" GTB7.1 (.NET CLR 3.5.30729)",
|
|
||||||
"Referer": REFERER,
|
|
||||||
}
|
|
||||||
|
|
||||||
headers_ajax = {"User-Agent": "Mozilla/5.0 (Windows; U; Windows "
|
|
||||||
"NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"
|
|
||||||
" GTB7.1 (.NET CLR 3.5.30729)",
|
|
||||||
"Accept": "application/json",
|
|
||||||
"X-Requested-With": "XMLHttpRequest",
|
|
||||||
"X-Request": "JSON",
|
|
||||||
"X-Brs-Xhr-Request": "true",
|
|
||||||
"X-Brs-Xhr-Schema": "DATA+OUT",
|
|
||||||
"Referer": REFERER,
|
|
||||||
}
|
|
||||||
|
|
||||||
req = urllib2.Request(url, headers=headers_ajax)
|
|
||||||
response = self.browser.open(req)
|
response = self.browser.open(req)
|
||||||
#extrat authentication token from response (in form)
|
#extrat authentication token from response (in form)
|
||||||
info = response.read()
|
info = response.read()
|
||||||
|
|
||||||
regex = re.compile(r"vous avez atteint le nombre maximum d'utilisation de l'authentification forte.")
|
regex = re.compile(self.MAX_LIMIT)
|
||||||
r = regex.search(info)
|
r = regex.search(info)
|
||||||
if r:
|
if r:
|
||||||
self.logger.info("Boursorama - Vous avez atteint le nombre maximum d'utilisation de l'authentification forte")
|
self.logger.info("Boursorama - Vous avez atteint le nombre maximum d'utilisation de l'authentification forte")
|
||||||
raise BrowserAuthenticationCodeMaxLimit()
|
raise BrowserAuthenticationCodeMaxLimit()
|
||||||
|
|
||||||
#print "Response from initial request,", len(info), response.info()
|
|
||||||
regex = re.compile(r"name=\\\"authentificationforteToken\\\" "
|
regex = re.compile(r"name=\\\"authentificationforteToken\\\" "
|
||||||
r"value=\\\"(?P<value>\w*?)\\\"")
|
r"value=\\\"(?P<value>\w*?)\\\"")
|
||||||
r = regex.search(info)
|
r = regex.search(info)
|
||||||
token = r.group('value')
|
self.browser.auth_token = r.group('value')
|
||||||
#print "Extracted token", token
|
|
||||||
|
|
||||||
#step2
|
#step2
|
||||||
url = "https://" + DOMAIN + "/ajax/banque/otp.phtml"
|
url = "https://" + self.browser.DOMAIN + "/ajax/banque/otp.phtml"
|
||||||
data = "authentificationforteToken=%s&authentificationforteStep=start&alertType=10100&org=%s&validate=" % (token, REFERER)
|
data = "authentificationforteToken=%s&authentificationforteStep=start&alertType=10100&org=%s&validate=" % (self.browser.auth_token, self.REFERER)
|
||||||
req = urllib2.Request(url, data, headers_ajax)
|
req = urllib2.Request(url, data, self.headers_ajax)
|
||||||
response = self.browser.open(req)
|
response = self.browser.open(req)
|
||||||
#info = response.read()
|
raise BrowserToBeContinued('pin_code')
|
||||||
#print "after asking to send token authentification" \
|
|
||||||
# ,len(info), response.info()
|
|
||||||
|
|
||||||
|
|
||||||
pin = raw_input('Enter the "Boursorama Banque" access code:')
|
|
||||||
#print "Pin access code: ''%s''" % (pin)
|
|
||||||
url = "https://" + DOMAIN + "/ajax/banque/otp.phtml"
|
|
||||||
data = "authentificationforteToken=%s&authentificationforteStep=otp&alertType=10100&org=%s&otp=%s&validate=" % (token, REFERER, pin)
|
|
||||||
req = urllib2.Request(url, data, headers_ajax)
|
|
||||||
response = self.browser.open(req)
|
|
||||||
#info = response.read()
|
|
||||||
#print "after pin authentification", len(info), response.info()
|
|
||||||
|
|
||||||
url = "%s?" % (SECURE_PAGE)
|
|
||||||
data = "org=/&device=%s" % (device)
|
|
||||||
req = urllib2.Request(url, data, headers=headers)
|
|
||||||
response = self.browser.open(req)
|
|
||||||
|
|
||||||
#result = response.read()
|
|
||||||
#print response, "\n", response.info()
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue