Skip to content

Instantly share code, notes, and snippets.

@almic
Last active February 2, 2022 07:21
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save almic/3795edc0e0143ef02fc400634313930f to your computer and use it in GitHub Desktop.
Save almic/3795edc0e0143ef02fc400634313930f to your computer and use it in GitHub Desktop.
The Node.js way for getting into the Halo MCC API.
const request = require('then-request')
// This is your microsoft live account information
const LOGIN = process.env.LOGIN // typically an email address
const PASSWD = process.env.PASSWD // typically your xbox live password
// This is the "api" we'll be calling once we login
const endpoint = 'https://www.halowaypoint.com/en-us/games/halo-the-master-chief-collection/xbox-one/' +
'game-history?gamertags=Furiousn00b&gameVariant=all&view=DataOnly'
// OAuth login link for halo waypoint
const oauth = 'https://login.live.com/oauth20_authorize.srf?client_id=000000004C0BD2F1' +
'&scope=xbox.basic+xbox.offline_access&response_type=code' +
'&redirect_uri=https:%2f%2fwww.halowaypoint.com%2fauth%2fcallback&locale=en-us' +
'&display=touch&state=https%253a%252f%252fwww.halowaypoint.com%252fen-us'
// These are for getting the unique data for session-based logins
const R_PPFT = /<input type="hidden" name="PPFT" id="i0327" value="(.+?)"\/>/
const R_POST = /urlPost:'(.+?)'/
// Encodes object into a data string
function stringify(obj) {
var result = ''
for (prop in obj) {
if (obj.hasOwnProperty(prop)) {
result += `&${encodeURIComponent(prop)}=${encodeURIComponent(obj[prop])}`
}
}
return result.substr(1)
}
// Helpful function to save our cookies
function storeCookies(array) {
var jar = []
const R_NAME = /^(.+?)=/
const R_VALUE = /=(.+?);/
for (cookie in array) {
cookie = array[cookie]
jar.push(`${cookie.match(R_NAME)[1]}=${cookie.match(R_VALUE)[1]};`)
}
return jar
}
request('GET', oauth).done(res => {
if (res.statusCode === 200) {
const cookies = storeCookies(res.headers['set-cookie'])
const body = res.body.toString('utf-8')
const ppft = body.match(R_PPFT)[1]
const post = body.match(R_POST)[1]
const data = stringify({
login: LOGIN,
passwd: PASSWD,
PPFT: ppft
})
console.log(`\nppft: ${ppft}\npost: ${post}\ndata: ${data}\n`)
request('POST', post, {
body: data,
headers: {
'cookie': cookies.join(''),
'content-type': 'application/x-www-form-urlencoded'
},
followRedirects: false // This is very important!
}).done(res => {
if (res.statusCode === 302) {
var location = res.headers.location
request('GET', location, {
followRedirects: false
}).done(res => {
if (res.statusCode === 302) {
// We ONLY care about the Auth cookie
var cookies = storeCookies(res.headers['set-cookie'])
var auth = ""
for (c in cookies) {
c = cookies[c]
if (c.startsWith('Auth=')) {
auth = c
}
}
console.log(`\n${auth}\n`)
request('GET', endpoint, {
headers: {'cookie': auth}
}).done(res => {
try {
res.json = JSON.parse(res.body.toString('utf-8'))
console.log(`\nResult: ${JSON.stringify(res.json)}\n`)
} catch (err) {
console.log('Response from endpoint was not valid JSON')
console.log(error)
}
})
} else {
console.error('Code retrieval did not return with a 302 status code.')
}
})
} else {
console.error('Login did not return with 302 status code.')
}
})
} else {
console.error('OAuth did not return with 200 status code.')
}
})

Important!

This example uses then-request, which you can install with npm install then-request However, any http library will work here.

The Halo Waypoint website requires only a valid "Auth" token/ cookie in order to access their "api."

To get an Auth token, you have to login to the website. You can try this now just by loggin in at www.halowaypoint.com, and you'll notice that after doing so you get an Auth cookie. For the past few years this has been the only requirement, so I'm sure it's not going to change anytime soon.

Lucky for you, this Auth cookie isn't very special, meaning that possibly hundreds can be used at the same time, because each new request to any "private" page on the website gives you a new Auth token to use. This is very good because it means you don't have to use the new Auth tokens! You can keep using the first one you get for a while before Waypoint requires you to login again, however you probably should be updating your token as often as possible, because this may extend the time between logins.

And because this Auth token isn't special, it means you can use your own account information without worrying about being logged out of your account on your own computer, or your script constantly having to log back in whenever you use your account else-where. After all, this is just OAuth.

The only downside to this is that each login can take multiple seconds, so saving your Auth token is absolutely essential for production environments. You can easily save the token in a database, and try using it later. If it works, awesome! You'll know when you need to login again because responses will not be valid JSON.

I highly recommend using your own account information, because it will make life much easier for yourself. Just be sure to not put your passwords in the source code!

I hope this helps anyone who looks for it!

Original Gist by @gitFurious: https://gist.github.com/gitFurious/28134b27414297681e29

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment