Authentication

1. Add the Dependency

Add minified-auth to your build.gradle file:

repositories {
    mavenCentral()
}

dependencies {
    implementation 'io.github.dervarex.minified:minified-auth:3.3.0'
}

2. Initialize the Auth Manager

Before using authentication, initialize the AuthManager with a directory where sessions can be stored.

Path authDirectory = Path.of("<auth-directory>");

AuthManager.init(authDirectory);

3. Check for a Saved Session

Before starting a new login, check whether a saved session already exists.

User user = null;

if (AuthManager.hasSessionSaved()) {
    user = AuthManager.loginWithSavedSession();
}

If the saved session is valid, loginWithSavedSession() returns the authenticated user.


4. Start Device Code Login

If no saved session exists, start the Microsoft device code login:

AuthManager.startDeviceCodeLoginAsync();

The login runs asynchronously. You can access its current state using:

LoginState state = AuthManager.getLoginState();

Wait until the user code becomes available:

while (true) {
    LoginState state = AuthManager.getLoginState();

    if (state.userCode != null && state.verificationUri != null) {
        System.out.println(
                "Go to " + state.verificationUri
                + " and enter code " + state.userCode
        );
        break;
    }

    Thread.sleep(500);
}

The user can then open the verification URL and enter the displayed code.


5. Wait for Authentication

After displaying the login instructions, wait until authentication succeeds or fails:

while (true) {
    LoginState state = AuthManager.getLoginState();

    if (state.status == AuthManager.LoginStatus.SUCCESS) {
        break;
    }

    if (state.status == AuthManager.LoginStatus.ERROR) {
        throw new IllegalStateException(state.message);
    }

    Thread.sleep(500);
}

After a successful login, get the authenticated user:

User user = AuthManager.getUser();

System.out.println(
        "Logged in as "
        + user.username()
        + " ("
        + user.uuid()
        + ")"
);

6. Listening for State Changes

Polling getLoginState() in a loop works, but AuthManager also supports pushing state changes directly to a listener - useful if your UI framework already has a callback/observer pattern instead of a poll loop:

LoginStateChangeListener listener = newState -> {
    System.out.println("New login state: " + newState.status);
};

AuthManager.addStateChangeListener(listener);

The listener is invoked with the same LoginState snapshot every time AuthManager updates it - during login(), startDeviceCodeLoginAsync(), and resetLoginState(). Remove it once you no longer need updates (e.g. when the login UI closes), the same way you would unsubscribe from any other event in Minified:

AuthManager.removeStateChangeListener(listener);

Complete Example

Path authDirectory = Path.of("<auth-directory>");

AuthManager.init(authDirectory);

User user = null;

if (AuthManager.hasSessionSaved()) {
    user = AuthManager.loginWithSavedSession();
}

if (user == null) {
    AuthManager.startDeviceCodeLoginAsync();

    boolean loginInstructionsShown = false;

    while (true) {
        LoginState state = AuthManager.getLoginState();

        if (!loginInstructionsShown
                && state.userCode != null
                && state.verificationUri != null) {

            System.out.println(
                    "Go to " + state.verificationUri
                    + " and enter code " + state.userCode
            );

            loginInstructionsShown = true;
        }

        if (state.status == AuthManager.LoginStatus.SUCCESS) {
            user = AuthManager.getUser();
            break;
        }

        if (state.status == AuthManager.LoginStatus.ERROR) {
            throw new IllegalStateException(state.message);
        }

        Thread.sleep(500);
    }
}

System.out.println(
        "Logged in as "
        + user.username()
        + " ("
        + user.uuid()
        + ")"
);

The returned User can now be passed directly to Minified Launch:

Launcher.launchMinecraft(
        user,
        config
);

Encryption Events

Sessions are stored encrypted on disk using a master key. AuthManager.init() accepts an EventBus that these events are dispatched on, see CreateMasterKeyEvent, SaveEncryptedSessionEvent and LoadEncryptedSessionEvent in the Events section for details on exactly when each one fires.