Simple and easy to use Minecraft microsoft authentication library (Java and Bedrock).
This is CCBlueX's fork of RaphiMC/MinecraftAuth, published to
CCBlueX's Maven under net.ccbluex. The Java packages are unchanged (net.raphimc.minecraftauth).
- Full support for Minecraft: Java Edition and Minecraft: Bedrock Edition
- Login using device code, credentials, a JavaFX WebView window, a browser you provide, or a local webserver
- Token lifecycle management (Automatic refreshing of tokens)
- Serializing and deserializing tokens to and from json
- Customizable login flows (Client ID, scopes, ...)
- Basic implementation of the Minecraft Realms API (Allows listing and joining realms)
MinecraftAuth is published to CCBlueX's Maven as net.ccbluex:MinecraftAuth.
Every push to main publishes a snapshot to the snapshots repository; publishing a GitHub Release
publishes that version to the releases repository.
repositories {
maven("https://maven.ccbluex.net/snapshots")
}
dependencies {
implementation("net.ccbluex:MinecraftAuth:5.0.3-SNAPSHOT")
}repositories {
maven {
url "https://maven.ccbluex.net/snapshots"
}
}
dependencies {
implementation 'net.ccbluex:MinecraftAuth:5.0.3-SNAPSHOT'
}<repositories>
<repository>
<id>ccbluex-snapshots</id>
<url>https://maven.ccbluex.net/snapshots</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>net.ccbluex</groupId>
<artifactId>MinecraftAuth</artifactId>
<version>5.0.3-SNAPSHOT</version>
</dependency>
</dependencies>For a tagged release, swap https://maven.ccbluex.net/snapshots for https://maven.ccbluex.net/releases
and drop the -SNAPSHOT suffix from the version.
If you just want the latest jar file you can download it from GitHub Actions.
MinecraftAuth provides its core functionality through the JavaAuthManager and BedrockAuthManager classes.
These classes provide predefined and customizable login flows for their respective Minecraft editions.
To get started create an HttpClient which will be used for all network requests:
// Create an HttpClient with a custom user agent (recommended)HttpClienthttpClient = MinecraftAuth.createHttpClient(userAgent);
// Or you can create an HttpClient without a custom user agent (not recommended)HttpClienthttpClient = MinecraftAuth.createHttpClient();The next step is to configure the authentication manager (Example is for Minecraft: Java Edition, but Minecraft: Bedrock Edition is pretty much the same):
// Use predefined application configuration (Uses the official Minecraft application details)JavaAuthManager.BuilderauthManagerBuilder = JavaAuthManager.create(httpClient);
// If you want to customize the application details (like client id, scope or client secret) you can do it like this:JavaAuthManager.BuilderauthManagerBuilder = JavaAuthManager.create(httpClient).msaApplicationConfig(newMsaApplicationConfig(...));The next step is to choose one of the login flows and initiate the login process.
The device code auth flow blocks the thread until the user has logged in and throws an exception if the process times out. The default timeout is 5 minutes.
JavaAuthManagerauthManager = authManagerBuilder.login(DeviceCodeMsaAuthService::new, newConsumer<MsaDeviceCode>() {
@Overridepublicvoidaccept(MsaDeviceCodedeviceCode) {
// Method to generate a verification URL and a code for the user to enter on that pageSystem.out.println("Go to " + deviceCode.getVerificationUri());
System.out.println("Enter code " + deviceCode.getUserCode());
// There is also a method to generate a direct URL without needing the user to enter a codeSystem.out.println("Go to " + deviceCode.getDirectVerificationUri());
}
});
System.out.println("Username: " + authManager.getMinecraftProfile().getUpToDate().getName());
System.out.println("Access token: " + authManager.getMinecraftToken().getUpToDate().getToken());The credentials auth flow does not handle 2FA and will throw an exception if the user has 2FA enabled. You should consider using the device code auth flow instead if you want to support 2FA.
JavaAuthManagerauthManager = authManagerBuilder.login(CredentialsMsaAuthService::new, newMsaCredentials("email@test.com", "P4ssw0rd"));
System.out.println("Username: " + authManager.getMinecraftProfile().getUpToDate().getName());
System.out.println("Access token: " + authManager.getMinecraftToken().getUpToDate().getToken());The JavaFX WebView auth flow opens a JavaFX window with a WebView for the user to log in. This method requires you to have JavaFX set up in your project.
JavaAuthManagerauthManager = authManagerBuilder.login(JfxWebViewMsaAuthService::new);If you already embed a browser engine, or the environment has no JavaFX, the auth code flow can run in a
browser this library does not own. Open getAuthenticationUrl(), report every URL the browser navigates
to, and close it once handleNavigation returns true.
JavaAuthManagerauthManager = authManagerBuilder.login((httpClient, applicationConfig) -> newExternalBrowserMsaAuthService(httpClient, applicationConfig, service -> {
// Called on the thread that is logging in. Open the browser and wire up its navigation events:myBrowser.open(service.getAuthenticationUrl(), url -> {
if (service.handleNavigation(url)) {
myBrowser.close();
}
});
// If the user closes the browser before finishing, call service.cancel()
}, service -> myBrowser.close()));If you want to implement your own MSA auth service (for example to implement a different login flow) or customize one of the existing ones you can do it like this:
// Create a customized MSA auth service (Example: Change login timeout to 60 seconds)DeviceCodeMsaAuthServiceauthService = newDeviceCodeMsaAuthService(MinecraftAuth.createHttpClient(), newMsaApplicationConfig(MsaConstants.JAVA_TITLE_ID, MsaConstants.SCOPE_TITLE_AUTH), newConsumer<MsaDeviceCode>() {
@Overridepublicvoidaccept(MsaDeviceCodedeviceCode) {
System.out.println("Go to " + deviceCode.getDirectVerificationUri());
}
}, 60_000);
// Acquire the MSA tokenMsaTokenmsaToken = authService.acquireToken();
// Pass it to the auth managerJavaAuthManagerauthManager = JavaAuthManager.create(MinecraftAuth.createHttpClient()).login(msaToken);After logging the user in you can serialize the tokens to a json object to save them for later use:
JsonObjectserializedAuthManager = JavaAuthManager.toJson(authManager);It is important to note, that MinecraftAuth does not request all tokens at once during the login process. Only the initial tokens are requested and the rest of the tokens are requested lazily when you access them. For this reason, it is recommended to attach a change listener to the auth manager after logging in to make sure new tokens are automatically saved:
authManager.getChangeListeners().add(() -> {
// save the auth manager state here
});Alternatively you can also request the tokens you need directly after logging and then save them:
JavaAuthManagerauthManager = authManagerBuilder.login(...);
authManager.getMinecraftToken().refresh(); // If you need the Minecraft tokenauthManager.getMinecraftProfile().refresh(); // If you need the Minecraft profile// Now save the auth manager state here or use the tokens in their cached stateLoading the tokens back from a json object is just as easy:
JavaAuthManagerauthManager = JavaAuthManager.fromJson(httpClient, serializedAuthManager);And of course don't forget to attach the change listener again after loading:
authManager.getChangeListeners().add(() -> {
// save the auth manager state here
});Alternatively you can also refresh the tokens you need directly after loading and then save them:
JavaAuthManagerauthManager = JavaAuthManager.fromJson(...);
authManager.getMinecraftToken().refreshIfExpired(); // If you need the Minecraft tokenauthManager.getMinecraftProfile().refreshIfExpired(); // If you need the Minecraft profile// Now save the auth manager state here and use the tokens in their cached stateAll token related methods in the auth managers return a Holder object which provides different methods to access the token.
Tokens are requested lazily, so they are only requested/refreshed when you access them.
The most important method is getUpToDate() which will automatically refresh the token if it is expired or not set yet.
This method will throw an exception if the refresh fails (The initial refresh token is no longer valid and the user has to login again).
The getCached() method can be used to get the current cached token without refreshing it.
This is useful if you know, that the token is still valid (Because you maybe refreshed it somewhere else in your code recently).
There are several other methods available in the Holder class, which you can learn more about in the javadoc.
Here is a full example which demonstrates logging in using the device code flow and saving the tokens to a json file:
FiletokenFile = newFile("tokens.json");
// Log in using device code flowJavaAuthManagerauthManager = JavaAuthManager.create(MinecraftAuth.createHttpClient()).login(DeviceCodeMsaAuthService::new, newConsumer<MsaDeviceCode>() {
@Overridepublicvoidaccept(MsaDeviceCodedeviceCode) {
System.out.println("Go to " + deviceCode.getDirectVerificationUri());
}
});
// Save tokens to file after loginFiles.write(tokenFile.toPath(), JavaAuthManager.toJson(authManager).toString().getBytes(StandardCharsets.UTF_8));
// Attach a listener to save tokens on changeauthManager.getChangeListeners().add(() -> {
try {
Files.write(tokenFile.toPath(), JavaAuthManager.toJson(authManager).toString().getBytes(StandardCharsets.UTF_8));
} catch (IOExceptione) {
thrownewRuntimeException(e);
}
});
// Request the Minecraft token (This is going to trigger the change listener, so its not necessary to save after this)System.out.println("Access token: " + authManager.getMinecraftToken().getUpToDate().getToken());
// The file "tokens.json" now contains all the necessary tokens to restore and use the auth manager laterMinecraftAuth also provides some extra functionality like a basic Minecraft Realms API implementation.
MinecraftAuth provides a basic implementation of the Minecraft Realms API. It supports listing and joining the realms of an user.
The Realms API requires you to provide the latest supported client version of your application.
You should hardcode this value instead of loading it from the Internet, as the Realms API will not work if your application can't handle the specified version.
JavaRealmsServicejavaRealmsService = newJavaRealmsService(httpClient, "latestSupportedClientVersionHere", authManager.getMinecraftToken(), authManager.getMinecraftProfile());
booleanisCompatible = javaRealmsService.isCompatible();
if (!isCompatible) {
System.out.println("The client version does not support Realms");
} else {
System.out.println("Your client supports Realms");
List<RealmsServer> realmsWorlds = javaRealmsService.getWorlds();
System.out.println("Realms worlds: " + realmsWorlds);
try {
System.out.println("Connect to: " + javaRealmsService.joinWorld(realmsWorlds.get(0)));
} catch (RealmsRequestExceptione) {
if (e.getErrorCode() == RealmsRequestException.ERROR_TOS_NOT_ACCEPTED) {
// The Java Edition Realms API requires users to accept the Minecraft Realms Terms of Service (https://aka.ms/MinecraftRealmsTerms)// You should display the terms to the user and ask them to accept them:javaRealmsService.acceptTos();
// If they accept, then you can try to join the world again
}
}
}BedrockRealmsServicebedrockRealmsService = newBedrockRealmsService(httpClient, "latestSupportedClientVersionHere", authManager.getRealmsXstsToken());
booleanisCompatible = bedrockRealmsService.isCompatible();
if (!isCompatible) {
System.out.println("The client version does not support Realms");
} else {
System.out.println("Your client supports Realms");
List<RealmsServer> realmsWorlds = bedrockRealmsService.getWorlds();
System.out.println("Realms worlds: " + realmsWorlds);
System.out.println("Connect to: " + bedrockRealmsService.joinWorld(realmsWorlds.get(0)));
}Here is an example implementation which is using the Realms API of both Minecraft editions.
If you are migrating from MinecraftAuth 4.x.x to 5.x.x you can use the MinecraftAuth4To5Migrator class to migrate the saved tokens of your users.
This class provides methods to migrate the Minecraft: Java Edition and Minecraft: Bedrock Edition token chains to the new auth manager structure.
If you encounter any issues, please report them on the
issue tracker.
If you just want to talk or need help implementing MinecraftAuth feel free to join my
Discord.
type(scope): subject, lowercase, no trailing period.
featfixrefactorchoredocs
Do not add Co-Authored-By trailers.