Socket
Socket
Sign inDemoInstall

@xboxreplay/xboxlive-auth

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@xboxreplay/xboxlive-auth - npm Package Compare versions

Comparing version 3.3.3 to 4.0.0-beta.0

CHANGELOG.md

13

dist/config.d.ts

@@ -1,17 +0,10 @@

export declare const USER_AGENT: string;
declare const _default: {
request: {
baseHeaders: {
'Accept-encoding': string;
'Accept-Language': string;
'User-Agent': string;
};
defaultLanguage: string;
defaultUserAgent: string;
};
gitHubLinks: {
github: {
createIssue: string;
seeUserTokenIssue: string;
twoFactorAuthenticationError: string;
unauthorizedActivityError: string;
};
};
export default _default;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.USER_AGENT = [
'Mozilla/5.0 (XboxReplay; XboxLiveAuth/3.0)',
'AppleWebKit/537.36 (KHTML, like Gecko)',
'Chrome/71.0.3578.98 Safari/537.36'
].join(' ');
exports.default = {
request: {
baseHeaders: {
'Accept-encoding': 'gzip',
'Accept-Language': 'en-US',
'User-Agent': exports.USER_AGENT
}
defaultLanguage: 'en-US',
defaultUserAgent: `XboxReplay; XboxLiveAuth/4.0`
},
gitHubLinks: {
createIssue: 'https://bit.ly/xr-xbl-auth-create-issue',
seeUserTokenIssue: 'https://bit.ly/xr-xbl-auth-user-token-issue',
twoFactorAuthenticationError: 'https://bit.ly/xr-xbl-auth-err-2fa',
unauthorizedActivityError: 'https://bit.ly/xr-xbl-auth-err-activity'
github: {
createIssue: 'https://github.com/XboxReplay/xboxlive-auth/issues'
}
};

@@ -0,16 +1,17 @@

export declare const defaultClientId = "000000004C12AE6F";
export declare const defaultScope = "service::user.auth.xboxlive.com::MBI_SSL";
export declare const defaultRedirectUri = "https://login.live.com/oauth20_desktop.srf";
export declare const defaultResponseType = "token";
declare const _default: {
uris: {
urls: {
authorize: string;
token: string;
};
queries: {
authorize: {
client_id: string;
redirect_uri: string;
scope: string;
display: string;
response_type: string;
locale: string;
};
client: {
id: string;
redirectUri: string;
scope: string;
responseType: string;
};
};
export default _default;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const CLIENT_IDS = {
MY_XBOX_LIVE: '0000000048093EE3',
XBOX_APP: '000000004C12AE6F'
};
exports.defaultResponseType = exports.defaultRedirectUri = exports.defaultScope = exports.defaultClientId = void 0;
exports.defaultClientId = '000000004C12AE6F';
exports.defaultScope = 'service::user.auth.xboxlive.com::MBI_SSL';
exports.defaultRedirectUri = 'https://login.live.com/oauth20_desktop.srf';
exports.defaultResponseType = 'token';
exports.default = {
uris: {
authorize: 'https://login.live.com/oauth20_authorize.srf'
urls: {
authorize: 'https://login.live.com/oauth20_authorize.srf',
token: 'https://login.live.com/oauth20_token.srf'
},
queries: {
authorize: {
client_id: CLIENT_IDS.XBOX_APP,
redirect_uri: 'https://login.live.com/oauth20_desktop.srf',
scope: 'service::user.auth.xboxlive.com::MBI_SSL',
display: 'touch',
response_type: 'token',
locale: 'en'
}
client: {
id: exports.defaultClientId,
redirectUri: exports.defaultRedirectUri,
scope: exports.defaultScope,
responseType: exports.defaultResponseType
}
};

@@ -1,3 +0,5 @@

import { PreAuthResponse, Credentials, LogUserResponse } from '../..';
export declare const preAuth: () => Promise<PreAuthResponse>;
export declare const logUser: (preAuthResponse: PreAuthResponse, credentials: Credentials) => Promise<LogUserResponse>;
import { LiveAuthResponse, LiveCredentials, LivePreAuthResponse } from '../..';
export declare const getAuthorizeUrl: (clientId?: string, scope?: string, responseType?: 'token' | 'code', redirectUri?: string) => string;
export declare const refreshAccessToken: (refreshToken: string, clientId?: string, scope?: string, clientSecret?: string | undefined) => Promise<LiveAuthResponse>;
export declare const preAuth: () => Promise<LivePreAuthResponse>;
export declare const authenticate: (credentials: LiveCredentials) => Promise<LiveAuthResponse>;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -6,84 +34,121 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
const errors_1 = __importDefault(require("@xboxreplay/errors"));
exports.authenticate = exports.preAuth = exports.refreshAccessToken = exports.getAuthorizeUrl = void 0;
const axios_1 = __importDefault(require("axios"));
const config_1 = __importDefault(require("./config"));
const config_2 = __importDefault(require("../../config"));
const querystring_1 = require("querystring");
const _getMatchForIndex = (entry, regex, index = 0) => {
const utils_1 = require("../../utils");
const XRError_1 = __importDefault(require("../../classes/XRError"));
const config_1 = __importDefault(require("../../config"));
const config_2 = __importStar(require("./config"));
const getMatchForIndex = (entry, regex, index = 0) => {
const match = entry.match(regex);
return (match === null || match === void 0 ? void 0 : match[index]) || void 0;
};
const _requiresIdentityConfirmation = (body) => {
const m1 = _getMatchForIndex(body, /id=\"fmHF\" action=\"(.*?)\"/, 1);
const m2 = _getMatchForIndex(m1 || '', /identity\/confirm/, 0);
return m2 !== null;
};
exports.preAuth = () => axios_1.default
.get(`${config_1.default.uris.authorize}?${querystring_1.stringify(Object.assign({}, config_1.default.queries.authorize))}`, { headers: config_2.default.request.baseHeaders })
.then(response => {
if (response.status !== 200) {
throw errors_1.default.internal('Pre-authentication failed.');
const getAuthorizeUrl = (clientId = config_2.defaultClientId, scope = config_2.defaultScope, responseType = config_2.defaultResponseType, redirectUri = config_2.defaultRedirectUri) => `${config_2.default.urls.authorize}?${querystring_1.stringify({
client_id: clientId,
redirectUri: redirectUri,
response_type: responseType,
scope: scope
})}`;
exports.getAuthorizeUrl = getAuthorizeUrl;
const refreshAccessToken = (refreshToken, clientId = config_2.defaultClientId, scope = config_2.defaultScope, clientSecret = void 0) => __awaiter(void 0, void 0, void 0, function* () {
const payload = {
client_id: clientId,
scope: scope || config_2.defaultScope,
grant_type: 'refresh_token',
refresh_token: refreshToken
};
if (clientSecret !== void 0) {
payload.client_secret = clientSecret;
}
const body = (response.data || '');
const cookie = (response.headers['set-cookie'] || [])
.map((c) => c.split(';')[0])
.join('; ');
const matches = {
PPFT: _getMatchForIndex(body, /sFTTag:'.*value=\"(.*)\"\/>'/, 1),
urlPost: _getMatchForIndex(body, /urlPost:'(.+?(?=\'))/, 1)
};
if (matches.PPFT === void 0)
throw errors_1.default.internal(`Could not match "PPFT" parameter, please fill an issue on ${config_2.default.gitHubLinks.createIssue}`);
else if (matches.urlPost === void 0)
throw errors_1.default.internal(`Could not match "urlPost" parameter, please fill an issue on ${config_2.default.gitHubLinks.createIssue}`);
return {
cookie,
matches: {
PPFT: matches.PPFT,
urlPost: matches.urlPost
const response = yield axios_1.default({
url: config_2.default.urls.token,
method: 'POST',
headers: utils_1.getBaseHeaders({
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
}),
data: querystring_1.stringify(payload)
})
.then(res => res.data)
.catch((err) => {
var _a;
throw new XRError_1.default(err.message, {
statusCode: (_a = err.response) === null || _a === void 0 ? void 0 : _a.status
});
});
return response;
});
exports.refreshAccessToken = refreshAccessToken;
const preAuth = () => __awaiter(void 0, void 0, void 0, function* () {
const response = yield axios_1.default({
url: exports.getAuthorizeUrl(),
method: 'GET',
headers: utils_1.getBaseHeaders()
})
.then(res => {
const body = (res.data || '');
const cookie = (res.headers['set-cookie'] || [])
.map((c) => c.split(';')[0])
.join('; ');
const matches = {
PPFT: getMatchForIndex(body, /sFTTag:'.*value=\"(.*)\"\/>'/, 1),
urlPost: getMatchForIndex(body, /urlPost:'(.+?(?=\'))/, 1)
};
if (matches.PPFT !== void 0 && matches.urlPost !== void 0) {
return {
cookie,
matches: matches
};
}
};
})
.catch(err => {
if (!!err.__XboxReplay__)
throw err;
else
throw errors_1.default.internal(err.message);
throw XRError_1.default.internal(`Could not match required "preAuth" parameters, please fill an issue on ${config_1.default.github.createIssue}`);
})
.catch(err => {
if (err.__XboxReplay__ === true)
throw err;
throw XRError_1.default.internal(err.message);
});
return response;
});
exports.logUser = (preAuthResponse, credentials) => axios_1.default
.post(preAuthResponse.matches.urlPost, querystring_1.stringify({
login: credentials.email,
loginfmt: credentials.email,
passwd: credentials.password,
PPFT: preAuthResponse.matches.PPFT
}), {
maxRedirects: 1,
headers: Object.assign(Object.assign({}, config_2.default.request.baseHeaders), { 'Content-Type': 'application/x-www-form-urlencoded', Cookie: preAuthResponse.cookie })
})
.then(response => {
var _a;
if (response.status !== 200) {
throw errors_1.default.internal(`Authentication failed.`);
}
const body = (response.data || '');
const { responseUrl = '' } = ((_a = response.request) === null || _a === void 0 ? void 0 : _a.res) || {};
const hash = responseUrl.split('#')[1];
if (responseUrl === preAuthResponse.matches.urlPost) {
throw errors_1.default.unauthorized('Invalid credentials.');
}
if (hash === void 0) {
const errorMessage = _requiresIdentityConfirmation(body) === true
? `Activity confirmation required, please refer to ${config_2.default.gitHubLinks.unauthorizedActivityError}`
: `Invalid credentials or 2FA enabled, please refer to ${config_2.default.gitHubLinks.twoFactorAuthenticationError}`;
throw errors_1.default.unauthorized(errorMessage);
}
const parseHash = querystring_1.parse(hash);
parseHash.expires_in = Number(parseHash.expires_in);
return parseHash;
})
.catch(err => {
if (!!err.__XboxReplay__)
throw err;
else
throw errors_1.default.internal(err.message);
exports.preAuth = preAuth;
const authenticate = (credentials) => __awaiter(void 0, void 0, void 0, function* () {
const preAuthResponse = yield exports.preAuth();
const response = yield axios_1.default({
url: preAuthResponse.matches.urlPost,
method: 'POST',
headers: utils_1.getBaseHeaders({
'Content-Type': 'application/x-www-form-urlencoded',
Cookie: preAuthResponse.cookie
}),
data: querystring_1.stringify({
login: credentials.email,
loginfmt: credentials.email,
passwd: credentials.password,
PPFT: preAuthResponse.matches.PPFT
}),
maxRedirects: 0,
validateStatus: status => status === 302 || status === 200
})
.then(res => {
if (res.status === 200) {
throw XRError_1.default.unauthorized(`Invalid credentials or 2FA enabled`);
}
const { location = '' } = res.headers || {};
const hash = location.split('#')[1];
const output = {};
for (const part of new URLSearchParams(hash)) {
if (part[0] === 'expires_in') {
output[part[0]] = Number(part[1]);
}
else
output[part[0]] = part[1];
}
return output;
})
.catch(err => {
if (err.__XboxReplay__ === true)
throw err;
throw XRError_1.default.internal(err.message);
});
return response;
});
exports.authenticate = authenticate;

@@ -0,8 +1,9 @@

export declare const defaultXSTSRelyingParty = "http://xboxlive.com";
declare const _default: {
uris: {
urls: {
userAuthenticate: string;
deviceAuthenticate: string;
XSTSAuthorize: string;
};
defaultRelyingParty: string;
};
export default _default;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultXSTSRelyingParty = void 0;
exports.defaultXSTSRelyingParty = 'http://xboxlive.com';
exports.default = {
uris: {
urls: {
userAuthenticate: 'https://user.auth.xboxlive.com/user/authenticate',
deviceAuthenticate: 'https://device.auth.xboxlive.com/device/authenticate',
XSTSAuthorize: 'https://xsts.auth.xboxlive.com/xsts/authorize'
},
defaultRelyingParty: 'http://xboxlive.com'
}
};

@@ -1,4 +0,5 @@

import { ExchangeRpsTicketResponse, AuthenticateResponse, ExchangeResponse, TokensExchangeProperties, TokensExchangeOptions } from '../..';
export declare const exchangeRpsTicketForUserToken: (RpsTicket: string) => Promise<ExchangeRpsTicketResponse>;
export declare const exchangeTokensForXSTSIdentity: <T extends ExchangeResponse>({ userToken, deviceToken, titleToken }: TokensExchangeProperties, { XSTSRelyingParty, optionalDisplayClaims, raw }?: TokensExchangeOptions) => Promise<T | AuthenticateResponse>;
export declare const exchangeUserTokenForXSTSIdentity: <T extends ExchangeResponse>(userToken: string, options: TokensExchangeOptions) => Promise<AuthenticateResponse | T>;
import { XBLDummyDeviceTokenResponse, XBLExchangeRpsTicketResponse, XBLExchangeTokensOptions, XBLExchangeTokensResponse, XBLTokens } from '../..';
export declare const exchangeRpsTicketForUserToken: (rpsTicket: string, preamble?: 'd' | 't', additionalHeaders?: Record<string, string>) => Promise<XBLExchangeRpsTicketResponse>;
export declare const exchangeTokensForXSTSToken: (tokens: XBLTokens, options?: XBLExchangeTokensOptions, additionalHeaders?: Record<string, string>) => Promise<XBLExchangeTokensResponse>;
export declare const exchangeTokenForXSTSToken: (userToken: string, options?: XBLExchangeTokensOptions, additionalHeaders?: Record<string, string>) => Promise<XBLExchangeTokensResponse>;
export declare const EXPERIMENTAL_createDummyWin32DeviceToken: () => Promise<XBLDummyDeviceTokenResponse>;
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -6,77 +34,101 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

Object.defineProperty(exports, "__esModule", { value: true });
const errors_1 = __importDefault(require("@xboxreplay/errors"));
exports.EXPERIMENTAL_createDummyWin32DeviceToken = exports.exchangeTokenForXSTSToken = exports.exchangeTokensForXSTSToken = exports.exchangeRpsTicketForUserToken = void 0;
const axios_1 = __importDefault(require("axios"));
const config_1 = __importDefault(require("./config"));
const config_1 = __importStar(require("./config"));
const utils_1 = require("../../utils");
const XRError_1 = __importDefault(require("../../classes/XRError"));
const config_2 = __importDefault(require("../../config"));
exports.exchangeRpsTicketForUserToken = (RpsTicket) => axios_1.default
.post(config_1.default.uris.userAuthenticate, {
RelyingParty: 'http://auth.xboxlive.com',
TokenType: 'JWT',
Properties: {
AuthMethod: 'RPS',
SiteName: 'user.auth.xboxlive.com',
RpsTicket
const XBLContractVersion = 0;
const XBLAdditionalHeaders = {
Accept: 'application/json',
'X-Xbl-Contract-Version': String(XBLContractVersion)
};
const exchangeRpsTicketForUserToken = (rpsTicket, preamble = 't', additionalHeaders = {}) => __awaiter(void 0, void 0, void 0, function* () {
const match = rpsTicket.match(/^([t|d]=)/g);
if (match === null) {
rpsTicket = `${preamble}=${rpsTicket}`;
}
}, {
headers: Object.assign(Object.assign({}, config_2.default.request.baseHeaders), { Accept: 'application/json', 'x-xbl-contract-version': 0 })
})
.then(response => {
if (response.status !== 200)
throw errors_1.default.internal('Could not exchange specified "RpsTicket"');
else
return response.data;
})
.catch(err => {
if (!!err.__XboxReplay__)
throw err;
else
throw errors_1.default.internal(err.message);
const response = yield axios_1.default({
url: config_1.default.urls.userAuthenticate,
method: 'POST',
headers: utils_1.getBaseHeaders(Object.assign(Object.assign({}, XBLAdditionalHeaders), additionalHeaders)),
data: {
RelyingParty: 'http://auth.xboxlive.com',
TokenType: 'JWT',
Properties: {
AuthMethod: 'RPS',
SiteName: 'user.auth.xboxlive.com',
RpsTicket: rpsTicket
}
}
})
.then(res => res.data)
.catch(_ => {
throw XRError_1.default.badRequest('Could not exchange specified "RpsTicket"');
});
return response;
});
exports.exchangeTokensForXSTSIdentity = ({ userToken, deviceToken, titleToken }, { XSTSRelyingParty, optionalDisplayClaims, raw } = {}) => axios_1.default
.post(config_1.default.uris.XSTSAuthorize, {
RelyingParty: XSTSRelyingParty || config_1.default.defaultRelyingParty,
TokenType: 'JWT',
Properties: {
UserTokens: [userToken],
DeviceToken: deviceToken,
TitleToken: titleToken,
OptionalDisplayClaims: optionalDisplayClaims,
SandboxId: 'RETAIL'
}
}, {
headers: Object.assign(Object.assign({}, config_2.default.request.baseHeaders), { Accept: 'application/json', 'x-xbl-contract-version': 1 })
})
.then(response => {
if (response.status !== 200) {
throw errors_1.default.internal('Could not exchange specified "userToken"');
}
if (raw !== true) {
const body = response.data;
return {
userXUID: body.DisplayClaims.xui[0].xid || null,
userHash: body.DisplayClaims.xui[0].uhs,
XSTSToken: body.Token,
expiresOn: body.NotAfter
};
}
else
return response.data;
})
.catch(err => {
var _a;
if (!!err.__XboxReplay__)
throw err;
else if (((_a = err.response) === null || _a === void 0 ? void 0 : _a.status) === 400) {
const isDefaultRelyingParty = XSTSRelyingParty === config_1.default.defaultRelyingParty;
const computedErrorMessage = [
'Could not exchange "userToken", please',
`refer to ${config_2.default.gitHubLinks.seeUserTokenIssue}`
];
if (isDefaultRelyingParty === false)
computedErrorMessage.splice(1, 0, 'double check the specified "XSTSRelyingParty" or');
throw errors_1.default.internal(computedErrorMessage.join(' '));
}
else
throw errors_1.default.internal(err.message);
exports.exchangeRpsTicketForUserToken = exchangeRpsTicketForUserToken;
const exchangeTokensForXSTSToken = (tokens, options = {}, additionalHeaders = {}) => __awaiter(void 0, void 0, void 0, function* () {
const response = yield axios_1.default({
url: config_1.default.urls.XSTSAuthorize,
method: 'POST',
headers: utils_1.getBaseHeaders(Object.assign(Object.assign({}, XBLAdditionalHeaders), additionalHeaders)),
data: {
RelyingParty: options.XSTSRelyingParty || config_1.defaultXSTSRelyingParty,
TokenType: 'JWT',
Properties: {
UserTokens: tokens.userTokens,
DeviceToken: tokens.deviceToken,
TitleToken: tokens.titleToken,
OptionalDisplayClaims: options.optionalDisplayClaims,
SandboxId: options.sandboxId || 'RETAIL'
}
}
})
.then(res => res.data)
.catch((err) => {
var _a;
throw new XRError_1.default('Could not exchange specified tokens, please double check used parameters or make sure to use the "EXPERIMENTAL_createDummyWin32DeviceToken" method to handle "Child" and "Teen" accounts', { statusCode: (_a = err.response) === null || _a === void 0 ? void 0 : _a.status });
});
return response;
});
exports.exchangeUserTokenForXSTSIdentity = (userToken, options) => exports.exchangeTokensForXSTSIdentity({ userToken }, options);
exports.exchangeTokensForXSTSToken = exchangeTokensForXSTSToken;
const exchangeTokenForXSTSToken = (userToken, options = {}, additionalHeaders = {}) => exports.exchangeTokensForXSTSToken({ userTokens: [userToken] }, options, additionalHeaders);
exports.exchangeTokenForXSTSToken = exchangeTokenForXSTSToken;
const EXPERIMENTAL_createDummyWin32DeviceToken = () => __awaiter(void 0, void 0, void 0, function* () {
const trustedParty = 'https://xboxreplay.net/';
const serviceDeviceId = '21354D2F-352F-472F-5842-5265706C6179';
const serviceSignature = 'AAAAAQHW6oD31MwA6MAjn67vdCppWCbrMovubA85xejO06rtOAEdZ0tMTZFnu7xbI6lZDNvIWfuMaIPJSUcpvxjKqSFJl1oaWzQGBw==';
const serviceProofKey = {
crv: 'P-256',
alg: 'ES256',
use: 'sig',
kty: 'EC',
x: 'b8Zc6GPFeu41DqiWPJxRa_jqUTSiMA537emKVHt8UO8',
y: 'CXAuTEHet72GjgSDfDg6psBrwE1waxBsNEIGrRZV_90'
};
const response = yield axios_1.default({
url: config_1.default.urls.deviceAuthenticate,
method: 'POST',
headers: utils_1.getBaseHeaders(Object.assign(Object.assign({}, XBLAdditionalHeaders), { Signature: serviceSignature })),
data: {
RelyingParty: 'http://auth.xboxlive.com',
TokenType: 'JWT',
Properties: {
AuthMethod: 'ProofOfPossession',
TrustedParty: trustedParty,
Id: `{${serviceDeviceId}}`,
DeviceType: 'Win32',
Version: '10.0.18363',
ProofKey: serviceProofKey
}
}
})
.then(res => res.data)
.catch(_ => {
throw XRError_1.default.badRequest(`Could not create a valid device token, please fill an issue on ${config_2.default.github.createIssue}`);
});
return response;
});
exports.EXPERIMENTAL_createDummyWin32DeviceToken = EXPERIMENTAL_createDummyWin32DeviceToken;

@@ -1,55 +0,136 @@

import { preAuth, logUser } from './core/live';
import { exchangeRpsTicketForUserToken, exchangeUserTokenForXSTSIdentity, exchangeTokensForXSTSIdentity } from './core/xboxlive';
export declare type Credentials = {
export declare type LiveCredentials = {
email: string;
password: string;
};
export declare type TokensExchangeProperties = {
userToken: string;
deviceToken?: string;
titleToken?: string;
export declare type LiveAuthResponse = {
token_type: 'bearer';
expires_in: number;
access_token: string;
refresh_token?: string;
scope: string;
user_id: string;
};
export declare type TokensExchangeOptions = {
XSTSRelyingParty?: string;
optionalDisplayClaims?: string[];
raw?: boolean;
export declare type LivePreAuthMatchedParameters = {
PPFT: string;
urlPost: string;
};
export declare type AuthenticateOptions = {
XSTSRelyingParty?: string;
export declare type LivePreAuthResponse = {
cookie: string;
matches: LivePreAuthMatchedParameters;
};
export declare type PreAuthResponse = {
cookie: string;
matches: {
PPFT: string;
urlPost: string;
export declare type XBLExchangeRpsTicketResponse = {
IssueInstant: string;
NotAfter: string;
Token: string;
DisplayClaims: {
xui: Array<{
uhs: string;
}>;
};
};
export declare type LogUserResponse = {
access_token: string;
token_type: string;
expires_in: number;
scope: string;
refresh_token: string;
user_id: string;
export declare type XBLExchangeTokensOptions = {
XSTSRelyingParty?: string;
optionalDisplayClaims?: string[];
sandboxId?: string;
};
export declare type ExchangeResponse = {
export declare type XBLExchangeTokensResponse = {
IssueInstant: string;
NotAfter: string;
Token: string;
DisplayClaims: object;
};
export declare type ExchangeRpsTicketResponse = ExchangeResponse & {
DisplayClaims: {
xui: [{
xui: Array<Record<string, string> & {
xid?: string;
uhs: string;
}];
}>;
};
};
export declare type AuthenticateResponse = {
userXUID: string | null;
userHash: string;
XSTSToken: string;
expiresOn: string;
export declare type XBLDummyDeviceTokenResponse = {
IssueInstant: string;
NotAfter: string;
Token: string;
DisplayClaims: {
xdi: {
did: 'F50CDD8781FF4476';
dcs: string;
};
};
};
export declare const authenticate: (email: string, password: string, options?: AuthenticateOptions) => Promise<AuthenticateResponse>;
export { preAuth, logUser, exchangeRpsTicketForUserToken, exchangeUserTokenForXSTSIdentity, exchangeTokensForXSTSIdentity };
export declare type XBLTokens = {
userTokens: string[];
deviceToken?: string;
titleToken?: string;
};
export declare type AuthenticateOptions = XBLExchangeTokensOptions & {
deviceToken?: string;
titleToken?: string;
raw?: boolean;
};
export declare const authenticate: (email: string, password: string, options?: AuthenticateOptions) => Promise<{
xuid: string | null;
user_hash: string;
xsts_token: string;
display_claims: Record<string, string> & {
xid?: string | undefined;
uhs: string;
};
expires_on: string;
'login.live.com'?: undefined;
'user.auth.xboxlive.com'?: undefined;
'xsts.auth.xboxlive.com'?: undefined;
} | {
'login.live.com': LiveAuthResponse;
'user.auth.xboxlive.com': XBLExchangeRpsTicketResponse;
'xsts.auth.xboxlive.com': XBLExchangeTokensResponse;
xuid?: undefined;
user_hash?: undefined;
xsts_token?: undefined;
display_claims?: undefined;
expires_on?: undefined;
}>;
export declare const live: {
getAuthorizeUrl: (clientId?: string, scope?: string, responseType?: "code" | "token", redirectUri?: string) => string;
authenticate: (credentials: LiveCredentials) => Promise<LiveAuthResponse>;
refreshAccessToken: (refreshToken: string, clientId?: string, scope?: string, clientSecret?: string | undefined) => Promise<LiveAuthResponse>;
};
export declare const xbl: {
EXPERIMENTAL_createDummyWin32DeviceToken: () => Promise<XBLDummyDeviceTokenResponse>;
exchangeRpsTicketForUserToken: (rpsTicket: string, preamble?: "d" | "t", additionalHeaders?: Record<string, string>) => Promise<XBLExchangeRpsTicketResponse>;
exchangeTokensForXSTSToken: (tokens: XBLTokens, options?: XBLExchangeTokensOptions, additionalHeaders?: Record<string, string>) => Promise<XBLExchangeTokensResponse>;
exchangeTokenForXSTSToken: (userToken: string, options?: XBLExchangeTokensOptions, additionalHeaders?: Record<string, string>) => Promise<XBLExchangeTokensResponse>;
};
declare const _default: {
xbl: {
EXPERIMENTAL_createDummyWin32DeviceToken: () => Promise<XBLDummyDeviceTokenResponse>;
exchangeRpsTicketForUserToken: (rpsTicket: string, preamble?: "d" | "t", additionalHeaders?: Record<string, string>) => Promise<XBLExchangeRpsTicketResponse>;
exchangeTokensForXSTSToken: (tokens: XBLTokens, options?: XBLExchangeTokensOptions, additionalHeaders?: Record<string, string>) => Promise<XBLExchangeTokensResponse>;
exchangeTokenForXSTSToken: (userToken: string, options?: XBLExchangeTokensOptions, additionalHeaders?: Record<string, string>) => Promise<XBLExchangeTokensResponse>;
};
live: {
getAuthorizeUrl: (clientId?: string, scope?: string, responseType?: "code" | "token", redirectUri?: string) => string;
authenticate: (credentials: LiveCredentials) => Promise<LiveAuthResponse>;
refreshAccessToken: (refreshToken: string, clientId?: string, scope?: string, clientSecret?: string | undefined) => Promise<LiveAuthResponse>;
};
authenticate: (email: string, password: string, options?: AuthenticateOptions) => Promise<{
xuid: string | null;
user_hash: string;
xsts_token: string;
display_claims: Record<string, string> & {
xid?: string | undefined;
uhs: string;
};
expires_on: string;
'login.live.com'?: undefined;
'user.auth.xboxlive.com'?: undefined;
'xsts.auth.xboxlive.com'?: undefined;
} | {
'login.live.com': LiveAuthResponse;
'user.auth.xboxlive.com': XBLExchangeRpsTicketResponse;
'xsts.auth.xboxlive.com': XBLExchangeTokensResponse;
xuid?: undefined;
user_hash?: undefined;
xsts_token?: undefined;
display_claims?: undefined;
expires_on?: undefined;
}>;
};
export default _default;

@@ -12,14 +12,46 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.xbl = exports.live = exports.authenticate = void 0;
const live_1 = require("./core/live");
exports.preAuth = live_1.preAuth;
exports.logUser = live_1.logUser;
const xboxlive_1 = require("./core/xboxlive");
exports.exchangeRpsTicketForUserToken = xboxlive_1.exchangeRpsTicketForUserToken;
exports.exchangeUserTokenForXSTSIdentity = xboxlive_1.exchangeUserTokenForXSTSIdentity;
exports.exchangeTokensForXSTSIdentity = xboxlive_1.exchangeTokensForXSTSIdentity;
exports.authenticate = (email, password, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
const preAuthResponse = yield live_1.preAuth();
const logUserResponse = yield live_1.logUser(preAuthResponse, { email, password });
const exchangeRpsTicketForUserTokenResponse = yield xboxlive_1.exchangeRpsTicketForUserToken(logUserResponse.access_token);
return xboxlive_1.exchangeUserTokenForXSTSIdentity(exchangeRpsTicketForUserTokenResponse.Token, { XSTSRelyingParty: options.XSTSRelyingParty, raw: false });
const authenticate = (email, password, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
const credentials = { email, password };
const liveAuthResponse = yield live_1.authenticate(credentials);
const { access_token: RpsTicket } = liveAuthResponse;
const userTokenResponse = yield xboxlive_1.exchangeRpsTicketForUserToken(RpsTicket);
const XSTSResponse = yield xboxlive_1.exchangeTokensForXSTSToken({
userTokens: [userTokenResponse.Token],
deviceToken: options.deviceToken,
titleToken: options.titleToken
}, {
XSTSRelyingParty: options.XSTSRelyingParty,
optionalDisplayClaims: options.optionalDisplayClaims,
sandboxId: options.sandboxId
});
if (options.raw !== true) {
return {
xuid: XSTSResponse.DisplayClaims.xui[0].xid || null,
user_hash: XSTSResponse.DisplayClaims.xui[0].uhs,
xsts_token: XSTSResponse.Token,
display_claims: XSTSResponse.DisplayClaims.xui[0],
expires_on: XSTSResponse.NotAfter
};
}
return {
'login.live.com': liveAuthResponse,
'user.auth.xboxlive.com': userTokenResponse,
'xsts.auth.xboxlive.com': XSTSResponse
};
});
exports.authenticate = authenticate;
exports.live = {
getAuthorizeUrl: live_1.getAuthorizeUrl,
authenticate: live_1.authenticate,
refreshAccessToken: live_1.refreshAccessToken
};
exports.xbl = {
EXPERIMENTAL_createDummyWin32DeviceToken: xboxlive_1.EXPERIMENTAL_createDummyWin32DeviceToken,
exchangeRpsTicketForUserToken: xboxlive_1.exchangeRpsTicketForUserToken,
exchangeTokensForXSTSToken: xboxlive_1.exchangeTokensForXSTSToken,
exchangeTokenForXSTSToken: xboxlive_1.exchangeTokenForXSTSToken
};
exports.default = { xbl: exports.xbl, live: exports.live, authenticate: exports.authenticate };
{
"name": "@xboxreplay/xboxlive-auth",
"description": "Simple Xbox Live authentication module.",
"version": "3.3.3",
"description": "A light Xbox Live authentication module",
"version": "4.0.0-beta.0",
"keywords": [
"xboxreplay",
"xboxlive",
"xbox",
"live",
"auth"

@@ -22,16 +24,17 @@ ],

"scripts": {
"build": "npm run clean && ./node_modules/.bin/tsc && rm -rf ./dist/__tests__",
"build": "npm run clean && ./node_modules/.bin/tsc",
"clean": "rm -rf ./dist",
"prepublishOnly": "npm run test && npm run build",
"test": "ts-node ./__tests__/e2e.test.js"
"touch-test-env": "touch .env.test",
"test": "npm run touch-test-env && ts-node ./__tests__/e2e.test.js"
},
"dependencies": {
"@xboxreplay/errors": "^0.1.0",
"axios": "^0.21.1"
},
"devDependencies": {
"@types/node": "^13.11.1",
"ts-node": "^8.8.2",
"typescript": "^3.8.3"
"@types/node": "^14.14.20",
"dotenv": "^8.2.0",
"ts-node": "^9.1.1",
"typescript": "^4.1.3"
}
}

@@ -1,44 +0,62 @@

# Xbox Live - Auth
# @xboxreplay/xboxlive-auth
Simple Xbox Live authentication module.
A light but advanced Xbox Live authentication module with [OAuth2.0](docs/02-Custom_Azure_Application.md) and [Electron](examples/electron-app) support.
### Warning
This module **MUST** be used server side only to prevent [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) issues and credentials leak (See issue: https://github.com/XboxReplay/xboxlive-auth/issues/8).
## Installation
### Installation
```shell
$ npm install @xboxreplay/xboxlive-auth
$ npm install @xboxreplay/xboxlive-auth@4.0.0-beta.0
```
### Usage example
## Usage Example
```javascript
import XboxLiveAuth from '@xboxreplay/xboxlive-auth';
import xboxliveAuth from '@xboxreplay/xboxlive-auth';
XboxLiveAuth.authenticate('xbl-account@your-domain.com', '*********')
.then(console.info)
.catch(console.error);
xboxliveAuth
.authenticate('name@domain.com', '*********')
.then(console.info)
.catch(console.error);
```
**Sample response:**
```
##### Sample Response
```javascript
{
"userXUID": "2584878536129841", // May be null
"userHash": "3218841136841218711",
"XSTSToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiWGJveFJlcGxheS5uZXQifQ.c2UraxPmZ4STYozrjFEW8SBqU0WjnIV0h-jjnfsKtrA",
"expiresOn": "2020-04-13T05:43:32.6275675Z"
"xuid": "2584878536129841", // May be null based on the specified "RelyingParty"
"user_hash": "3218841136841218711",
"xsts_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"display_claims": {
"gtg": "Zeny IC",
"xid": "2584878536129841",
"uhs": "3218841136841218711"
"agg": "Adult",
"usr" "234",
"utr": "190",
"prv": "185 186 187 188 191 192 ..."
},
"expires_on": "2021-04-13T05:43:32.6275675Z"
}
```
### Parameters
## Documentation
- email {string}
- password {string}
- options {Object?}
- XSTSRelyingParty {string?} - Default: http://xboxlive.com
- [Basic authentication](docs/01-Authenticate.md)
- [Use a custom Azure Application (OAuth2.0)](docs/02-Custom_Azure_Application.md)
- [Experimental methods, such as "deviceToken" generation](docs/03-Experimental.md)
- [What's a RelyingParty and how to use it](docs/04-RelyingParty.md)
- [Available methods in this library](docs/05-Methods.md)
- [Known issues and possible workarounds](docs/06-Known_Issues.md)
- [How to deal with unauthorized "AgeGroup" authentication](docs/07-Detect_Unauthorized_AgeGroup.md)
### How to interact with the Xbox Live API?
## Available Examples
The best way to interact with the API is to use our [XboxLive-API](https://github.com/XboxReplay/xboxlive-api) module. That said, a cURL example is available below.
- [Electron App](examples/electron-app)
**Sample call:**
## How to interact with the Xbox Live API?
The best way to interact with the API is to use our [@xboxreplay/xboxlive-auth](https://github.com/XboxReplay/xboxlive-api) module. That said, a cURL example is available below.
##### Example
```shell

@@ -50,32 +68,12 @@ $ curl 'https://profile.xboxlive.com/users/gt(Major%20Nelson)/profile/settings?settings=Gamerscore' \

**Sample response:**
## What about 2FA (Two-factor authentication)?
```javascript
{
"profileUsers": [
{
"id": "2584878536129841",
"hostId": "2584878536129841",
"settings": [
{
"id": "Gamerscore",
"value": "911540"
}
],
"isSponsoredUser": false
}
]
}
```
2FA is not supported by this module which may cause authentication issues. Please disable it for the used account or create a dummy one with Xbox LIVE capabalities. Of course, a Gold account is not required. Please note that Electron applications are not impacted by this issue.
### What's a "XSTSRelyingParty"?
## Known Issues
The "XSTSRelyingParty" is a domain configured by Microsoft and / or its partners to create a XSTS token which is intended to be used for a targeted service. For instance, if you use `http://beam.pro/` you will be able to interact with the private **Mixer.com** API. A partial list can be found here: https://title.mgt.xboxlive.com/titles/default/endpoints?type=1.
Please refer to the [dedicated documention](docs/06-Known_Issues.md).
### What about 2FA (Two-factor authentication)?
## Licence
2FA is not supported by this module which may cause authentication issues. Please disable it for the used account or create a dummy one with Xbox LIVE capabalities. Of course, a Gold account is not required.
### I'm unable to connect even with valid credentials and no 2FA
Take a look at https://account.live.com/activity or try to sign in to https://account.xbox.com/Profile from your browser. Recent activities (from unknown location, as a production server) may be blocked.
MIT
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc