Skip to content

Commit 860d2ad

Browse files
authored
feat: Microsoft authentication! (#150)
fixes #36
1 parent d81aace commit 860d2ad

28 files changed

+780
-158
lines changed

.github/workflows/publish.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Deploy to GitHub pages
1+
name: Release
22
env:
33
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
44
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}

README.MD

+1-1
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ Press `Y` to set query parameters to url of your current game state.
113113
- `?version=<version>` - Set the version for server
114114
- `?lockConnect=true` - Disable cancel / save buttons, useful for integrates iframes
115115
- `?reconnect=true` - Reconnect to the server on page reloads. Available in **dev mode only** and very useful on server testing.
116-
<!-- - `?password=<password>` - Set the password on load -->
117116
- `?loadSave=<save_name>` - Load the save on load with the specified folder name (not title)
118117
- `?singleplayer=1` - Create empty world on load. Nothing will be saved
119118
- `?noSave=true` - Disable auto save on unload / disconnect / export. Only manual save with `/save` command will work
119+
<!-- - `?requiresAuth=true` - Show the Microsoft login screen on server connect. Useful for servers that require authentication (running in online mode) -->
120120

121121
- `?map=<map_url>` - Load the map from ZIP. You can use any url, but it must be CORS enabled.
122122
- `?setting=<setting_name>:<setting_value>` - Set the and lock the setting on load. You can set multiple settings by separating them with `&` e.g. `?setting=autoParkour:true&setting=renderDistance:4`

cypress/e2e/index.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const compareRenderedFlatWorld = () => {
1414
}
1515

