|
|
@@ -0,0 +1,219 @@
|
|
|
+const request = require('request')
|
|
|
+
|
|
|
+const minecraftAgent = {
|
|
|
+ name: 'Minecraft',
|
|
|
+ version: 1
|
|
|
+}
|
|
|
+const authpath = 'https://authserver.mojang.com'
|
|
|
+const statuses = [
|
|
|
+ {
|
|
|
+ service: 'minecraft.net',
|
|
|
+ status: 'grey',
|
|
|
+ name: 'Minecraft.net'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ service: 'api.mojang.com',
|
|
|
+ status: 'grey',
|
|
|
+ name: 'Public API'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ service: 'textures.minecraft.net',
|
|
|
+ status: 'grey',
|
|
|
+ name: 'Minecraft Skins'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ service: 'authserver.mojang.com',
|
|
|
+ status: 'grey',
|
|
|
+ name: 'Authentication Service'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ service: 'sessionserver.mojang.com',
|
|
|
+ status: 'grey',
|
|
|
+ name: 'Multiplayer Session Service'
|
|
|
+ },
|
|
|
+ {
|
|
|
+ service: 'account.mojang.com',
|
|
|
+ status: 'grey',
|
|
|
+ name: 'Mojang accounts website'
|
|
|
+ }
|
|
|
+]
|
|
|
+
|
|
|
+/**
|
|
|
+ * Converts a Mojang status color to a hex value. Valid statuses
|
|
|
+ * are 'green', 'yellow', 'red', and 'grey'. Grey is a custom status
|
|
|
+ * to our project which represends an unknown status.
|
|
|
+ *
|
|
|
+ * @param {String} status - a valid status code.
|
|
|
+ * @returns {String} - the hex color of the status code.
|
|
|
+ */
|
|
|
+exports.statusToHex = function(status){
|
|
|
+ switch(status.toLowerCase()){
|
|
|
+ case 'green':
|
|
|
+ return '#a5c325'
|
|
|
+ case 'yellow':
|
|
|
+ return '#eac918'
|
|
|
+ case 'red':
|
|
|
+ return '#c32625'
|
|
|
+ case 'grey':
|
|
|
+ default:
|
|
|
+ return '#848484'
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Retrieves the status of Mojang's services.
|
|
|
+ * The response is condensed into a single object. Each service is
|
|
|
+ * a key, where the value is an object containing a status and name
|
|
|
+ * property.
|
|
|
+ *
|
|
|
+ * @see http://wiki.vg/Mojang_API#API_Status
|
|
|
+ */
|
|
|
+exports.status = function(){
|
|
|
+ return new Promise(function(fulfill, reject) {
|
|
|
+ request.get('https://status.mojang.com/check',
|
|
|
+ {
|
|
|
+ json: true
|
|
|
+ },
|
|
|
+ function(error, response, body){
|
|
|
+ if(response.statusCode === 200){
|
|
|
+ for(let i=0; i<body.length; i++){
|
|
|
+ const key = Object.keys(body[i])[0]
|
|
|
+ inner:
|
|
|
+ for(let j=0; j<statuses.length; j++){
|
|
|
+ if(statuses[j].service === key) {
|
|
|
+ statuses[j].status = body[i][key]
|
|
|
+ break inner
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ fulfill(statuses)
|
|
|
+ } else {
|
|
|
+ reject()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Authenticate a user with their Mojang credentials.
|
|
|
+ *
|
|
|
+ * @param {String} username - user's username, this is often an email.
|
|
|
+ * @param {String} password - user's password.
|
|
|
+ * @param {String} clientToken - launcher's Client Token.
|
|
|
+ * @param {Boolean} requestUser - optional. Adds user object to the reponse.
|
|
|
+ * @param {Object} agent - optional. Provided by default. Adds user info to the response.
|
|
|
+ *
|
|
|
+ * @see http://wiki.vg/Authentication#Authenticate
|
|
|
+ */
|
|
|
+exports.authenticate = function(username, password, clientToken, requestUser = true, agent = minecraftAgent){
|
|
|
+ return new Promise(function(fulfill, reject){
|
|
|
+ request.post(authpath + '/authenticate',
|
|
|
+ {
|
|
|
+ json: true,
|
|
|
+ body: {
|
|
|
+ agent,
|
|
|
+ username,
|
|
|
+ password,
|
|
|
+ clientToken,
|
|
|
+ requestUser
|
|
|
+ }
|
|
|
+ },
|
|
|
+ function(error, response, body){
|
|
|
+ if(response.statusCode === 200){
|
|
|
+ fulfill(body)
|
|
|
+ } else {
|
|
|
+ reject()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Validate an access token. This should always be done before launching.
|
|
|
+ * The client token should match the one used to create the access token.
|
|
|
+ *
|
|
|
+ * @param {String} accessToken - the access token to validate.
|
|
|
+ * @param {String} clientToken - the launcher's client token.
|
|
|
+ *
|
|
|
+ * @see http://wiki.vg/Authentication#Validate
|
|
|
+ */
|
|
|
+exports.validate = function(accessToken, clientToken){
|
|
|
+ return new Promise(function(fulfill, reject){
|
|
|
+ request.post(authpath + '/validate',
|
|
|
+ {
|
|
|
+ json: true,
|
|
|
+ body: {
|
|
|
+ accessToken,
|
|
|
+ clientToken
|
|
|
+ }
|
|
|
+ },
|
|
|
+ function(error, response, body){
|
|
|
+ if(error && error.message === 'Invalid token'){
|
|
|
+ fulfill(false)
|
|
|
+ } else {
|
|
|
+ fulfill(true)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Invalidates an access token. The clientToken must match the
|
|
|
+ * token used to create the provided accessToken.
|
|
|
+ *
|
|
|
+ * @param {String} accessToken - the access token to invalidate.
|
|
|
+ * @param {String} clientToken - the launcher's client token.
|
|
|
+ *
|
|
|
+ * @see http://wiki.vg/Authentication#Invalidate
|
|
|
+ */
|
|
|
+exports.invalidate = function(accessToken, clientToken){
|
|
|
+ return new Promise(function(fulfill, reject){
|
|
|
+ request.post(authpath + '/invalidate',
|
|
|
+ {
|
|
|
+ json: true,
|
|
|
+ body: {
|
|
|
+ accessToken,
|
|
|
+ clientToken
|
|
|
+ }
|
|
|
+ },
|
|
|
+ function(error, response, body){
|
|
|
+ if(response.statusCode === 200){
|
|
|
+ fulfill()
|
|
|
+ } else {
|
|
|
+ reject()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Refresh a user's authentication. This should be used to keep a user logged
|
|
|
+ * in without asking them for their credentials again. A new access token will
|
|
|
+ * be generated using a recent invalid access token. See Wiki for more info.
|
|
|
+ *
|
|
|
+ * @param {String} accessToken - the old access token.
|
|
|
+ * @param {String} clientToken - the launcher's client token.
|
|
|
+ * @param {Boolean} requestUser - optional. Adds user object to the reponse.
|
|
|
+ *
|
|
|
+ * @see http://wiki.vg/Authentication#Refresh
|
|
|
+ */
|
|
|
+exports.refresh = function(accessToken, clientToken, requestUser = true){
|
|
|
+ return new Promise(function(fulfill, reject){
|
|
|
+ request.post(authpath + '/refresh',
|
|
|
+ {
|
|
|
+ json: true,
|
|
|
+ body: {
|
|
|
+ accessToken,
|
|
|
+ clientToken,
|
|
|
+ requestUser
|
|
|
+ }
|
|
|
+ },
|
|
|
+ function(error, response, body){
|
|
|
+ if(response.statusCode === 200){
|
|
|
+ fulfill(body)
|
|
|
+ } else {
|
|
|
+ reject()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|