Proper name spoofing protection (API change, no actual protection!) (#42)
* Working username fetching and db field also sends the username in authenticate_incoming_player * Update dev.env * Switch from using puppeteer to just http * Fix indentation * fail open instead of closed if i’m not mistaken, failing every time they auth will result in username being “null”, otherwise will remain as the previous value * should make the default username in db be empty string * Fix username fetch (added missing package) * Format * eslint pain * eslint pain episode 2 * switch to async func over promise * i removed by accident, makes it work again * allow origin stuff to be disabled * Add persistent sid cookie * remove newline in sid.cookie * automatic db upgrading using dbSchema.json * Catch origin auth error * Nicely do this instead * Save non-authed state when failing
This commit is contained in:
parent
85c0cd2966
commit
737c637c9f
|
@ -120,3 +120,9 @@ dist
|
|||
# db files
|
||||
.db
|
||||
playerdata.db
|
||||
|
||||
# ssl keys
|
||||
*.pem
|
||||
|
||||
# origin sid cookie
|
||||
sid.cookie
|
|
@ -3,6 +3,7 @@ const crypto = require( "crypto" )
|
|||
const { GetGameServers } = require( path.join( __dirname, "../shared/gameserver.js" ) )
|
||||
const accounts = require( path.join( __dirname, "../shared/accounts.js" ) )
|
||||
const asyncHttp = require( path.join( __dirname, "../shared/asynchttp.js" ) )
|
||||
const { getUserInfo, getOriginAuthState } = require( path.join( __dirname, "../shared/origin.js" ) )
|
||||
|
||||
let shouldRequireSessionToken = process.env.REQUIRE_SESSION_TOKEN = true
|
||||
|
||||
|
@ -75,6 +76,16 @@ module.exports = ( fastify, opts, done ) =>
|
|||
return { success: false, error: UNAUTHORIZED_GAME }
|
||||
}
|
||||
|
||||
let playerUsername
|
||||
try
|
||||
{
|
||||
if( getOriginAuthState() ) playerUsername = ( await getUserInfo( request.query.id ) ).EAID[0] // try to find username of player
|
||||
}
|
||||
catch( e )
|
||||
{
|
||||
// don't do this: return { success: false } // fail if we can't find it
|
||||
}
|
||||
|
||||
let account = await accounts.AsyncGetPlayerByID( request.query.id )
|
||||
if ( !account ) // create account for user
|
||||
{
|
||||
|
@ -85,6 +96,8 @@ module.exports = ( fastify, opts, done ) =>
|
|||
let authToken = crypto.randomBytes( 16 ).toString( "hex" )
|
||||
accounts.AsyncUpdateCurrentPlayerAuthToken( account.id, authToken )
|
||||
|
||||
if ( playerUsername ) accounts.AsyncUpdatePlayerUsername( account.id, playerUsername )
|
||||
|
||||
accounts.AsyncUpdatePlayerAuthIp( account.id, request.ip )
|
||||
|
||||
return {
|
||||
|
@ -140,7 +153,7 @@ module.exports = ( fastify, opts, done ) =>
|
|||
method: "POST",
|
||||
host: server.ip,
|
||||
port: server.authPort,
|
||||
path: `/authenticate_incoming_player?id=${request.query.id}&authToken=${authToken}&serverAuthToken=${server.serverAuthToken}`
|
||||
path: `/authenticate_incoming_player?id=${request.query.id}&authToken=${authToken}&serverAuthToken=${server.serverAuthToken}&username=${account.username}`
|
||||
}, pdata )
|
||||
}
|
||||
catch
|
||||
|
@ -160,6 +173,7 @@ module.exports = ( fastify, opts, done ) =>
|
|||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
ip: server.ip,
|
||||
port: server.port,
|
||||
authToken: authToken
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
{
|
||||
"accounts": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "TEXT",
|
||||
"modifier": "PRIMARY KEY NOT NULL"
|
||||
},
|
||||
{
|
||||
"name": "currentAuthToken",
|
||||
"type": "TEXT"
|
||||
},
|
||||
{
|
||||
"name": "currentAuthTokenExpirationTime",
|
||||
"type": "INTEGER"
|
||||
},
|
||||
{
|
||||
"name": "currentServerId",
|
||||
"type": "TEXT"
|
||||
},
|
||||
{
|
||||
"name": "persistentDataBaseline",
|
||||
"type": "BLOB",
|
||||
"modifier": "NOT NULL"
|
||||
},
|
||||
{
|
||||
"name": "lastAuthIp",
|
||||
"type": "TEXT"
|
||||
},
|
||||
{
|
||||
"name": "username",
|
||||
"type": "TEXT",
|
||||
"modifier": "DEFAULT ''"
|
||||
}
|
||||
]
|
||||
},
|
||||
"modPersistentData": {
|
||||
"columns": [
|
||||
{
|
||||
"name": "id",
|
||||
"type": "TEXT",
|
||||
"modifier": "NOT NULL"
|
||||
},
|
||||
{
|
||||
"name": "pdiffHash",
|
||||
"type": "TEXT",
|
||||
"modifier": "NOT NULL"
|
||||
},
|
||||
{
|
||||
"name": "data",
|
||||
"type": "TEXT",
|
||||
"modifier": "NOT NULL"
|
||||
}
|
||||
],
|
||||
"extra": "PRIMARY KEY ( id, pdiffHash )"
|
||||
}
|
||||
}
|
6
dev.env
6
dev.env
|
@ -27,3 +27,9 @@ REQ_PER_MINUTE__SERVER_HEARTBEAT=60
|
|||
REQ_PER_MINUTE__SERVER_UPDATEVALUES=20
|
||||
REQ_PER_MINUTE__SERVER_REMOVESERVER=5
|
||||
REQ_PER_MINUTE__ACCOUNT_WRITEPERSISTENCE=50
|
||||
|
||||
# origin
|
||||
ORIGIN_ENABLE=1
|
||||
ORIGIN_PERSIST_SID=1
|
||||
ORIGIN_EMAIL=
|
||||
ORIGIN_PASSWORD=
|
|
@ -14,7 +14,8 @@
|
|||
"fastify-multipart": "^5.1.0",
|
||||
"fastify-rate-limit": "^5.7.0",
|
||||
"fastify-static": "^4.5.0",
|
||||
"sqlite3": "^5.0.2"
|
||||
"sqlite3": "^5.0.2",
|
||||
"xml2js": "^0.4.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.6.0",
|
||||
|
@ -788,9 +789,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
|
@ -3792,6 +3793,26 @@
|
|||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
||||
"dependencies": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
@ -4403,9 +4424,9 @@
|
|||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
|
||||
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
|
||||
"integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
|
@ -6745,6 +6766,20 @@
|
|||
"integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==",
|
||||
"dev": true
|
||||
},
|
||||
"xml2js": {
|
||||
"version": "0.4.23",
|
||||
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz",
|
||||
"integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==",
|
||||
"requires": {
|
||||
"sax": ">=0.6.0",
|
||||
"xmlbuilder": "~11.0.0"
|
||||
}
|
||||
},
|
||||
"xmlbuilder": {
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA=="
|
||||
},
|
||||
"yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
|
|
|
@ -22,7 +22,8 @@
|
|||
"fastify-multipart": "^5.1.0",
|
||||
"fastify-rate-limit": "^5.7.0",
|
||||
"fastify-static": "^4.5.0",
|
||||
"sqlite3": "^5.0.2"
|
||||
"sqlite3": "^5.0.2",
|
||||
"xml2js": "^0.4.23"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.6.0",
|
||||
|
|
|
@ -7,7 +7,10 @@ const DEFAULT_PDATA_BASELINE = fs.readFileSync( "default.pdata" )
|
|||
// const pjson = require( path.join( __dirname, "../shared/pjson.js" ) )
|
||||
// const DEFAULT_PDEF_OBJECT = pjson.ParseDefinition( fs.readFileSync( "persistent_player_data_version_231.pdef" ).toString() )
|
||||
|
||||
let playerDB = new sqlite.Database( "playerdata.db", sqlite.OPEN_CREATE | sqlite.OPEN_READWRITE, ex =>
|
||||
const dbSchemaRaw = fs.readFileSync( "./dbSchema.json" )
|
||||
const dbSchema = JSON.parse( dbSchemaRaw )
|
||||
|
||||
let playerDB = new sqlite.Database( "playerdata.db", sqlite.OPEN_CREATE | sqlite.OPEN_READWRITE, async ex =>
|
||||
{
|
||||
if ( ex )
|
||||
console.error( ex )
|
||||
|
@ -18,12 +21,11 @@ let playerDB = new sqlite.Database( "playerdata.db", sqlite.OPEN_CREATE | sqlite
|
|||
// this should mirror the PlayerAccount class's properties
|
||||
playerDB.run( `
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
id TEXT PRIMARY KEY NOT NULL,
|
||||
currentAuthToken TEXT,
|
||||
currentAuthTokenExpirationTime INTEGER,
|
||||
currentServerId TEXT,
|
||||
persistentDataBaseline BLOB NOT NULL,
|
||||
lastAuthIp TEXT
|
||||
${ dbSchema.accounts.columns.map( ( col ) =>
|
||||
{
|
||||
return `${col.name} ${col.type} ${col.modifier ? col.modifier : ""}`
|
||||
} ).join( ",\n\r\t\t" ) }
|
||||
${ dbSchema.accounts.extra ? ","+dbSchema.accounts.extra : "" }
|
||||
)
|
||||
`, ex =>
|
||||
{
|
||||
|
@ -37,10 +39,11 @@ let playerDB = new sqlite.Database( "playerdata.db", sqlite.OPEN_CREATE | sqlite
|
|||
// this should mirror the PlayerAccount class's properties
|
||||
playerDB.run( `
|
||||
CREATE TABLE IF NOT EXISTS modPersistentData (
|
||||
id TEXT NOT NULL,
|
||||
pdiffHash TEXT NOT NULL,
|
||||
data TEXT NOT NULL,
|
||||
PRIMARY KEY ( id, pdiffHash )
|
||||
${ dbSchema.modPersistentData.columns.map( ( col ) =>
|
||||
{
|
||||
return `${col.name} ${col.type} ${col.modifier ? col.modifier : ""}`
|
||||
} ).join( ",\n\r\t\t" ) }
|
||||
${ dbSchema.modPersistentData.extra ? ","+dbSchema.modPersistentData.extra : "" }
|
||||
)
|
||||
`, ex =>
|
||||
{
|
||||
|
@ -49,6 +52,23 @@ let playerDB = new sqlite.Database( "playerdata.db", sqlite.OPEN_CREATE | sqlite
|
|||
else
|
||||
console.log( "Created mod persistent data table successfully" )
|
||||
} )
|
||||
|
||||
for ( const col of dbSchema.accounts.columns )
|
||||
{
|
||||
if( !await columnExists( "accounts", col.name ) )
|
||||
{
|
||||
console.log( `The 'accounts' table is missing the '${col.name}' column` )
|
||||
await addColumnToTable( "accounts", col )
|
||||
}
|
||||
}
|
||||
for ( const col of dbSchema.modPersistentData.columns )
|
||||
{
|
||||
if( !await columnExists( "modPersistentData", col.name ) )
|
||||
{
|
||||
console.log( `The 'modPersistentData' table is missing the '${col.name}' column` )
|
||||
await addColumnToTable( "modPersistentData", col )
|
||||
}
|
||||
}
|
||||
} )
|
||||
|
||||
function asyncDBGet( sql, params = [] )
|
||||
|
@ -85,6 +105,49 @@ function asyncDBRun( sql, params = [] )
|
|||
} )
|
||||
}
|
||||
|
||||
function columnExists( tableName, colName )
|
||||
{
|
||||
return new Promise( ( resolve, reject ) =>
|
||||
{
|
||||
playerDB.get( `
|
||||
SELECT COUNT(*) AS CNTREC FROM pragma_table_info('${tableName}') WHERE name='${colName}'
|
||||
`, [], ( ex, row ) =>
|
||||
{
|
||||
if ( ex )
|
||||
{
|
||||
console.error( "Encountered error querying database: " + ex )
|
||||
reject( ex )
|
||||
}
|
||||
else
|
||||
{
|
||||
resolve( row.CNTREC == 1 )
|
||||
}
|
||||
} )
|
||||
} )
|
||||
}
|
||||
|
||||
function addColumnToTable( tableName, column )
|
||||
{
|
||||
return new Promise( ( resolve, reject ) =>
|
||||
{
|
||||
playerDB.run( `
|
||||
ALTER TABLE ${tableName} ADD COLUMN ${column.name} ${column.type} ${column.modifier ? column.modifier : ""}
|
||||
`, ex =>
|
||||
{
|
||||
if ( ex )
|
||||
{
|
||||
console.error( "Encountered error adding column to database: " + ex )
|
||||
reject( ex )
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log( `Added '${column.name}' column to the '${tableName}' table` )
|
||||
resolve()
|
||||
}
|
||||
} )
|
||||
} )
|
||||
}
|
||||
|
||||
class PlayerAccount
|
||||
{
|
||||
// mirrors account struct in db
|
||||
|
@ -95,7 +158,7 @@ class PlayerAccount
|
|||
// string currentServerId
|
||||
// Buffer persistentDataBaseline
|
||||
|
||||
constructor ( id, currentAuthToken, currentAuthTokenExpirationTime, currentServerId, persistentDataBaseline, lastAuthIp )
|
||||
constructor ( id, currentAuthToken, currentAuthTokenExpirationTime, currentServerId, persistentDataBaseline, lastAuthIp, username )
|
||||
{
|
||||
this.id = id
|
||||
this.currentAuthToken = currentAuthToken
|
||||
|
@ -103,6 +166,7 @@ class PlayerAccount
|
|||
this.currentServerId = currentServerId
|
||||
this.persistentDataBaseline = persistentDataBaseline
|
||||
this.lastAuthIp = lastAuthIp
|
||||
this.username = username
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,7 +178,7 @@ module.exports = {
|
|||
if ( !row )
|
||||
return null
|
||||
|
||||
return new PlayerAccount( row.id, row.currentAuthToken, row.currentAuthTokenExpirationTime, row.currentServerId, row.persistentDataBaseline, row.lastAuthIp )
|
||||
return new PlayerAccount( row.id, row.currentAuthToken, row.currentAuthTokenExpirationTime, row.currentServerId, row.persistentDataBaseline, row.lastAuthIp, row.username )
|
||||
},
|
||||
|
||||
AsyncCreateAccountForID: async function AsyncCreateAccountForID( id )
|
||||
|
@ -127,6 +191,11 @@ module.exports = {
|
|||
await asyncDBRun( "UPDATE accounts SET currentAuthToken = ?, currentAuthTokenExpirationTime = ? WHERE id = ?", [ token, Date.now() + TOKEN_EXPIRATION_TIME, id ] )
|
||||
},
|
||||
|
||||
AsyncUpdatePlayerUsername: async function AsyncUpdatePlayerUsername( id, username )
|
||||
{
|
||||
await asyncDBRun( "UPDATE accounts SET username = ? WHERE id = ?", [ username, id ] )
|
||||
},
|
||||
|
||||
AsyncUpdatePlayerAuthIp: async function AsyncUpdatePlayerAuthIp( id, lastAuthIp )
|
||||
{
|
||||
await asyncDBRun( "UPDATE accounts SET lastAuthIp = ? WHERE id = ?", [ lastAuthIp, id ] )
|
||||
|
|
|
@ -0,0 +1,212 @@
|
|||
let sidCookie
|
||||
let AuthToken
|
||||
let authed = false
|
||||
const fs = require( "fs" )
|
||||
const https = require( "https" )
|
||||
const { parseString } = require( "xml2js" )
|
||||
|
||||
async function authWithOrigin()
|
||||
{ // thanks to r-ex for the help
|
||||
const fidURL = "https://accounts.ea.com/connect/auth?response_type=code&client_id=ORIGIN_SPA_ID&display=originXWeb/login&locale=en_US&release_type=prod&redirect_uri=https://www.origin.com/views/login.html"
|
||||
const loginURL = "https://accounts.ea.com/connect/auth?client_id=ORIGIN_JS_SDK&response_type=token&redirect_uri=nucleus:rest&prompt=none&release_type=prod"
|
||||
|
||||
if( !sidCookie )
|
||||
{
|
||||
let fidLocation = ( await GetHeaders( fidURL ) )["location"]
|
||||
// let fid = fidLocation.match(/(?<=fid=)[a-zA-Z0-9]+?(?=&|$)/g)[0];
|
||||
let jSessionIDheaders = await GetHeaders( fidLocation )
|
||||
let jSessionID = jSessionIDheaders["set-cookie"].join( "; " ).match( /(?<=JSESSIONID=)[\S]+?(?=;)/g )[0]
|
||||
let signinCookie = jSessionIDheaders["set-cookie"].join( "; " ).match( /(?<=signin-cookie=)[\S]+?(?=;)/g )[0]
|
||||
let jSessionLocation = `https://signin.ea.com${jSessionIDheaders["location"]}`
|
||||
|
||||
// AuthorizeLogin
|
||||
let authData = {
|
||||
"email": process.env.ORIGIN_EMAIL,
|
||||
"password": process.env.ORIGIN_PASSWORD,
|
||||
"_eventId": "submit",
|
||||
"cid": GenerateCID(),
|
||||
"showAgeUp": "true",
|
||||
"thirdPartyCaptchaResponse": "",
|
||||
"_rememberMe": "on",
|
||||
"rememberMe": "on"
|
||||
}
|
||||
let authResponse = await PostData( jSessionLocation, authData, {"Cookie": [`JSESSIONID=${jSessionID}`, `signin-cookie=${signinCookie}`]} )
|
||||
let authResLocation = authResponse.toString().match( /(?<=window\.location = ")\S+(?=";)/g )[0]
|
||||
let sidHeaders = await GetHeaders( authResLocation, {"Cookie": [`JSESSIONID=${jSessionID}`, `signin-cookie=${signinCookie}`]} )
|
||||
sidCookie = sidHeaders["set-cookie"].join( "; " ).match( /(?<=sid=)[\S]+?(?=;)/g )[0]
|
||||
}
|
||||
let authTokenRes = await GetData( loginURL, {"Cookie": [`sid=${sidCookie}`]} )
|
||||
let authResJson = JSON.parse( authTokenRes.toString() )
|
||||
|
||||
if( authResJson.error )
|
||||
{
|
||||
authed = false
|
||||
console.log( `Error authing with Origin: '${authResJson.error}'` )
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
AuthToken = authResJson.access_token
|
||||
console.log( "Successfully got Origin auth token" )
|
||||
authed = true
|
||||
|
||||
if( process.env.ORIGIN_PERSIST_SID )
|
||||
{
|
||||
fs.writeFile( "./sid.cookie", sidCookie, ( err ) =>
|
||||
{
|
||||
if( err ) console.log( "Failed to save Origin sid cookie" )
|
||||
else console.log( "Saved Origin sid cookie" )
|
||||
} )
|
||||
}
|
||||
|
||||
setTimeout( authWithOrigin, Number( authResJson.expires_in )*1000 - 60000 ) // Refresh access token 1 minute before it expires just to be safe
|
||||
}
|
||||
}
|
||||
|
||||
if( process.env.ORIGIN_ENABLE )
|
||||
{
|
||||
console.log( "Attempting to auth with Origin" )
|
||||
if( process.env.ORIGIN_PERSIST_SID && fs.existsSync( "./sid.cookie" ) )
|
||||
{
|
||||
console.log( "Found Origin sid cookie, reading data" )
|
||||
sidCookie = fs.readFileSync( "./sid.cookie", "utf-8" ).replace( /\r?\n|\r/g, "" )
|
||||
}
|
||||
authWithOrigin()
|
||||
}
|
||||
|
||||
function GenerateCID()
|
||||
{
|
||||
var l = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz"
|
||||
var h = 32
|
||||
var j = ""
|
||||
for ( var k = 0; k < h; k++ )
|
||||
{
|
||||
var m = Math.floor( Math.random() * l.length )
|
||||
j += l.substring( m, m + 1 )
|
||||
}
|
||||
return j
|
||||
}
|
||||
|
||||
function GetHeaders( location, headers = {} )
|
||||
{
|
||||
return new Promise( resolve =>
|
||||
{
|
||||
let params = { headers }
|
||||
let href = new URL( location )
|
||||
params.host = href.host
|
||||
params.path = href.pathname + href.search
|
||||
https.get( params, reqResult =>
|
||||
{
|
||||
resolve( reqResult.headers )
|
||||
} )
|
||||
} )
|
||||
}
|
||||
function GetData( location, headers = {} )
|
||||
{
|
||||
return new Promise( resolve =>
|
||||
{
|
||||
let params = { headers }
|
||||
let href = new URL( location )
|
||||
params.host = href.host
|
||||
params.path = href.pathname + href.search
|
||||
https.get( params, reqResult =>
|
||||
{
|
||||
let data = []
|
||||
reqResult.on( "data", c => data.push( c ) )
|
||||
// eslint-disable-next-line
|
||||
reqResult.on( "end", _ => resolve( Buffer.concat( data ) ) )
|
||||
} )
|
||||
} )
|
||||
}
|
||||
|
||||
// data must be an object to be sent as x-www-form-urlencoded
|
||||
function PostData( location, postData, headers = {} )
|
||||
{
|
||||
return new Promise( ( resolve, reject ) =>
|
||||
{
|
||||
let params = { headers }
|
||||
let href = new URL( location )
|
||||
params.method = "POST"
|
||||
|
||||
params.host = href.host
|
||||
params.path = href.pathname + href.search
|
||||
|
||||
if ( postData )
|
||||
{
|
||||
var body = new URLSearchParams()
|
||||
for( var name in postData )
|
||||
{
|
||||
body.append( name, postData[name] )
|
||||
}
|
||||
|
||||
headers["Content-Length"] = body.toString().length
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
}
|
||||
let req = https.request( params, reqResult =>
|
||||
{
|
||||
let data = []
|
||||
reqResult.on( "data", c => data.push( c ) )
|
||||
// eslint-disable-next-line
|
||||
reqResult.on( "end", _ => resolve( Buffer.concat( data ) ) )
|
||||
} )
|
||||
|
||||
req.on( "error", e =>
|
||||
{
|
||||
reject( e )
|
||||
} )
|
||||
|
||||
if ( postData )
|
||||
{
|
||||
req.write( body.toString() )
|
||||
}
|
||||
|
||||
req.end()
|
||||
} )
|
||||
}
|
||||
|
||||
const asyncHttp = require( "./asynchttp.js" )
|
||||
|
||||
async function getUserInfo( uid )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( !authed || !AuthToken ) return
|
||||
|
||||
let response = await asyncHttp.request( {
|
||||
method: "GET",
|
||||
host: "https://api1.origin.com",
|
||||
port: 443,
|
||||
path: `/atom/users?userIds=${uid}`,
|
||||
headers: { "AuthToken": AuthToken }
|
||||
} )
|
||||
|
||||
let json
|
||||
try
|
||||
{
|
||||
json = await new Promise( resolve =>
|
||||
{
|
||||
parseString( response.toString(), function ( err, result )
|
||||
{
|
||||
resolve( result )
|
||||
} )
|
||||
} )
|
||||
}
|
||||
catch ( error )
|
||||
{
|
||||
return
|
||||
}
|
||||
return json.users.user[0]
|
||||
}
|
||||
catch ( error )
|
||||
{
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getOriginAuthState: function getOriginAuthState()
|
||||
{
|
||||
return authed
|
||||
},
|
||||
getUserInfo
|
||||
}
|
Loading…
Reference in New Issue