1616
const testWorldLoad = () => {
17-
return cy.document().then({ timeout: 20_000 }, doc => {
17+
return cy.document().then({ timeout: 25_000 }, doc => {
1818
return new Cypress.Promise(resolve => {
1919
doc.addEventListener('cypress-world-ready', resolve)
2020
})

esbuild.mjs

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ const buildOptions = {
6060
net: 'net-browserify',
6161
assert: 'assert',
6262
dns: './src/dns.js',
63+
'yggdrasil': './src/yggdrasilReplacement.ts',
6364
// todo write advancedAliases plugin
6465
},
6566
inject: [

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@
4848
"@types/react-dom": "^18.2.7",
4949
"@types/wicg-file-system-access": "^2023.10.2",
5050
"@xmcl/text-component": "^2.1.3",
51-
"@zardoy/react-util": "^0.2.0",
51+
"@zardoy/react-util": "^0.2.4",
5252
"@zardoy/utils": "^0.0.11",
5353
"adm-zip": "^0.5.12",
5454
"browserfs": "github:zardoy/browserfs#build",
@@ -71,7 +71,7 @@
7171
"lodash-es": "^4.17.21",
7272
"minecraft-assets": "^1.12.2",
7373
"minecraft-data": "3.65.0",
74-
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol",
74+
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
7575
"mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader",
7676
"mojangson": "^2.0.4",
7777
"net-browserify": "github:zardoy/prismarinejs-net-browserify",
@@ -160,7 +160,7 @@
160160
"prismarine-world": "github:zardoy/prismarine-world#next-era",
161161
"minecraft-data": "3.65.0",
162162
"prismarine-provider-anvil": "github:zardoy/prismarine-provider-anvil#everything",
163-
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol",
163+
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
164164
"react": "^18.2.0",
165165
"prismarine-chunk": "github:zardoy/prismarine-chunk"
166166
},

patches/[email protected]

+66-8
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ index c437ecf3a0e4ab5758a48538c714b7e9651bb5da..d9c9895ae8614550aa09ad60a396ac32
1212
debug('ping response', response)
1313
// TODO: could also use ping pre-connect to save description, type, max players, etc.
1414
@@ -40,6 +40,7 @@ module.exports = function (client, options) {
15-
15+
1616
// Reinitialize client object with new version TODO: move out of its constructor?
1717
client.version = minecraftVersion
1818
+ await options.versionSelectedHook?.(client)
1919
client.state = states.HANDSHAKING
20-
20+
2121
// Let other plugins such as Forge/FML (modinfo) respond to the ping response
2222
diff --git a/src/client/encrypt.js b/src/client/encrypt.js
2323
index b9d21bab9faccd5dbf1975fc423fc55c73e906c5..99ffd76527b410e3a393181beb260108f4c63536 100644
@@ -34,7 +34,7 @@ index b9d21bab9faccd5dbf1975fc423fc55c73e906c5..99ffd76527b410e3a393181beb260108
3434
+ // clearTimeout(loginTimeout)
3535
+ // })
3636
}
37-
37+
3838
function onJoinServerResponse (err) {
3939
diff --git a/src/client.js b/src/client.js
4040
index c89375e32babbf3559655b1e95f6441b9a30796f..f24cd5dc8fa9a0a4000b184fb3c79590a3ad8b8a 100644
@@ -74,7 +74,7 @@ index c89375e32babbf3559655b1e95f6441b9a30796f..f24cd5dc8fa9a0a4000b184fb3c79590
7474
}
7575
@@ -166,7 +174,10 @@ class Client extends EventEmitter {
7676
}
77-
77+
7878
const onFatalError = (err) => {
7979
- this.emit('error', err)
8080
+ // todo find out what is trying to write after client disconnect
@@ -83,7 +83,7 @@ index c89375e32babbf3559655b1e95f6441b9a30796f..f24cd5dc8fa9a0a4000b184fb3c79590
8383
+ }
8484
endSocket()
8585
}
86-
86+
8787
@@ -195,6 +206,8 @@ class Client extends EventEmitter {
8888
serializer -> framer -> socket -> splitter -> deserializer */
8989
if (this.serializer) {
@@ -94,7 +94,7 @@ index c89375e32babbf3559655b1e95f6441b9a30796f..f24cd5dc8fa9a0a4000b184fb3c79590
9494
if (this.socket) this.socket.end()
9595
}
9696
@@ -236,8 +249,11 @@ class Client extends EventEmitter {
97-
97+
9898
write (name, params) {
9999
if (!this.serializer.writable) { return }
100100
- debug('writing packet ' + this.state + '.' + name)
@@ -106,7 +106,7 @@ index c89375e32babbf3559655b1e95f6441b9a30796f..f24cd5dc8fa9a0a4000b184fb3c79590
106106
+ this.emit('writePacket', name, params)
107107
this.serializer.write({ name, params })
108108
}
109-
109+
110110
diff --git a/src/index.d.ts b/src/index.d.ts
111111
index 0a5821c32d735e11205a280aa5a503c13533dc14..94a49f661d922478b940d853169b6087e6ec3df5 100644
112112
--- a/src/index.d.ts
@@ -126,5 +126,63 @@ index 0a5821c32d735e11205a280aa5a503c13533dc14..94a49f661d922478b940d853169b6087
126126
+ /** Can be used to prepare mc data on autoVersion (client.version has selected version) */
127127
+ versionSelectedHook?: (client: Client) => Promise<void> | void
128128
}
129-
129+
130130
export class Server extends EventEmitter {
131+
diff --git a/src/client/chat.js b/src/client/chat.js
132+
index 5cad9954db13d7121ed0a03792c2304156cdf436..ffd7c7d6299ef54854e0923f8d5296bf2a58956b 100644
133+
--- a/src/client/chat.js
134+
+++ b/src/client/chat.js
135+
@@ -111,7 +111,7 @@ module.exports = function (client, options) {
136+
for (const player of packet.data) {
137+
if (!player.chatSession) continue
138+
client._players[player.UUID] = {
139+
- publicKey: crypto.createPublicKey({ key: player.chatSession.publicKey.keyBytes, format: 'der', type: 'spki' }),
140+
+ // publicKey: crypto.createPublicKey({ key: player.chatSession.publicKey.keyBytes, format: 'der', type: 'spki' }),
141+
publicKeyDER: player.chatSession.publicKey.keyBytes,
142+
sessionUuid: player.chatSession.uuid
143+
}
144+
@@ -127,7 +127,7 @@ module.exports = function (client, options) {
145+
for (const player of packet.data) {
146+
if (player.crypto) {
147+
client._players[player.UUID] = {
148+
- publicKey: crypto.createPublicKey({ key: player.crypto.publicKey, format: 'der', type: 'spki' }),
149+
+ // publicKey: crypto.createPublicKey({ key: player.crypto.publicKey, format: 'der', type: 'spki' }),
150+
publicKeyDER: player.crypto.publicKey,
151+
signature: player.crypto.signature,
152+
displayName: player.displayName || player.name
153+
@@ -198,7 +198,7 @@ module.exports = function (client, options) {
154+
if (mcData.supportFeature('useChatSessions')) {
155+
const tsDelta = BigInt(Date.now()) - packet.timestamp
156+
const expired = !packet.timestamp || tsDelta > messageExpireTime || tsDelta < 0
157+
- const verified = !packet.unsignedChatContent && updateAndValidateSession(packet.senderUuid, packet.plainMessage, packet.signature, packet.index, packet.previousMessages, packet.salt, packet.timestamp) && !expired
158+
+ const verified = false && !packet.unsignedChatContent && updateAndValidateSession(packet.senderUuid, packet.plainMessage, packet.signature, packet.index, packet.previousMessages, packet.salt, packet.timestamp) && !expired
159+
if (verified) client._signatureCache.push(packet.signature)
160+
client.emit('playerChat', {
161+
plainMessage: packet.plainMessage,
162+
@@ -363,7 +363,7 @@ module.exports = function (client, options) {
163+
}
164+
}
165+
166+
- client._signedChat = (message, options = {}) => {
167+
+ client._signedChat = async (message, options = {}) => {
168+
options.timestamp = options.timestamp || BigInt(Date.now())
169+
options.salt = options.salt || 1n
170+
171+
@@ -404,7 +404,7 @@ module.exports = function (client, options) {
172+
message,
173+
timestamp: options.timestamp,
174+
salt: options.salt,
175+
- signature: (client.profileKeys && client._session) ? client.signMessage(message, options.timestamp, options.salt, undefined, acknowledgements) : undefined,
176+
+ signature: (client.profileKeys && client._session) ? await client.signMessage(message, options.timestamp, options.salt, undefined, acknowledgements) : undefined,
177+
offset: client._lastSeenMessages.pending,
178+
acknowledged
179+
})
180+
@@ -418,7 +418,7 @@ module.exports = function (client, options) {
181+
message,
182+
timestamp: options.timestamp,
183+
salt: options.salt,
184+
- signature: client.profileKeys ? client.signMessage(message, options.timestamp, options.salt, options.preview) : Buffer.alloc(0),
185+
+ signature: client.profileKeys ? await client.signMessage(message, options.timestamp, options.salt, options.preview) : Buffer.alloc(0),
186+
signedPreview: options.didPreview,
187+
previousMessages: client._lastSeenMessages.map((e) => ({
188+
messageSender: e.sender,

0 commit comments

Comments
 (0)