From 56c6361a813df2264019b777b88623e66803697b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 19 Aug 2024 11:58:24 +0100 Subject: [PATCH 01/12] Add PlayFab and Minecraft Services managers --- examples/services/deviceCode.js | 18 +++++ src/MicrosoftAuthFlow.js | 34 ++++++++- src/TokenManagers/MinecraftServicesManager.js | 60 ++++++++++++++++ src/TokenManagers/PlayfabTokenManager.js | 71 +++++++++++++++++++ src/common/Constants.js | 5 +- 5 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 examples/services/deviceCode.js create mode 100644 src/TokenManagers/MinecraftServicesManager.js create mode 100644 src/TokenManagers/PlayfabTokenManager.js diff --git a/examples/services/deviceCode.js b/examples/services/deviceCode.js new file mode 100644 index 0000000..c37f868 --- /dev/null +++ b/examples/services/deviceCode.js @@ -0,0 +1,18 @@ +const { Authflow, Titles } = require('prismarine-auth') + +const [, , username, cacheDir] = process.argv + +if (!username) { + console.log('Usage: node deviceCode.js [cacheDirectory]') + process.exit(1) +} + +async function doAuth () { + const flow = new Authflow(username, cacheDir, { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) + + const response = await flow.getMinecraftServicesToken() + + console.log(response) +} + +module.exports = doAuth() diff --git a/src/MicrosoftAuthFlow.js b/src/MicrosoftAuthFlow.js index 234b27b..9c78aa2 100644 --- a/src/MicrosoftAuthFlow.js +++ b/src/MicrosoftAuthFlow.js @@ -3,6 +3,7 @@ const path = require('path') const crypto = require('crypto') const debug = require('debug')('prismarine-auth') +const Titles = require('./common/Titles') const { createHash } = require('./common/Util') const { Endpoints, msalConfig } = require('./common/Constants') const FileCache = require('./common/cache/FileCache') @@ -12,7 +13,8 @@ const JavaTokenManager = require('./TokenManagers/MinecraftJavaTokenManager') const XboxTokenManager = require('./TokenManagers/XboxTokenManager') const MsaTokenManager = require('./TokenManagers/MsaTokenManager') const BedrockTokenManager = require('./TokenManagers/MinecraftBedrockTokenManager') -const Titles = require('./common/Titles') +const PlayfabTokenManager = require('./TokenManagers/PlayfabTokenManager') +const MinecraftServicesTokenManager = require('./TokenManagers/MinecraftServicesManager') async function retry (methodFn, beforeRetry, times) { while (times--) { @@ -87,6 +89,8 @@ class MicrosoftAuthFlow { this.xbl = new XboxTokenManager(keyPair, cache({ cacheName: 'xbl', username })) this.mba = new BedrockTokenManager(cache({ cacheName: 'bed', username })) this.mca = new JavaTokenManager(cache({ cacheName: 'mca', username })) + this.mcs = new MinecraftServicesTokenManager(cache({ cacheName: 'mcs', username })) + this.pfb = new PlayfabTokenManager(cache({ cacheName: 'pfb', username })) } async getMsaToken () { @@ -113,6 +117,34 @@ class MicrosoftAuthFlow { } } + async getPlayfabLogin() { + const cache = this.pfb.getCachedAccessToken() + + if (cache.valid) { + return cache.data + } + + const xsts = await this.getXboxToken(Endpoints.PlayfabRelyingParty) + + const playfab = await this.pfb.getAccessToken(xsts) + + return playfab + } + + async getMinecraftServicesToken () { + const cache = await this.mcs.getCachedAccessToken() + + if (cache.valid) { + return cache.data + } + + const playfab = await this.getPlayfabLogin() + + const mcs = await this.mcs.getAccessToken(playfab.SessionTicket) + + return mcs + } + async getXboxToken (relyingParty = this.options.relyingParty || Endpoints.XboxRelyingParty, forceRefresh = false) { const options = { ...this.options, relyingParty } diff --git a/src/TokenManagers/MinecraftServicesManager.js b/src/TokenManagers/MinecraftServicesManager.js new file mode 100644 index 0000000..21c836a --- /dev/null +++ b/src/TokenManagers/MinecraftServicesManager.js @@ -0,0 +1,60 @@ +const debug = require('debug')('prismarine-auth') +const fetch = require('node-fetch') + +const { Endpoints } = require('../common/Constants') +const { checkStatus } = require('../common/Util') + +class MinecraftServicesTokenManager { + constructor(cache) { + this.cache = cache + } + + async getCachedAccessToken() { + const { mcs: token } = await this.cache.getCached() + debug('[mcs] token cache', token) + + if (!token) return { valid: false } + + const expires = new Date(token.validUntil) + const remainingMs = expires - Date.now() + const valid = remainingMs > 1000 + return { valid, until: expires, token: token.authorizationHeader, data: token } + } + + async setCachedToken(data) { + await this.cache.setCachedPartial(data) + } + + async getAccessToken(sessionTicket, options = {}) { + + const response = await fetch(Endpoints.MinecraftServicesSessionStart, { + method: 'post', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + device: { + applicationType: options.applicationType ?? 'MinecraftPE', + gameVersion: options.version ?? '1.20.62', + id: options.deviceId ?? 'c1681ad3-415e-30cd-abd3-3b8f51e771d1', + memory: options.deviceMemory ?? String(8 * (1024 * 1024 * 1024)), + platform: options.platform ?? 'Windows10', + playFabTitleId: options.playFabtitleId ?? '20CA2', + storePlatform: options.storePlatform ?? 'uwp.store', + type: options.type ?? 'Windows10' + }, + user: { + token: sessionTicket, + tokenType: 'PlayFab' + } + }) + }).then(checkStatus) + + debug('[mc] mc-services token response', response.result) + + await this.setCachedToken({ mcs: response.result }) + + return response.result + + } +} + +module.exports = MinecraftServicesTokenManager diff --git a/src/TokenManagers/PlayfabTokenManager.js b/src/TokenManagers/PlayfabTokenManager.js new file mode 100644 index 0000000..b1c5172 --- /dev/null +++ b/src/TokenManagers/PlayfabTokenManager.js @@ -0,0 +1,71 @@ +const debug = require('debug')('prismarine-auth') +const fetch = require('node-fetch') + +const { Endpoints } = require('../common/Constants') + +class PlayfabTokenManager { + constructor (cache) { + this.cache = cache + } + + async setCachedAccessToken (data) { + await this.cache.setCachedPartial(data) + } + + async getCachedAccessToken () { + const { pfb: cache } = await this.cache.getCached() + + debug('[pf] token cache', cache) + + if (!cache) return + + const expires = new Date(cache.EntityToken.TokenExpiration) + + const remaining = expires - Date.now() + + const valid = remaining > 1000 + + return { valid, until: expires, data: cache } + } + + async getAccessToken (xsts) { + + const response = await fetch(Endpoints.PlayfabLoginWithXbox, { + method: 'post', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + CreateAccount: true, + EncryptedRequest: null, + InfoRequestParameters: { + GetCharacterInventories: false, + GetCharacterList: false, + GetPlayerProfile: true, + GetPlayerStatistics: false, + GetTitleData: false, + GetUserAccountInfo: true, + GetUserData: false, + GetUserInventory: false, + GetUserReadOnlyData: false, + GetUserVirtualCurrency: false, + PlayerStatisticNames: null, + ProfileConstraints: null, + TitleDataKeys: null, + UserDataKeys: null, + UserReadOnlyDataKeys: null + }, + PlayerSecret: null, + TitleId: '20CA2', + XboxToken: `XBL3.0 x=${xsts.userHash};${xsts.XSTSToken}` + }) + }) + + const data = await response.json() + + await this.setCachedAccessToken({ pfb: data.data }) + + return data.data + } + +} + +module.exports = PlayfabTokenManager diff --git a/src/common/Constants.js b/src/common/Constants.js index 28aab21..6632432 100644 --- a/src/common/Constants.js +++ b/src/common/Constants.js @@ -2,6 +2,7 @@ module.exports = { Endpoints: { PCXSTSRelyingParty: 'rp://api.minecraftservices.com/', BedrockXSTSRelyingParty: 'https://multiplayer.minecraft.net/', + PlayfabRelyingParty: 'https://b980a380.minecraft.playfabapi.com/', XboxAuthRelyingParty: 'http://auth.xboxlive.com/', XboxRelyingParty: 'http://xboxlive.com', BedrockAuth: 'https://multiplayer.minecraft.net/authentication', @@ -17,7 +18,9 @@ module.exports = { MinecraftServicesProfile: 'https://api.minecraftservices.com/minecraft/profile', MinecraftServicesReport: 'https://api.minecraftservices.com/player/report', LiveDeviceCodeRequest: 'https://login.live.com/oauth20_connect.srf', - LiveTokenRequest: 'https://login.live.com/oauth20_token.srf' + LiveTokenRequest: 'https://login.live.com/oauth20_token.srf', + MinecraftServicesSessionStart: 'https://authorization.franchise.minecraft-services.net/api/v1.0/session/start', + PlayfabLoginWithXbox: 'https://20ca2.playfabapi.com/Client/LoginWithXbox' }, msalConfig: { // Initialize msal From cf14886c1dc965c85bd1ed98d3d81bb175499784 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Aug 2024 10:58:05 +0100 Subject: [PATCH 02/12] Add PlayFab example --- examples/playfab/deviceCode.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 examples/playfab/deviceCode.js diff --git a/examples/playfab/deviceCode.js b/examples/playfab/deviceCode.js new file mode 100644 index 0000000..e5620f0 --- /dev/null +++ b/examples/playfab/deviceCode.js @@ -0,0 +1,18 @@ +const { Authflow, Titles } = require('prismarine-auth') + +const [, , username, cacheDir] = process.argv + +if (!username) { + console.log('Usage: node deviceCode.js [cacheDirectory]') + process.exit(1) +} + +async function doAuth () { + const flow = new Authflow(username, cacheDir, { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) + + const response = await flow.getPlayfabLogin() + + console.log(response) +} + +module.exports = doAuth() From b99f8522e07f063e2afa04428fc655b0de1102a0 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Aug 2024 10:58:12 +0100 Subject: [PATCH 03/12] Add types --- index.d.ts | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/index.d.ts b/index.d.ts index e559164..f1c6ffb 100644 --- a/index.d.ts +++ b/index.d.ts @@ -29,6 +29,72 @@ declare module 'prismarine-auth' { }): Promise<{ token: string, entitlements: MinecraftJavaLicenses, profile: MinecraftJavaProfile, certificates: MinecraftJavaCertificates }> // Returns a Minecraft Bedrock Edition auth token. Public key parameter must be a KeyLike object. getMinecraftBedrockToken(publicKey: KeyObject): Promise + + getMinecraftServicesToken(): Promise<{ + mcToken: string, + validUntil: string, + treatments: string[], + treatmentContext: string, + configurations: object + }> + + getPlayfabLogin(): Promise<{ + SessionTicket: string; + PlayFabId: string; + NewlyCreated: boolean; + SettingsForUser: { + NeedsAttribution: boolean; + GatherDeviceInfo: boolean; + GatherFocusInfo: boolean; + }; + LastLoginTime: string; + InfoResultPayload: { + AccountInfo: { + PlayFabId: string; + Created: string; + TitleInfo: { + Origination: string; + Created: string; + LastLogin: string; + FirstLogin: string; + isBanned: boolean; + TitlePlayerAccount: { + Id: string; + Type: string; + TypeString: string; + }; + }; + PrivateInfo: Record; + XboxInfo: { + XboxUserId: string; + XboxUserSandbox: string; + }; + }; + UserInventory: any[]; + UserDataVersion: number; + UserReadOnlyDataVersion: number; + CharacterInventories: any[]; + PlayerProfile: { + PublisherId: string; + TitleId: string; + PlayerId: string; + }; + }; + EntityToken: { + EntityToken: string; + TokenExpiration: string; + Entity: { + Id: string; + Type: string; + TypeString: string; + }; + }; + TreatmentAssignment: { + Variants: any[]; + Variables: any[]; + }; + }> + } // via request to https://api.minecraftservices.com/entitlements/license, a list of licenses the player has From 5b876317c031aa64de850d5a5c6c82154f826d50 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Aug 2024 10:58:30 +0100 Subject: [PATCH 04/12] Format Minecraft Services response --- src/TokenManagers/MinecraftServicesManager.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/TokenManagers/MinecraftServicesManager.js b/src/TokenManagers/MinecraftServicesManager.js index 21c836a..bfc2453 100644 --- a/src/TokenManagers/MinecraftServicesManager.js +++ b/src/TokenManagers/MinecraftServicesManager.js @@ -18,7 +18,7 @@ class MinecraftServicesTokenManager { const expires = new Date(token.validUntil) const remainingMs = expires - Date.now() const valid = remainingMs > 1000 - return { valid, until: expires, token: token.authorizationHeader, data: token } + return { valid, until: expires, token: token.mcToken, data: token } } async setCachedToken(data) { @@ -48,9 +48,17 @@ class MinecraftServicesTokenManager { }) }).then(checkStatus) - debug('[mc] mc-services token response', response.result) + const tokenResponse = { + mcToken: response.result.authorizationHeader, + validUntil: response.result.validUntil, + treatments: response.result.treatments, + configurations: response.result.configurations, + treatmentContext: response.result.treatmentContext + } - await this.setCachedToken({ mcs: response.result }) + debug('[mc] mc-services token response', tokenResponse) + + await this.setCachedToken({ mcs: tokenResponse }) return response.result From a69f59b933647239758f856977dc8bfed5919df9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Aug 2024 11:00:19 +0100 Subject: [PATCH 05/12] Linting --- examples/playfab/deviceCode.js | 2 +- examples/services/deviceCode.js | 2 +- src/MicrosoftAuthFlow.js | 2 +- src/TokenManagers/MinecraftServicesManager.js | 18 ++++++++---------- src/TokenManagers/PlayfabTokenManager.js | 6 ++---- 5 files changed, 13 insertions(+), 17 deletions(-) diff --git a/examples/playfab/deviceCode.js b/examples/playfab/deviceCode.js index e5620f0..4ca7244 100644 --- a/examples/playfab/deviceCode.js +++ b/examples/playfab/deviceCode.js @@ -9,7 +9,7 @@ if (!username) { async function doAuth () { const flow = new Authflow(username, cacheDir, { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) - + const response = await flow.getPlayfabLogin() console.log(response) diff --git a/examples/services/deviceCode.js b/examples/services/deviceCode.js index c37f868..f3db144 100644 --- a/examples/services/deviceCode.js +++ b/examples/services/deviceCode.js @@ -9,7 +9,7 @@ if (!username) { async function doAuth () { const flow = new Authflow(username, cacheDir, { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) - + const response = await flow.getMinecraftServicesToken() console.log(response) diff --git a/src/MicrosoftAuthFlow.js b/src/MicrosoftAuthFlow.js index 9c78aa2..fd49f1e 100644 --- a/src/MicrosoftAuthFlow.js +++ b/src/MicrosoftAuthFlow.js @@ -117,7 +117,7 @@ class MicrosoftAuthFlow { } } - async getPlayfabLogin() { + async getPlayfabLogin () { const cache = this.pfb.getCachedAccessToken() if (cache.valid) { diff --git a/src/TokenManagers/MinecraftServicesManager.js b/src/TokenManagers/MinecraftServicesManager.js index bfc2453..88aed75 100644 --- a/src/TokenManagers/MinecraftServicesManager.js +++ b/src/TokenManagers/MinecraftServicesManager.js @@ -5,11 +5,11 @@ const { Endpoints } = require('../common/Constants') const { checkStatus } = require('../common/Util') class MinecraftServicesTokenManager { - constructor(cache) { + constructor (cache) { this.cache = cache } - async getCachedAccessToken() { + async getCachedAccessToken () { const { mcs: token } = await this.cache.getCached() debug('[mcs] token cache', token) @@ -21,19 +21,18 @@ class MinecraftServicesTokenManager { return { valid, until: expires, token: token.mcToken, data: token } } - async setCachedToken(data) { + async setCachedToken (data) { await this.cache.setCachedPartial(data) } - async getAccessToken(sessionTicket, options = {}) { - + async getAccessToken (sessionTicket, options = {}) { const response = await fetch(Endpoints.MinecraftServicesSessionStart, { method: 'post', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - device: { - applicationType: options.applicationType ?? 'MinecraftPE', - gameVersion: options.version ?? '1.20.62', + body: JSON.stringify({ + device: { + applicationType: options.applicationType ?? 'MinecraftPE', + gameVersion: options.version ?? '1.20.62', id: options.deviceId ?? 'c1681ad3-415e-30cd-abd3-3b8f51e771d1', memory: options.deviceMemory ?? String(8 * (1024 * 1024 * 1024)), platform: options.platform ?? 'Windows10', @@ -61,7 +60,6 @@ class MinecraftServicesTokenManager { await this.setCachedToken({ mcs: tokenResponse }) return response.result - } } diff --git a/src/TokenManagers/PlayfabTokenManager.js b/src/TokenManagers/PlayfabTokenManager.js index b1c5172..67c1123 100644 --- a/src/TokenManagers/PlayfabTokenManager.js +++ b/src/TokenManagers/PlayfabTokenManager.js @@ -20,16 +20,15 @@ class PlayfabTokenManager { if (!cache) return const expires = new Date(cache.EntityToken.TokenExpiration) - + const remaining = expires - Date.now() - + const valid = remaining > 1000 return { valid, until: expires, data: cache } } async getAccessToken (xsts) { - const response = await fetch(Endpoints.PlayfabLoginWithXbox, { method: 'post', headers: { 'Content-Type': 'application/json' }, @@ -65,7 +64,6 @@ class PlayfabTokenManager { return data.data } - } module.exports = PlayfabTokenManager From fbe4ded759ef2dd0f69cddba08d9f72386ef2183 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Aug 2024 11:06:32 +0100 Subject: [PATCH 06/12] Add new caches --- src/MicrosoftAuthFlow.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MicrosoftAuthFlow.js b/src/MicrosoftAuthFlow.js index fd49f1e..090df91 100644 --- a/src/MicrosoftAuthFlow.js +++ b/src/MicrosoftAuthFlow.js @@ -28,7 +28,7 @@ async function retry (methodFn, beforeRetry, times) { } } -const CACHE_IDS = ['msal', 'live', 'sisu', 'xbl', 'bed', 'mca'] +const CACHE_IDS = ['msal', 'live', 'sisu', 'xbl', 'bed', 'mca', 'mcs', 'pfb'] class MicrosoftAuthFlow { constructor (username = '', cache = __dirname, options, codeCallback) { From 7ea213136f1ed0a2255441cc2bbe619ac10fca05 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Aug 2024 15:31:20 +0100 Subject: [PATCH 07/12] Correct output --- src/TokenManagers/MinecraftServicesManager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TokenManagers/MinecraftServicesManager.js b/src/TokenManagers/MinecraftServicesManager.js index 88aed75..b818c29 100644 --- a/src/TokenManagers/MinecraftServicesManager.js +++ b/src/TokenManagers/MinecraftServicesManager.js @@ -59,7 +59,7 @@ class MinecraftServicesTokenManager { await this.setCachedToken({ mcs: tokenResponse }) - return response.result + return tokenResponse } } From a79ac536d2bce39bf4810163bbebced93339c9ce Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 23 Aug 2024 13:17:59 +0100 Subject: [PATCH 08/12] Add docs --- README.md | 44 ++++++++++++++++++ docs/API.md | 14 +++++- index.d.ts | 130 +++++++++++++++++++++++++++------------------------- 3 files changed, 124 insertions(+), 64 deletions(-) diff --git a/README.md b/README.md index e9ee2c9..b0815d6 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,50 @@ flow.getMinecraftJavaToken({ fetchProfile: true }).then(console.log) ### getMinecraftBedrockToken See [docs/API.md](docs/API.md) and [example](examples). +### getMinecraftServicesToken +```js +const { Authflow, Titles } = require('prismarine-auth') + +const userIdentifier = 'any unique identifier' +const cacheDir = './' // You can leave this as undefined unless you want to specify a caching directory +const flow = new Authflow(userIdentifier, cacheDir) +// Get a Minecraft Services token, then log it +flow.getMinecraftServicesToken().then(console.log) +``` + +### Expected Response +```json +{ + "mcToken": "MCToken eyJ...", + "validUntil": "1970-01-01T00:00:00.000Z", + "treatments": [ + "mc-enable-feedback-landing-page", + "mc-store-enableinbox", + "mc-nps-freeorpaid-paidaug24", + // and more + ], + "configurations": { + "validation": { + "id": "Validation", + "parameters": { + "minecraftnetaatest": "false" + } + }, + "minecraft": { + "id": "Minecraft", + "parameters": { + "with-spongebobadd-button-noswitch": "true", + "sfsdfsdfsfss": "true", + "fsdfd": "true", + "mc-maelstrom-disable": "true", + // and more + } + } + }, + "treatmentContext": "mc-sunsetting_5:31118471;mc-..." +} +``` + ### More [View more examples here](https://github.com/PrismarineJS/prismarine-auth/tree/master/examples). diff --git a/docs/API.md b/docs/API.md index 1060f93..da42e33 100644 --- a/docs/API.md +++ b/docs/API.md @@ -39,7 +39,7 @@ Example usage : const { Authflow } = require('prismarine-auth') const flow = new Authflow() // No parameters needed flow.getXboxToken().then(console.log) -`````` +``` #### getMinecraftJavaToken (options?: { fetchEntitlements?: boolean fetchProfile?: boolean }) : Promise<{ token: string, entitlements: object, profile: object }> @@ -54,6 +54,18 @@ Returns a Minecraft: Bedrock Edition auth token. The first parameter is a Node.j The return object are multiple JWTs returned from the auth server, from both the Mojang and Xbox steps. +### getPlayfabLogin (): Promise + +Returns a Playfab login response which can be used to authenticate to the Playfab API. The SessionTicket returned in the response is used when generating the MCToken. + +[Returns ServerLoginResult](https://learn.microsoft.com/en-us/rest/api/playfab/server/authentication/login-with-xbox?view=playfab-rest#serverloginresult) + +### getMinecraftServicesToken (): Promise + +Returns an mctoken which can be used to query the minecraft-services.net/api and is also used to authenticate the WebSocket connection for the NetherNet WebRTC signalling channel. + +The return object contains the `mcToken` and `treatments` relating to the features the user has access to. + ### Titles * A list of known client IDs for convenience. Currently exposes `MinecraftNintendoSwitch` and `MinecraftJava`. These should be passed to `Authflow` options constructor (make sure to set appropriate `deviceType`). diff --git a/index.d.ts b/index.d.ts index f1c6ffb..e31454b 100644 --- a/index.d.ts +++ b/index.d.ts @@ -30,70 +30,9 @@ declare module 'prismarine-auth' { // Returns a Minecraft Bedrock Edition auth token. Public key parameter must be a KeyLike object. getMinecraftBedrockToken(publicKey: KeyObject): Promise - getMinecraftServicesToken(): Promise<{ - mcToken: string, - validUntil: string, - treatments: string[], - treatmentContext: string, - configurations: object - }> + getMinecraftServicesToken(): Promise - getPlayfabLogin(): Promise<{ - SessionTicket: string; - PlayFabId: string; - NewlyCreated: boolean; - SettingsForUser: { - NeedsAttribution: boolean; - GatherDeviceInfo: boolean; - GatherFocusInfo: boolean; - }; - LastLoginTime: string; - InfoResultPayload: { - AccountInfo: { - PlayFabId: string; - Created: string; - TitleInfo: { - Origination: string; - Created: string; - LastLogin: string; - FirstLogin: string; - isBanned: boolean; - TitlePlayerAccount: { - Id: string; - Type: string; - TypeString: string; - }; - }; - PrivateInfo: Record; - XboxInfo: { - XboxUserId: string; - XboxUserSandbox: string; - }; - }; - UserInventory: any[]; - UserDataVersion: number; - UserReadOnlyDataVersion: number; - CharacterInventories: any[]; - PlayerProfile: { - PublisherId: string; - TitleId: string; - PlayerId: string; - }; - }; - EntityToken: { - EntityToken: string; - TokenExpiration: string; - Entity: { - Id: string; - Type: string; - TypeString: string; - }; - }; - TreatmentAssignment: { - Variants: any[]; - Variables: any[]; - }; - }> + getPlayfabLogin(): Promise } @@ -210,4 +149,69 @@ declare module 'prismarine-auth' { } export type CacheFactory = (options: { username: string, cacheName: string }) => Cache + + export type GetMinecraftServicesResponse = { + mcToken: string + validUntil: string + treatments: string[] + treatmentContext: string + configurations: object + } + + export type GetPlayfabLoginResponse = { + SessionTicket: string; + PlayFabId: string; + NewlyCreated: boolean; + SettingsForUser: { + NeedsAttribution: boolean; + GatherDeviceInfo: boolean; + GatherFocusInfo: boolean; + }; + LastLoginTime: string; + InfoResultPayload: { + AccountInfo: { + PlayFabId: string; + Created: string; + TitleInfo: { + Origination: string; + Created: string; + LastLogin: string; + FirstLogin: string; + isBanned: boolean; + TitlePlayerAccount: { + Id: string; + Type: string; + TypeString: string; + }; + }; + PrivateInfo: Record; + XboxInfo: { + XboxUserId: string; + XboxUserSandbox: string; + }; + }; + UserInventory: any[]; + UserDataVersion: number; + UserReadOnlyDataVersion: number; + CharacterInventories: any[]; + PlayerProfile: { + PublisherId: string; + TitleId: string; + PlayerId: string; + }; + }; + EntityToken: { + EntityToken: string; + TokenExpiration: string; + Entity: { + Id: string; + Type: string; + TypeString: string; + }; + }; + TreatmentAssignment: { + Variants: any[]; + Variables: any[]; + }; + } } From 5f3d079831912fb4562406d3a6935d1c08df7f4b Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 13 Sep 2024 12:28:16 +0100 Subject: [PATCH 09/12] Fix some types --- index.d.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index e31454b..69d5d84 100644 --- a/index.d.ts +++ b/index.d.ts @@ -3,6 +3,11 @@ import { KeyObject } from 'crypto' declare module 'prismarine-auth' { export class Authflow { + + username: string + + options: MicrosoftAuthFlowOptions + /** * Creates a new Authflow instance, which holds its own token cache * @param username A unique identifier. If using password auth, this should be an email. @@ -15,7 +20,7 @@ declare module 'prismarine-auth' { // Returns a Microsoft Oauth access token -- https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens getMsaToken(): Promise // Returns an XSTS token -- https://docs.microsoft.com/en-us/gaming/xbox-live/api-ref/xbox-live-rest/additional/edsauthorization - getXboxToken(relyingParty?: string): Promise<{ + getXboxToken(relyingParty?: string, forceRefresh?: boolean): Promise<{ userXUID: string, userHash: string, XSTSToken: string, From 33e575f8c615bf1adf98fa1c7771fb626655434a Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jan 2025 09:44:12 +0000 Subject: [PATCH 10/12] Rename `getMinecraftServicesToken` to `getMinecraftBedrockServicesToken` --- README.md | 4 ++-- docs/API.md | 2 +- examples/services/deviceCode.js | 2 +- index.d.ts | 4 ++-- src/MicrosoftAuthFlow.js | 6 +++--- ...ervicesManager.js => MinecraftBedrockServicesManager.js} | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) rename src/TokenManagers/{MinecraftServicesManager.js => MinecraftBedrockServicesManager.js} (95%) diff --git a/README.md b/README.md index b0815d6..d075ad3 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ flow.getMinecraftJavaToken({ fetchProfile: true }).then(console.log) ### getMinecraftBedrockToken See [docs/API.md](docs/API.md) and [example](examples). -### getMinecraftServicesToken +### getMinecraftBedrockServicesToken ```js const { Authflow, Titles } = require('prismarine-auth') @@ -87,7 +87,7 @@ const userIdentifier = 'any unique identifier' const cacheDir = './' // You can leave this as undefined unless you want to specify a caching directory const flow = new Authflow(userIdentifier, cacheDir) // Get a Minecraft Services token, then log it -flow.getMinecraftServicesToken().then(console.log) +flow.getMinecraftBedrockServicesToken().then(console.log) ``` ### Expected Response diff --git a/docs/API.md b/docs/API.md index da42e33..03c0ee4 100644 --- a/docs/API.md +++ b/docs/API.md @@ -60,7 +60,7 @@ Returns a Playfab login response which can be used to authenticate to the Playfa [Returns ServerLoginResult](https://learn.microsoft.com/en-us/rest/api/playfab/server/authentication/login-with-xbox?view=playfab-rest#serverloginresult) -### getMinecraftServicesToken (): Promise +### getMinecraftBedrockServicesToken (): Promise Returns an mctoken which can be used to query the minecraft-services.net/api and is also used to authenticate the WebSocket connection for the NetherNet WebRTC signalling channel. diff --git a/examples/services/deviceCode.js b/examples/services/deviceCode.js index f3db144..bbf890f 100644 --- a/examples/services/deviceCode.js +++ b/examples/services/deviceCode.js @@ -10,7 +10,7 @@ if (!username) { async function doAuth () { const flow = new Authflow(username, cacheDir, { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) - const response = await flow.getMinecraftServicesToken() + const response = await flow.getMinecraftBedrockServicesToken({ version: '1.21.50' }) console.log(response) } diff --git a/index.d.ts b/index.d.ts index 69d5d84..c451a93 100644 --- a/index.d.ts +++ b/index.d.ts @@ -35,7 +35,7 @@ declare module 'prismarine-auth' { // Returns a Minecraft Bedrock Edition auth token. Public key parameter must be a KeyLike object. getMinecraftBedrockToken(publicKey: KeyObject): Promise - getMinecraftServicesToken(): Promise + getMinecraftBedrockServicesToken(): Promise getPlayfabLogin(): Promise @@ -155,7 +155,7 @@ declare module 'prismarine-auth' { export type CacheFactory = (options: { username: string, cacheName: string }) => Cache - export type GetMinecraftServicesResponse = { + export type GetMinecraftBedrockServicesResponse = { mcToken: string validUntil: string treatments: string[] diff --git a/src/MicrosoftAuthFlow.js b/src/MicrosoftAuthFlow.js index 090df91..ff45c86 100644 --- a/src/MicrosoftAuthFlow.js +++ b/src/MicrosoftAuthFlow.js @@ -14,7 +14,7 @@ const XboxTokenManager = require('./TokenManagers/XboxTokenManager') const MsaTokenManager = require('./TokenManagers/MsaTokenManager') const BedrockTokenManager = require('./TokenManagers/MinecraftBedrockTokenManager') const PlayfabTokenManager = require('./TokenManagers/PlayfabTokenManager') -const MinecraftServicesTokenManager = require('./TokenManagers/MinecraftServicesManager') +const MinecraftServicesTokenManager = require('./TokenManagers/MinecraftBedrockServicesManager') async function retry (methodFn, beforeRetry, times) { while (times--) { @@ -131,7 +131,7 @@ class MicrosoftAuthFlow { return playfab } - async getMinecraftServicesToken () { + async getMinecraftBedrockServicesToken ({ verison }) { const cache = await this.mcs.getCachedAccessToken() if (cache.valid) { @@ -140,7 +140,7 @@ class MicrosoftAuthFlow { const playfab = await this.getPlayfabLogin() - const mcs = await this.mcs.getAccessToken(playfab.SessionTicket) + const mcs = await this.mcs.getAccessToken(playfab.SessionTicket, { verison }) return mcs } diff --git a/src/TokenManagers/MinecraftServicesManager.js b/src/TokenManagers/MinecraftBedrockServicesManager.js similarity index 95% rename from src/TokenManagers/MinecraftServicesManager.js rename to src/TokenManagers/MinecraftBedrockServicesManager.js index b818c29..c97639f 100644 --- a/src/TokenManagers/MinecraftServicesManager.js +++ b/src/TokenManagers/MinecraftBedrockServicesManager.js @@ -4,7 +4,7 @@ const fetch = require('node-fetch') const { Endpoints } = require('../common/Constants') const { checkStatus } = require('../common/Util') -class MinecraftServicesTokenManager { +class MinecraftBedrockServicesTokenManager { constructor (cache) { this.cache = cache } @@ -63,4 +63,4 @@ class MinecraftServicesTokenManager { } } -module.exports = MinecraftServicesTokenManager +module.exports = MinecraftBedrockServicesTokenManager From 117e0cf4b77b3c717a4c8eb3eb593e02c4fe7cf2 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jan 2025 09:48:25 +0000 Subject: [PATCH 11/12] Remove node-fetch --- src/TokenManagers/MinecraftBedrockServicesManager.js | 1 - src/TokenManagers/PlayfabTokenManager.js | 1 - 2 files changed, 2 deletions(-) diff --git a/src/TokenManagers/MinecraftBedrockServicesManager.js b/src/TokenManagers/MinecraftBedrockServicesManager.js index c97639f..06f9ed7 100644 --- a/src/TokenManagers/MinecraftBedrockServicesManager.js +++ b/src/TokenManagers/MinecraftBedrockServicesManager.js @@ -1,5 +1,4 @@ const debug = require('debug')('prismarine-auth') -const fetch = require('node-fetch') const { Endpoints } = require('../common/Constants') const { checkStatus } = require('../common/Util') diff --git a/src/TokenManagers/PlayfabTokenManager.js b/src/TokenManagers/PlayfabTokenManager.js index 67c1123..3ba041f 100644 --- a/src/TokenManagers/PlayfabTokenManager.js +++ b/src/TokenManagers/PlayfabTokenManager.js @@ -1,5 +1,4 @@ const debug = require('debug')('prismarine-auth') -const fetch = require('node-fetch') const { Endpoints } = require('../common/Constants') From 38b663e07302390f6631fb28f4be5b6b6b871a56 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 20 Jan 2025 19:39:35 +0000 Subject: [PATCH 12/12] Update types --- docs/API.md | 2 +- index.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/API.md b/docs/API.md index 03c0ee4..0397e56 100644 --- a/docs/API.md +++ b/docs/API.md @@ -60,7 +60,7 @@ Returns a Playfab login response which can be used to authenticate to the Playfa [Returns ServerLoginResult](https://learn.microsoft.com/en-us/rest/api/playfab/server/authentication/login-with-xbox?view=playfab-rest#serverloginresult) -### getMinecraftBedrockServicesToken (): Promise +### getMinecraftBedrockServicesToken ({ version }): Promise Returns an mctoken which can be used to query the minecraft-services.net/api and is also used to authenticate the WebSocket connection for the NetherNet WebRTC signalling channel. diff --git a/index.d.ts b/index.d.ts index c451a93..eb5d9ab 100644 --- a/index.d.ts +++ b/index.d.ts @@ -35,7 +35,7 @@ declare module 'prismarine-auth' { // Returns a Minecraft Bedrock Edition auth token. Public key parameter must be a KeyLike object. getMinecraftBedrockToken(publicKey: KeyObject): Promise - getMinecraftBedrockServicesToken(): Promise + getMinecraftBedrockServicesToken(config: { version: string }): Promise getPlayfabLogin(): Promise