Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -103,35 +103,30 @@ public UUID getProfileID() {

@Override
public synchronized AuthInfo logIn() throws AuthenticationException {
if (!authenticated || !session.hasProfileName()) {
if (session.hasProfileName() && service.validate(session.getAccessToken(), session.getClientToken())) {
authenticated = true;
} else {
YggdrasilSession acquiredSession;
try {
acquiredSession = service.refresh(session.getAccessToken(), session.getClientToken(), null);
} catch (RemoteAuthenticationException e) {
if ("ForbiddenOperationException".equals(e.getRemoteName())) {
throw new CredentialExpiredException(e);
} else {
throw e;
}
}
if (acquiredSession.getSelectedProfile() == null ||
!acquiredSession.getSelectedProfile().getId().equals(profileID)) {
throw new ServerResponseMalformedException("Selected profile changed");
}
if (!acquiredSession.hasProfileName()) {
throw new ServerResponseMalformedException("Profile name is missing");
if (!authenticated || !session.hasProfileName() || !service.validate(session.getAccessToken(), session.getClientToken())) {
YggdrasilSession acquiredSession;
try {
acquiredSession = service.refresh(session.getAccessToken(), session.getClientToken(), null);
} catch (RemoteAuthenticationException e) {
if ("ForbiddenOperationException".equals(e.getRemoteName())) {
throw new CredentialExpiredException(e);
} else {
throw e;
}
}
if (acquiredSession.getSelectedProfile() == null ||
!acquiredSession.getSelectedProfile().getId().equals(profileID)) {
throw new ServerResponseMalformedException("Selected profile changed");
}
if (!acquiredSession.hasProfileName()) {
throw new ServerResponseMalformedException("Profile name is missing");
}

session = acquiredSession;
session = acquiredSession;

authenticated = true;
invalidate();
}
authenticated = true;
invalidate();
}
Comment on lines +106 to 129

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This change introduces several critical issues:

  1. Bypassing validation on startup: Because of short-circuit evaluation (!authenticated || ...), when authenticated is false (the default state when the launcher starts), the condition evaluates to true immediately without calling service.validate(...). This forces a redundant service.refresh(...) on every startup, rotating the token and writing to disk unnecessarily even if the existing token is perfectly valid.
  2. Redundant network requests: When authenticated is true, every call to logIn() (e.g., when launching a game) will perform a blocking network request to validate the token, introducing significant latency.
  3. Breaking offline launching: If the user is offline or the auth server is down, service.validate(...) will throw a ServerDisconnectException. Since this exception is not caught, it propagates out of logIn(), completely breaking offline play for authenticated accounts.

We should restore the startup validation logic, skip validation once authenticated, and gracefully handle network errors during validation to support offline play.

        if (!authenticated || !session.hasProfileName()) {
            if (session.hasProfileName()) {
                try {
                    if (service.validate(session.getAccessToken(), session.getClientToken())) {
                        authenticated = true;
                    }
                } catch (AuthenticationException e) {
                    if (e instanceof ServerDisconnectException) {
                        authenticated = true;
                    }
                }
            }

            if (!authenticated) {
                YggdrasilSession acquiredSession;
                try {
                    acquiredSession = service.refresh(session.getAccessToken(), session.getClientToken(), null);
                } catch (RemoteAuthenticationException e) {
                    if ("ForbiddenOperationException".equals(e.getRemoteName())) {
                        throw new CredentialExpiredException(e);
                    } else {
                        throw e;
                    }
                }
                if (acquiredSession.getSelectedProfile() == null ||
                        !acquiredSession.getSelectedProfile().getId().equals(profileID)) {
                    throw new ServerResponseMalformedException("Selected profile changed");
                }
                if (!acquiredSession.hasProfileName()) {
                    throw new ServerResponseMalformedException("Profile name is missing");
                }

                session = acquiredSession;

                authenticated = true;
                invalidate();
            }
        }


return session.toAuthInfo();
}

Expand Down