Skip to content

Commit 1aef6e1

Browse files
authored
Scope constants (#127)
* Scope constants * cleanup
1 parent abd312f commit 1aef6e1

10 files changed

+77
-67
lines changed

index.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ declare module 'prismarine-auth' {
2929
// Returns a Minecraft Java Edition auth token
3030
getMinecraftJavaToken(options?: {
3131
fetchCertificates?: boolean,
32-
fetchEntitlements?: boolean
32+
fetchEntitlements?: boolean,
3333
fetchProfile?: boolean
34-
}): Promise<{ token: string, entitlements: MinecraftJavaLicenses, profile: MinecraftJavaProfile, certificates: MinecraftJavaCertificates }>
34+
}): Promise<{ token: string, entitlements: MinecraftJavaEntitlements, profile: MinecraftJavaProfile, certificates: MinecraftJavaCertificates }>
3535
// Returns a Minecraft Bedrock Edition auth token. Public key parameter must be a KeyLike object.
3636
getMinecraftBedrockToken(publicKey: KeyObject): Promise<string>
3737

src/MicrosoftAuthFlow.js

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,35 +119,26 @@ class MicrosoftAuthFlow {
119119

120120
async getPlayfabLogin () {
121121
const cache = this.pfb.getCachedAccessToken()
122-
123122
if (cache.valid) {
124123
return cache.data
125124
}
126-
127125
const xsts = await this.getXboxToken(Endpoints.PlayfabRelyingParty)
128-
129126
const playfab = await this.pfb.getAccessToken(xsts)
130-
131127
return playfab
132128
}
133129

134130
async getMinecraftBedrockServicesToken ({ verison }) {
135131
const cache = await this.mcs.getCachedAccessToken()
136-
137132
if (cache.valid) {
138133
return cache.data
139134
}
140-
141135
const playfab = await this.getPlayfabLogin()
142-
143136
const mcs = await this.mcs.getAccessToken(playfab.SessionTicket, { verison })
144-
145137
return mcs
146138
}
147139

148-
async getXboxToken (relyingParty = this.options.relyingParty || Endpoints.XboxRelyingParty, forceRefresh = false) {
140+
async getXboxToken (relyingParty = this.options.relyingParty || Endpoints.xbox.relyingParty, forceRefresh = false) {
149141
const options = { ...this.options, relyingParty }
150-
151142
const { xstsToken, userToken, deviceToken, titleToken } = await this.xbl.getCachedTokens(relyingParty)
152143

153144
if (xstsToken.valid && !forceRefresh) {
@@ -192,7 +183,7 @@ class MicrosoftAuthFlow {
192183
} else {
193184
debug('[mc] Need to obtain tokens')
194185
await retry(async () => {
195-
const xsts = await this.getXboxToken(Endpoints.PCXSTSRelyingParty)
186+
const xsts = await this.getXboxToken(Endpoints.minecraftJava.XSTSRelyingParty)
196187
debug('[xbl] xsts data', xsts)
197188
response.token = await this.mca.getAccessToken(xsts)
198189
}, () => { this.xbl.forceRefresh = true }, 2)
@@ -207,6 +198,9 @@ class MicrosoftAuthFlow {
207198
if (options.fetchCertificates) {
208199
response.certificates = await this.mca.fetchCertificates(response.token).catch(e => debug('Failed to obtain keypair data', e))
209200
}
201+
if (options.fetchAttributes) {
202+
response.attributes = await this.mca.fetchAttributes(response.token).catch(e => debug('Failed to obtain attributes data', e))
203+
}
210204

211205
return response
212206
}
@@ -222,7 +216,7 @@ class MicrosoftAuthFlow {
222216
if (!publicKey) throw new Error('Need to specifiy a ECDH x509 URL encoded public key')
223217
debug('[mc] Need to obtain tokens')
224218
return await retry(async () => {
225-
const xsts = await this.getXboxToken(Endpoints.BedrockXSTSRelyingParty)
219+
const xsts = await this.getXboxToken(Endpoints.minecraftBedrock.XSTSRelyingParty)
226220
debug('[xbl] xsts data', xsts)
227221
const token = await this.mba.getAccessToken(publicKey, xsts)
228222
// If we want to auth with a title ID, make sure there's a TitleID in the response

src/TokenManagers/LiveTokenManager.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class LiveTokenManager {
4646
credentials: 'include' // This cookie handler does not work on node-fetch ...
4747
}
4848

49-
const token = await fetch(Endpoints.LiveTokenRequest, codeRequest).then(checkStatus)
49+
const token = await fetch(Endpoints.live.tokenRequest, codeRequest).then(checkStatus)
5050
this.updateCache(token)
5151
return token
5252
}
@@ -91,7 +91,7 @@ class LiveTokenManager {
9191

9292
const cookies = []
9393

94-
const res = await fetch(Endpoints.LiveDeviceCodeRequest, codeRequest)
94+
const res = await fetch(Endpoints.live.deviceCodeRequest, codeRequest)
9595
.then(res => {
9696
if (res.status !== 200) {
9797
res.text().then(console.warn)
@@ -128,7 +128,7 @@ class LiveTokenManager {
128128
}).toString()
129129
}
130130

131-
const token = await fetch(Endpoints.LiveTokenRequest + '?client_id=' + this.clientId, verifi)
131+
const token = await fetch(Endpoints.live.tokenRequest + '?client_id=' + this.clientId, verifi)
132132
.then(res => res.json()).then(res => {
133133
if (res.error) {
134134
if (res.error === 'authorization_pending') {

src/TokenManagers/MinecraftBedrockServicesManager.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class MinecraftBedrockServicesTokenManager {
2525
}
2626

2727
async getAccessToken (sessionTicket, options = {}) {
28-
const response = await fetch(Endpoints.MinecraftServicesSessionStart, {
28+
const response = await fetch(Endpoints.minecraftBedrock.servicesSessionStart, {
2929
method: 'post',
3030
headers: { 'Content-Type': 'application/json' },
3131
body: JSON.stringify({

src/TokenManagers/MinecraftBedrockTokenManager.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const debug = require('debug')('prismarine-auth')
22

33
const { Endpoints } = require('../common/Constants')
4-
const { checkStatus } = require('../common/Util')
4+
const { checkStatusWithHelp } = require('../common/Util')
55

66
class BedrockTokenManager {
77
constructor (cache) {
@@ -51,11 +51,11 @@ class BedrockTokenManager {
5151
'User-Agent': 'MCPE/UWP',
5252
Authorization: `XBL3.0 x=${xsts.userHash};${xsts.XSTSToken}`
5353
}
54-
const MineServicesResponse = await fetch(Endpoints.BedrockAuth, {
54+
const MineServicesResponse = await fetch(Endpoints.minecraftBedrock.authenticate, {
5555
method: 'post',
5656
headers,
5757
body: JSON.stringify({ identityPublicKey: clientPublicKey })
58-
}).then(checkStatus)
58+
}).then(checkStatusWithHelp({ 401: 'Ensure that you are able to sign-in to Minecraft with this account' }))
5959

6060
debug('[mc] mc auth response', MineServicesResponse)
6161
await this.setCachedAccessToken(MineServicesResponse)

src/TokenManagers/MinecraftJavaTokenManager.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class MinecraftJavaTokenManager {
6565

6666
async getAccessToken (xsts) {
6767
debug('[mc] authing to minecraft', xsts)
68-
const MineServicesResponse = await fetch(Endpoints.MinecraftServicesLogWithXbox, {
68+
const MineServicesResponse = await fetch(Endpoints.minecraftJava.loginWithXbox, {
6969
method: 'post',
7070
...fetchOptions,
7171
body: JSON.stringify({ identityToken: `XBL3.0 x=${xsts.userHash};${xsts.XSTSToken}` })
@@ -79,7 +79,7 @@ class MinecraftJavaTokenManager {
7979
async fetchProfile (accessToken) {
8080
debug(`[mc] fetching minecraft profile with ${accessToken.slice(0, 16)}`)
8181
const headers = { ...fetchOptions.headers, Authorization: `Bearer ${accessToken}` }
82-
const profile = await fetch(Endpoints.MinecraftServicesProfile, { headers })
82+
const profile = await fetch(Endpoints.minecraftJava.profile, { headers })
8383
.then(checkStatus)
8484
debug(`[mc] got profile response: ${profile}`)
8585
return profile
@@ -93,15 +93,15 @@ class MinecraftJavaTokenManager {
9393
async fetchEntitlements (accessToken) {
9494
debug(`[mc] fetching entitlements with ${accessToken.slice(0, 16)}`)
9595
const headers = { ...fetchOptions.headers, Authorization: `Bearer ${accessToken}` }
96-
const entitlements = await fetch(Endpoints.MinecraftServicesLicense + `?requestId=${crypto.randomUUID()}`, { headers }).then(checkStatus)
96+
const entitlements = await fetch(Endpoints.minecraftJava.entitlements + `?requestId=${crypto.randomUUID()}`, { headers }).then(checkStatus)
9797
debug(`[mc] got entitlement response: ${entitlements}`)
9898
return entitlements
9999
}
100100

101101
async fetchCertificates (accessToken) {
102102
debug(`[mc] fetching key-pair with ${accessToken.slice(0, 16)}`)
103103
const headers = { ...fetchOptions.headers, Authorization: `Bearer ${accessToken}` }
104-
const cert = await fetch(Endpoints.MinecraftServicesCertificate, { method: 'post', headers }).then(checkStatus)
104+
const cert = await fetch(Endpoints.minecraftJava.certificates, { method: 'post', headers }).then(checkStatus)
105105
debug('[mc] got key-pair')
106106
const profileKeys = {
107107
publicPEM: cert.keyPair.publicKey,
@@ -176,7 +176,7 @@ class MinecraftJavaTokenManager {
176176
}
177177

178178
debug('[mc] reporting player with payload', body)
179-
const reportResponse = await fetch(Endpoints.MinecraftServicesReport, { method: 'post', headers, body }).then(checkStatus)
179+
const reportResponse = await fetch(Endpoints.minecraftJava.reportPlayer, { method: 'post', headers, body }).then(checkStatus)
180180
debug('[mc] server response for report', reportResponse)
181181
return true
182182
}

src/TokenManagers/PlayfabTokenManager.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const debug = require('debug')('prismarine-auth')
2-
32
const { Endpoints } = require('../common/Constants')
43

54
class PlayfabTokenManager {
@@ -13,17 +12,11 @@ class PlayfabTokenManager {
1312

1413
async getCachedAccessToken () {
1514
const { pfb: cache } = await this.cache.getCached()
16-
1715
debug('[pf] token cache', cache)
18-
1916
if (!cache) return
20-
2117
const expires = new Date(cache.EntityToken.TokenExpiration)
22-
2318
const remaining = expires - Date.now()
24-
2519
const valid = remaining > 1000
26-
2720
return { valid, until: expires, data: cache }
2821
}
2922

@@ -58,9 +51,7 @@ class PlayfabTokenManager {
5851
})
5952

6053
const data = await response.json()
61-
6254
await this.setCachedAccessToken({ pfb: data.data })
63-
6455
return data.data
6556
}
6657
}

src/TokenManagers/XboxTokenManager.js

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ class XboxTokenManager {
7575
}
7676

7777
const body = JSON.stringify(payload)
78-
const signature = this.sign(Endpoints.XboxUserAuth, '', body).toString('base64')
78+
const signature = this.sign(Endpoints.xbox.userAuth, '', body).toString('base64')
7979
const headers = { ...this.headers, signature, 'Content-Type': 'application/json', accept: 'application/json', 'x-xbl-contract-version': '2' }
8080

81-
const ret = await fetch(Endpoints.XboxUserAuth, { method: 'post', headers, body }).then(checkStatus)
81+
const ret = await fetch(Endpoints.xbox.userAuth, { method: 'post', headers, body }).then(checkStatus)
8282

8383
await this.setCachedToken({ userToken: ret })
8484

@@ -147,11 +147,11 @@ class XboxTokenManager {
147147

148148
const body = JSON.stringify(payload)
149149

150-
const signature = this.sign(Endpoints.SisuAuthorize, '', body).toString('base64')
150+
const signature = this.sign(Endpoints.xbox.sisuAuthorize, '', body).toString('base64')
151151

152152
const headers = { Signature: signature }
153153

154-
const req = await fetch(Endpoints.SisuAuthorize, { method: 'post', headers, body })
154+
const req = await fetch(Endpoints.xbox.sisuAuthorize, { method: 'post', headers, body })
155155
const ret = await req.json()
156156
if (!req.ok) this.checkTokenError(parseInt(req.headers.get('x-err')), ret)
157157

@@ -186,11 +186,11 @@ class XboxTokenManager {
186186
}
187187

188188
const body = JSON.stringify(payload)
189-
const signature = this.sign(Endpoints.XstsAuthorize, '', body).toString('base64')
189+
const signature = this.sign(Endpoints.xbox.xstsAuthorize, '', body).toString('base64')
190190

191191
const headers = { ...this.headers, Signature: signature }
192192

193-
const req = await fetch(Endpoints.XstsAuthorize, { method: 'post', headers, body })
193+
const req = await fetch(Endpoints.xbox.xstsAuthorize, { method: 'post', headers, body })
194194
const ret = await req.json()
195195
if (!req.ok) this.checkTokenError(ret.XErr, ret)
196196

@@ -226,10 +226,10 @@ class XboxTokenManager {
226226
}
227227

228228
const body = JSON.stringify(payload)
229-
const signature = this.sign(Endpoints.XboxDeviceAuth, '', body).toString('base64')
229+
const signature = this.sign(Endpoints.xbox.deviceAuth, '', body).toString('base64')
230230
const headers = { ...this.headers, Signature: signature }
231231

232-
const ret = await fetch(Endpoints.XboxDeviceAuth, { method: 'post', headers, body }).then(checkStatus)
232+
const ret = await fetch(Endpoints.xbox.deviceAuth, { method: 'post', headers, body }).then(checkStatus)
233233

234234
await this.setCachedToken({ deviceToken: ret })
235235

@@ -251,11 +251,11 @@ class XboxTokenManager {
251251
TokenType: 'JWT'
252252
}
253253
const body = JSON.stringify(payload)
254-
const signature = this.sign(Endpoints.XboxTitleAuth, '', body).toString('base64')
254+
const signature = this.sign(Endpoints.xbox.titleAuth, '', body).toString('base64')
255255

256256
const headers = { ...this.headers, Signature: signature }
257257

258-
const ret = await fetch(Endpoints.XboxTitleAuth, { method: 'post', headers, body }).then(checkStatus)
258+
const ret = await fetch(Endpoints.xbox.titleAuth, { method: 'post', headers, body }).then(checkStatus)
259259

260260
await this.setCachedToken({ titleToken: ret })
261261

src/common/Constants.js

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
module.exports = {
22
Endpoints: {
3-
PCXSTSRelyingParty: 'rp://api.minecraftservices.com/',
4-
BedrockXSTSRelyingParty: 'https://multiplayer.minecraft.net/',
3+
minecraftJava: {
4+
XSTSRelyingParty: 'rp://api.minecraftservices.com/',
5+
loginWithXbox: 'https://api.minecraftservices.com/authentication/login_with_xbox',
6+
profile: 'https://api.minecraftservices.com/minecraft/profile',
7+
license: 'https://api.minecraftservices.com/entitlements/license',
8+
entitlements: 'https://api.minecraftservices.com/entitlements/mcstore',
9+
attributes: 'https://api.minecraftservices.com/player/attributes',
10+
certificates: 'https://api.minecraftservices.com/player/certificates',
11+
reportPlayer: 'https://api.minecraftservices.com/player/report'
12+
},
13+
minecraftBedrock: {
14+
XSTSRelyingParty: 'https://multiplayer.minecraft.net/',
15+
authenticate: 'https://multiplayer.minecraft.net/authentication',
16+
servicesSessionStart: 'https://authorization.franchise.minecraft-services.net/api/v1.0/session/start'
17+
},
18+
xbox: {
19+
authRelyingParty: 'http://auth.xboxlive.com',
20+
relyingParty: 'http://xboxlive.com',
21+
deviceAuth: 'https://device.auth.xboxlive.com/device/authenticate',
22+
titleAuth: 'https://title.auth.xboxlive.com/title/authenticate',
23+
userAuth: 'https://user.auth.xboxlive.com/user/authenticate',
24+
sisuAuthorize: 'https://sisu.xboxlive.com/authorize',
25+
xstsAuthorize: 'https://xsts.auth.xboxlive.com/xsts/authorize'
26+
},
27+
live: {
28+
deviceCodeRequest: 'https://login.live.com/oauth20_connect.srf',
29+
tokenRequest: 'https://login.live.com/oauth20_token.srf'
30+
},
531
PlayfabRelyingParty: 'https://b980a380.minecraft.playfabapi.com/',
6-
XboxAuthRelyingParty: 'http://auth.xboxlive.com/',
7-
XboxRelyingParty: 'http://xboxlive.com',
8-
BedrockAuth: 'https://multiplayer.minecraft.net/authentication',
9-
XboxDeviceAuth: 'https://device.auth.xboxlive.com/device/authenticate',
10-
XboxTitleAuth: 'https://title.auth.xboxlive.com/title/authenticate',
11-
XboxUserAuth: 'https://user.auth.xboxlive.com/user/authenticate',
12-
SisuAuthorize: 'https://sisu.xboxlive.com/authorize',
13-
XstsAuthorize: 'https://xsts.auth.xboxlive.com/xsts/authorize',
14-
MinecraftServicesLogWithXbox: 'https://api.minecraftservices.com/authentication/login_with_xbox',
15-
MinecraftServicesCertificate: 'https://api.minecraftservices.com/player/certificates',
16-
MinecraftServicesEntitlement: 'https://api.minecraftservices.com/entitlements/mcstore',
17-
MinecraftServicesLicense: 'https://api.minecraftservices.com/entitlements/license',
18-
MinecraftServicesProfile: 'https://api.minecraftservices.com/minecraft/profile',
19-
MinecraftServicesReport: 'https://api.minecraftservices.com/player/report',
20-
LiveDeviceCodeRequest: 'https://login.live.com/oauth20_connect.srf',
21-
LiveTokenRequest: 'https://login.live.com/oauth20_token.srf',
22-
MinecraftServicesSessionStart: 'https://authorization.franchise.minecraft-services.net/api/v1.0/session/start',
2332
PlayfabLoginWithXbox: 'https://20ca2.playfabapi.com/Client/LoginWithXbox'
2433
},
2534
msalConfig: {
@@ -47,5 +56,6 @@ module.exports = {
4756
2148916236: 'Your account requires proof of age. Please login to https://login.live.com/login.srf and provide proof of age.',
4857
2148916237: 'Your account has reached the its limit for playtime. Your account has been blocked from logging in.',
4958
2148916238: 'The account date of birth is under 18 years and cannot proceed unless the account is added to a family by an adult.'
50-
}
59+
},
60+
oneDayMs: 86400000
5161
}

src/common/Util.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,23 @@ async function checkStatus (res) {
1111
}
1212
}
1313

14+
function checkStatusWithHelp (errorDict) {
15+
return async function (res) {
16+
if (res.ok) return res.json() // res.status >= 200 && res.status < 300
17+
const resp = await res.text()
18+
debug('Request fail', resp)
19+
throw new Error(`${res.status} ${res.statusText} ${resp} ${errorDict[res.status] ?? ''}`)
20+
}
21+
}
22+
1423
function createHash (input) {
15-
return crypto.createHash('sha1').update(input ?? '', 'binary').digest('hex').substr(0, 6)
24+
return crypto.createHash('sha1')
25+
.update(input ?? '', 'binary')
26+
.digest('hex').substr(0, 6)
27+
}
28+
29+
function nextUUID () {
30+
return globalThis.crypto.randomUUID()
1631
}
1732

18-
module.exports = { checkStatus, createHash }
33+
module.exports = { checkStatus, checkStatusWithHelp, createHash, nextUUID }

0 commit comments

Comments
 (0)