Uses casperjs or ghost.py to get lync api tokens from https://ucwa.skype.com/login/explore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Uses casperjs to get api tokens from https://ucwa.skype.com/login/explore | |
* | |
* @outputs: | |
* this will output ucwaTokens.json to current directory | |
* | |
* If debug is true, then it will output screenshots to ./debug-images/<name>.png | |
* | |
* | |
* @run | |
* casperjs --ignore-ssl-errors=yes --ssl-protocol=any get_ucwa_tokens.js | |
* | |
*/ | |
var debug = true; | |
var terms_url = 'https://ucwa.skype.com/login/terms'; | |
var login_url = 'https://skypeucwa.accesscontrol.windows.net/v2/wsfederation?wa=wsignin1.0&wtrealm=https://ucwa.skype.com/'; | |
// check for credentias | |
var fs = require("fs"); | |
try { | |
var credentials = require('config/credentials.json'); | |
} catch (e) { | |
console.error("Place your credentials in credentials.json"); | |
throw e; | |
} | |
console.log('Found credentials, email: ', credentials.email); | |
var casper = require('casper').create({ | |
verbose: true, | |
logLevel: 'warning', | |
pageSettings: { | |
loadImages: false, // The WebPage instance used by Casper will | |
loadPlugins: false, // use these settings | |
userAgent: 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19', | |
javascriptEnabled: true, | |
// "webSecurityEnabled": false, | |
// "ignoreSslErrors": true, | |
// "sslProtocol":"any" | |
}, | |
viewportSize: { | |
width: 512, | |
height: 256 | |
}, | |
}); | |
var outFile = casper.cli.options['outfile']||'output/ucwaTokens.json'; | |
/*Callback to take a screenshot.*/ | |
function screenshot(name) { | |
var ts = new Date().getTime(); | |
var safeurl = casper.getTitle().replace(/[^a-z0-9]/gi, '_').toLowerCase(); | |
casper.capture("debug-images/screenshot_" + safeurl + '-' + ts + '.png'); | |
} | |
/* More information on resource errors such as proxy or ssl errors */ | |
casper.on("resource.error", function (resourceError) { | |
console.error('Unable to load resource (#' + resourceError.id + 'URL:' + resourceError.url + ')'); | |
console.error('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString); | |
screenshot(); | |
}); | |
if (debug) { | |
casper.on("load.finished", screenshot); | |
casper.on("load.failed", screenshot); | |
casper.on("waitFor.timeout", screenshot); | |
casper.on("fil", screenshot); | |
} | |
// load terms and conditions and click OK: receive a cookie | |
casper.start(terms_url); | |
casper.waitForSelector('form#form_terms'); // wait for form to appear | |
casper.then(function () { | |
console.log('Lync - Terms==', casper.getTitle()); | |
this.fillSelectors('form#form_terms', { | |
'#input_agree': 'Yes' | |
}, | |
true | |
); | |
}); | |
casper.waitWhileSelector('form#form_terms'); // wait for form to disappear | |
// login to live and receive a cookie | |
casper.thenOpen(login_url); | |
casper.waitForSelector('input[name=SI]'); | |
casper.then(function () { | |
console.log('Sign in to your Microsoft account==', casper.getTitle()); | |
casper.fillSelectors( | |
'form[name="f1"]', { | |
'input[name="loginfmt"]': credentials.email, | |
'input[name="passwd"]': credentials.password | |
}, | |
false | |
); | |
casper.click('input[name=SI]'); // we need this click to submit properly | |
}); | |
casper.waitWhileSelector('form[name=f1]'); | |
// now get tickets | |
casper.thenOpen('https://ucwa.skype.com/api/gettickets', { | |
method: 'get', | |
headers: { | |
'Accept': 'application/json' | |
} | |
}); | |
casper.then(function () { | |
var tokens = casper.getPageContent(); | |
var jsonTokens = JSON.parse(tokens); | |
if (!(jsonTokens.users && jsonTokens.users.length > 2)) { | |
throw 'Received json without expected form: ' + tokens; | |
} else { | |
console.log(JSON.stringify(jsonTokens, null, 2)); | |
} | |
// we use phantoms fs, not nodes http://phantomjs.org/api/fs/method/write.html | |
fs.write(outFile, tokens, 'w'); | |
console.log('Wrote api tokens to ', outFile); | |
}); | |
casper.run(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Login to live.com using ghost. | |
Usage: | |
`sh | |
set LIVE_EMAIL='me@live.com' | |
set LIVE_PASSWORD='feck' | |
python get_ucwa_tokens.py | |
` | |
Setup: | |
- Needs live.com email and password set as environmental variables | |
- Also requires [ghost.py which requires pyside or pyqt4.](https://github.com/jeanphix/Ghost.py) | |
Troubleshooting: | |
To debug, set display=True and run. You will be able to watch the browser. | |
""" | |
import os | |
import re | |
from ghost import Ghost | |
from ghost.bindings import QNetworkCookieJar | |
import json | |
def get_title(page): | |
"""Extract page title from html.""" | |
titles = re.findall('<title>(.+)</title>', page.content) | |
if titles: | |
return titles[0] | |
else: | |
return None | |
def get_tickets(outfile=None): | |
""" | |
Retrive api tickets from ucwa.skype.com/api/gettickets. | |
This uses ghost.py to login, accept terms, and get api tickets. | |
Args | |
outfile: optional location to write tickets (default None) | |
Returns: | |
json of tickets | |
Raises: | |
ValueError if MSLIVE_EMAIL or MSLIVE_PASSWORD is not present | |
ValueError if auth fails | |
""" | |
# TODO cache tickets | |
log_level = 'WARNING' | |
email = os.environ.get('MSLIVE_EMAIL') | |
password = os.environ.get('MSLIVE_PASSWORD') | |
if email is None or password is None: | |
raise ValueError( | |
"No live.com login and password in environmental variables MSLIVE_EMAIL and MSLIVE_PASSWORD") | |
ghost = Ghost(log_level=log_level) | |
kwargs = dict( | |
wait_timeout=30, | |
display=False, | |
plugins_enabled=False, | |
java_enabled=False, | |
download_images=False, | |
user_agent='Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3' | |
) | |
with ghost.start(**kwargs) as session: | |
# I shouldn't have to do this | |
session.cookie_jar = QNetworkCookieJar() | |
session.save_cookies(session.cookie_jar) | |
page, extra_resources = session.open( | |
"https://ucwa.skype.com/login/terms") | |
session.wait_for_selector('form#form_terms') | |
assert get_title(page) == 'Lync - Terms' | |
page, resources = session.click("button", expect_loading=True) | |
session.wait_while_selector('form#form_terms') | |
# now we should be redirected to login page, unless auth or recaptcha | |
# error | |
session.wait_for_selector('form[name=f1]') | |
assert get_title(page) == 'Sign in to your Microsoft account' | |
# fill wont work on email so I evaluate instead | |
session.evaluate( | |
'document.querySelector("input[name=loginfmt]").value="%s";' % email) | |
session.evaluate( | |
'document.querySelector("input[name=passwd]").value="%s";' % password) | |
page, extra_resources = session.click( | |
"input[name=SI]", expect_loading=True) | |
if get_title(page) == 'Sign in to your Microsoft account': | |
# raise auth errors | |
result, resources = session.evaluate(""" | |
var errs=document.querySelectorAll('.errorDiv'); | |
var res=[]; | |
for( var i=0;i<errs.length;i++){ | |
res.push(errs[i].textContent); | |
} | |
res | |
""") | |
raise ValueError(', '.join(result)) | |
session.wait_while_selector('form[name=f1]') | |
# Now get json tickets | |
page, extra_resources = session.open("https://ucwa.skype.com/api/gettickets", headers={ | |
'Accept': 'application/json' | |
}) | |
try: | |
tickets = json.loads(page.content) | |
except Exception as err: | |
print('Error: cant parse json: ', tickets) | |
raise err | |
assert page.http_status == 200 and 'users' in tickets | |
assert 'users' in tickets and len(tickets['users']) == 3 | |
if outfile: | |
with open(outfile, 'w') as fh: | |
json.dump(tickets, fh) | |
return tickets | |
if __name__ == "__main__": | |
print(get_tickets()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment