def submit_credentials(email, password): # Get and parse authorization webpage xml and form response = singletons.session().get(_authorization_url()) authorization_page_xml = response.text filtered_xml = _filter_tag(authorization_page_xml, 'script') filtered_xml = _filter_tag(filtered_xml, 'head') root = ET.fromstring(filtered_xml) form = root.find('.//form') for child in form: if child.attrib.get('name') == 'csrftoken2': csrftoken2 = child.attrib['value'] if child.attrib.get('name') == 'auth_request': auth_request = child.attrib['value'] if child.attrib.get('name') == 'web_redirect_url': web_redirect_url = child.attrib['value'] # Submit form data = { 'username': email, 'password': password, 'web_redirect_url': web_redirect_url, 'csrftoken2': csrftoken2, 'auth_request': auth_request, 'grant': 1, } url = '{}?{}'.format(settings.AUTHORIZATION_URL, urllib.urlencode(data)) response = singletons.session().post(url, allow_redirects=False) if response.status_code != 302: log.error('expecting a redirect') return False redirect_url = response.headers['location'] return redirect_url, auth_request, csrftoken2
def two_factor(redirect_url, auth_request, csrftoken2): '''Do the two factor auth dance. Return access_token or False. ''' log.info('Sending SMS verification ...') # Get two factor page response = singletons.session().get(redirect_url) # Send SMS secret = extract_otp_secret(response.text) headers = {'Venmo-Otp-Secret': secret} data = { 'via': 'sms', 'csrftoken2': csrftoken2, } url = '{}?{}'.format(settings.TWO_FACTOR_URL, urllib.urlencode(data)) response = singletons.session().post( url, headers=headers, ) assert response.status_code == 200, 'Post to 2FA failed' assert response.json()['data']['status'] == 'sent', 'SMS did not send' # Prompt verification code verification_code = raw_input('Verification code: ') if not verification_code: log.error('verification code required') return False # Submit verification code headers['Venmo-Otp'] = verification_code data = { 'auth_request': auth_request, 'csrftoken2': csrftoken2, } response = singletons.session().post( settings.TWO_FACTOR_AUTHORIZATION_URL, headers=headers, json=data, allow_redirects=False, ) if response.status_code != 200: log.error('verification code failed') return False # Retrieve access token location = response.json()['location'] code = location.split('code=')[1] access_token = retrieve_access_token(code) return access_token
def retrieve_access_token(code): data = { 'client_id': settings.CLIENT_ID, 'client_secret': settings.CLIENT_SECRET, 'code': code, } response = singletons.session().post(settings.ACCESS_TOKEN_URL, data) response_dict = response.json() access_token = response_dict['access_token'] return access_token
def search(query): response = singletons.session().get( settings.USERS_URL, params={ 'limit': 5, 'query': query, } ) users = response.json()['data'] results = [] for u in users: results.append({ 'id': u['id'], 'username': u['username'], 'display_name': u['display_name'], 'profile_picture_url': u['profile_picture_url'], }) return results
""" Authentication """ import ConfigParser import getpass import os import os.path import re import urllib import xml.etree.ElementTree as ET from venmo import settings, singletons session = singletons.session() def configure(args=None): """Get venmo ready to make payments. First, set username and password. If those change, then get access token. If that fails, unset username and password. Return whether or not we save an access token. """ changed = update_credentials() if not changed: return # Get and parse authorization webpage xml and form response = session.get(_authorization_url())
def exit_handler(): cookies.save(singletons.session().cookies)