@@ -170,24 +170,59 @@ ipcMain.handle('launch-minecraft', async (event, { uuid, name }) => {
170
170
if ( fs . existsSync ( accountsPath ) ) {
171
171
try {
172
172
const accountData = JSON . parse ( fs . readFileSync ( accountsPath , 'utf8' ) ) ;
173
+ console . log ( 'Loaded account data:' , { uuid : accountData . uuid , name : accountData . name , hasRefreshToken : ! ! accountData . refreshToken } ) ;
173
174
174
175
// Check if this is a Microsoft account with a refresh token
175
176
if ( accountData . refreshToken ) {
176
177
try {
178
+ console . log ( 'Attempting to refresh access token...' ) ;
177
179
// Use refresh token to get fresh access token
178
180
const authManager = new Auth ( "select_account" ) ;
179
181
const xbox = await authManager . refresh ( accountData . refreshToken ) ;
180
182
const minecraftProfile = await xbox . getMinecraft ( ) ;
181
183
accessToken = minecraftProfile . access_token ;
182
- console . log ( 'Got fresh access token using refresh token' ) ;
184
+
185
+ console . log ( 'Successfully refreshed access token' ) ;
186
+ console . log ( 'Token length:' , accessToken ? accessToken . length : 0 ) ;
187
+ console . log ( 'Profile info:' , {
188
+ id : minecraftProfile . profile . id ,
189
+ name : minecraftProfile . profile . name
190
+ } ) ;
191
+
192
+ // Validate that the token is not empty or malformed
193
+ if ( ! accessToken || accessToken . length < 10 ) {
194
+ throw new Error ( 'Received invalid or empty access token' ) ;
195
+ }
196
+
197
+ // Update the refresh token in case it changed
198
+ const updatedAccountData = {
199
+ ...accountData ,
200
+ refreshToken : xbox . save ( )
201
+ } ;
202
+ fs . writeFileSync ( accountsPath , JSON . stringify ( updatedAccountData , null , 2 ) ) ;
203
+ console . log ( 'Updated refresh token in account data' ) ;
204
+
183
205
} catch ( error ) {
184
- console . warn ( 'Failed to refresh access token, launching in offline mode:' , error ) ;
185
- // Continue without token - will work for offline servers
206
+ console . error ( 'Failed to refresh access token:' , error ) ;
207
+ console . warn ( 'Launching in offline mode due to token refresh failure' ) ;
208
+ accessToken = null ;
209
+
210
+ // If refresh fails, the account might need re-authentication
211
+ // You could optionally clear the refresh token here or prompt for re-login
212
+ if ( error . message && error . message . includes ( 'invalid_grant' ) ) {
213
+ console . warn ( 'Refresh token is invalid - user may need to re-authenticate' ) ;
214
+ // Send a message to the renderer to prompt for re-authentication
215
+ mainWindow . webContents . send ( 'auth-expired' ) ;
216
+ }
186
217
}
218
+ } else {
219
+ console . log ( 'No refresh token found - this is a cracked account or offline mode' ) ;
187
220
}
188
221
} catch ( error ) {
189
222
console . warn ( 'Could not load account data:' , error ) ;
190
223
}
224
+ } else {
225
+ console . log ( 'No account data file found' ) ;
191
226
}
192
227
193
228
// Check if BlitzClient directory exists
@@ -251,4 +286,43 @@ ipcMain.handle('launch-minecraft', async (event, { uuid, name }) => {
251
286
ipcMain . handle ( 'open-external-link' , async ( event , url ) => {
252
287
await shell . openExternal ( url ) ;
253
288
return true ;
289
+ } ) ;
290
+
291
+ ipcMain . handle ( 're-authenticate' , async ( ) => {
292
+ try {
293
+ // Clear existing account data
294
+ const accountsPath = path . join ( path . dirname ( INSTALL_DIR ) , 'accounts.json' ) ;
295
+ if ( fs . existsSync ( accountsPath ) ) {
296
+ fs . unlinkSync ( accountsPath ) ;
297
+ }
298
+
299
+ // Create a new Auth manager with select_account prompt
300
+ const authManager = new Auth ( "select_account" ) ;
301
+
302
+ // Launch using 'electron' as the GUI framework
303
+ const xbox = await authManager . launch ( "electron" ) ;
304
+
305
+ // Get the Minecraft profile
306
+ const minecraftProfile = await xbox . getMinecraft ( ) ;
307
+
308
+ // Extract necessary data from the Minecraft profile
309
+ const accountData = {
310
+ uuid : minecraftProfile . profile . id ,
311
+ name : minecraftProfile . profile . name ,
312
+ refreshToken : xbox . save ( )
313
+ } ;
314
+
315
+ // Save account data
316
+ const accountsDirectory = path . dirname ( INSTALL_DIR ) ;
317
+ if ( ! fs . existsSync ( accountsDirectory ) ) {
318
+ fs . mkdirSync ( accountsDirectory , { recursive : true } ) ;
319
+ }
320
+
321
+ fs . writeFileSync ( accountsPath , JSON . stringify ( accountData , null , 2 ) ) ;
322
+
323
+ return accountData ;
324
+ } catch ( error ) {
325
+ console . error ( 'Re-authentication error:' , error ) ;
326
+ throw error ;
327
+ }
254
328
} ) ;
0 commit comments