2022-09-18 18:56:44 +02:00
package io.gitlab.jfronny.inceptum.launcher.api.account ;
2023-05-05 18:49:56 +02:00
import io.gitlab.jfronny.commons.jlhttp.JLHTTPServer ;
import io.gitlab.jfronny.commons.jlhttp.util.VirtualHost ;
2022-09-18 18:56:44 +02:00
import io.gitlab.jfronny.inceptum.common.Utils ;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv ;
2023-05-04 11:31:54 +02:00
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.Entitlements ;
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.Profile ;
2022-11-18 21:58:40 +01:00
import io.gitlab.jfronny.inceptum.launcher.model.microsoft.response.* ;
2022-09-18 18:56:44 +02:00
import org.jetbrains.annotations.Nullable ;
import java.io.Closeable ;
import java.io.IOException ;
import java.net.URLDecoder ;
import java.nio.charset.StandardCharsets ;
import java.util.Objects ;
public class MicrosoftAuthServer implements Closeable {
2023-05-05 18:49:56 +02:00
private static final JLHTTPServer server = new JLHTTPServer ( MicrosoftAuthAPI . MICROSOFT_LOGIN_REDIRECT_PORT ) ;
private static final VirtualHost host = server . getVirtualHost ( null ) ;
2022-09-18 18:56:44 +02:00
private final MicrosoftAccount previous ;
public MicrosoftAuthServer ( @Nullable MicrosoftAccount previous ) {
this . previous = previous ;
}
public void start ( ) throws IOException {
host . addContext ( " / " , ( req , res ) - > {
2023-05-05 18:49:56 +02:00
if ( req . getParams ( ) . containsKey ( " error " ) ) {
res . getHeaders ( ) . add ( " Content-Type " , " text/plain " ) ;
2022-09-18 18:56:44 +02:00
res . send ( 500 , " Error logging in. Check console for more information " ) ;
Utils . LOGGER . error ( " Error logging into Microsoft account: " + URLDecoder
2023-05-05 18:49:56 +02:00
. decode ( req . getParams ( ) . get ( " error_description " ) , StandardCharsets . UTF_8 ) ) ;
2022-09-18 18:56:44 +02:00
close ( ) ;
return 0 ;
}
2023-05-05 18:49:56 +02:00
if ( ! req . getParams ( ) . containsKey ( " code " ) ) {
res . getHeaders ( ) . add ( " Content-Type " , " text/plain " ) ;
2022-09-18 18:56:44 +02:00
res . send ( 400 , " Code is missing " ) ;
close ( ) ;
return 0 ;
}
try {
2023-05-05 18:49:56 +02:00
acquireAccessToken ( req . getParams ( ) . get ( " code " ) ) ;
2022-09-18 18:56:44 +02:00
} catch ( Exception e ) {
Utils . LOGGER . error ( " Error acquiring accessToken " , e ) ;
2023-05-05 18:49:56 +02:00
res . getHeaders ( ) . add ( " Content-Type " , " text/html " ) ;
2022-09-18 18:56:44 +02:00
res . send ( 500 , " Error logging in. Check console for more information " ) ;
close ( ) ;
return 0 ;
}
2023-05-05 18:49:56 +02:00
res . getHeaders ( ) . add ( " Content-Type " , " text/plain " ) ;
2022-09-18 18:56:44 +02:00
// #. {0} is the name of the launcher
res . send ( 200 , " Login complete. You can now close this window and go back to the Launcher " ) ;
close ( ) ;
return 0 ;
} , " GET " ) ;
server . start ( ) ;
}
private void addAccount ( OauthTokenResponse oauthTokenResponse , XboxLiveAuthResponse xstsAuthResponse , LoginResponse loginResponse , Profile profile ) {
2023-05-05 18:49:56 +02:00
if ( this . previous ! = null | | AccountManager . isAccountByName ( loginResponse . username ( ) ) ) {
MicrosoftAccount account = ( MicrosoftAccount ) AccountManager . getAccountByName ( loginResponse . username ( ) ) ;
2022-09-18 18:56:44 +02:00
if ( account = = null ) {
return ;
}
// if forced to relogin, then make sure they logged into correct account
if ( this . previous ! = null & & ! Objects . equals ( account . accountId , this . previous . accountId ) ) {
LauncherEnv . showError ( " Logged into incorrect account. Please login again on the Accounts tab " , " Incorrect account " ) ;
return ;
}
account . update ( oauthTokenResponse , xstsAuthResponse , loginResponse , profile ) ;
AccountManager . saveAccounts ( ) ;
} else {
MicrosoftAccount account = new MicrosoftAccount ( oauthTokenResponse , xstsAuthResponse , loginResponse , profile ) ;
AccountManager . addAccount ( account ) ;
}
}
private void acquireAccessToken ( String authcode ) throws Exception {
OauthTokenResponse oauthTokenResponse = MicrosoftAuthAPI . tradeCodeForAccessToken ( authcode ) ;
acquireXBLToken ( oauthTokenResponse ) ;
}
private void acquireXBLToken ( OauthTokenResponse oauthTokenResponse ) throws Exception {
2023-05-05 18:49:56 +02:00
XboxLiveAuthResponse xblAuthResponse = MicrosoftAuthAPI . getXBLToken ( oauthTokenResponse . accessToken ( ) ) ;
2022-09-18 18:56:44 +02:00
2022-11-02 00:38:04 +01:00
acquireXsts ( oauthTokenResponse , xblAuthResponse . token ( ) ) ;
2022-09-18 18:56:44 +02:00
}
private void acquireXsts ( OauthTokenResponse oauthTokenResponse , String xblToken ) throws Exception {
XboxLiveAuthResponse xstsAuthResponse = MicrosoftAuthAPI . getXstsToken ( xblToken ) ;
if ( xstsAuthResponse ! = null ) {
acquireMinecraftToken ( oauthTokenResponse , xstsAuthResponse ) ;
}
}
private void acquireMinecraftToken ( OauthTokenResponse oauthTokenResponse , XboxLiveAuthResponse xstsAuthResponse ) throws Exception {
2023-05-05 18:49:56 +02:00
LoginResponse loginResponse = MicrosoftAuthAPI . loginToMinecraft ( " XBL3.0 x= " + xstsAuthResponse . displayClaims ( ) . xui ( ) . get ( 0 ) . uhs ( ) + " ; " + xstsAuthResponse . token ( ) ) ;
2022-09-18 18:56:44 +02:00
if ( loginResponse = = null ) {
throw new Exception ( " Failed to login to Minecraft " ) ;
}
2023-05-05 18:49:56 +02:00
Entitlements entitlements = MicrosoftAuthAPI . getEntitlements ( loginResponse . accessToken ( ) ) ;
2022-09-18 18:56:44 +02:00
2023-05-05 18:49:56 +02:00
if ( ! ( entitlements . items ( ) . stream ( ) . anyMatch ( i - > i . name ( ) . equalsIgnoreCase ( " product_minecraft " ) )
& & entitlements . items ( ) . stream ( ) . anyMatch ( i - > i . name ( ) . equalsIgnoreCase ( " game_minecraft " ) ) ) ) {
2022-09-18 18:56:44 +02:00
LauncherEnv . showError ( " This account doesn't have a valid purchase of Minecraft. \ nPlease make sure you've bought the Java edition of Minecraft and then try again. " , " Doesn't own Minecraft " ) ;
throw new Exception ( " Account does not own Minecraft " ) ;
}
Profile profile = null ;
try {
2023-05-05 18:49:56 +02:00
profile = MicrosoftAuthAPI . getMcProfile ( loginResponse . accessToken ( ) ) ;
2022-09-18 18:56:44 +02:00
} catch ( Exception e ) {
LauncherEnv . showError ( """
No Minecraft profiles were found for this account . Have you purchased Minecraft ?
Please make sure you ' ve bought the Java edition of Minecraft and then try again .
If you ' re an Xbox Game Pass subscriber , make sure to login and play through the Minecraft
Launcher once in order to create your Minecraft profile , then try logging in again . " " " ,
" Minecraft Profile Not Found " ) ;
throw new Exception ( " Minecraft Profile not found " , e ) ;
}
if ( profile = = null ) {
throw new Exception ( " Failed to get Minecraft profile " ) ;
}
// add the account
addAccount ( oauthTokenResponse , xstsAuthResponse , loginResponse , profile ) ;
}
@Override
public void close ( ) {
server . stop ( ) ;
}
}