Skip to content

Instantly share code, notes, and snippets.

@wassname
Last active December 18, 2015 11:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wassname/63ae08d7776c8b891143 to your computer and use it in GitHub Desktop.
Save wassname/63ae08d7776c8b891143 to your computer and use it in GitHub Desktop.
Uses casperjs or ghost.py to get lync api tokens from https://ucwa.skype.com/login/explore
/*
* 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();
# -*- 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