Package net.ftb.workers

Source Code of net.ftb.workers.AuthlibHelper

/*
* This file is part of FTB Launcher.
*
* Copyright © 2012-2014, FTB Launcher Contributors <https://github.com/Slowpoke101/FTBLaunch/>
* FTB Launcher is licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.ftb.workers;

import java.io.File;
import java.net.Proxy;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mojang.authlib.GameProfile;
import net.feed_the_beast.launcher.json.DateAdapter;
import net.feed_the_beast.launcher.json.EnumAdaptorFactory;
import net.feed_the_beast.launcher.json.FileAdapter;
import net.ftb.data.LoginResponse;
import net.ftb.data.UserManager;
import net.ftb.gui.LaunchFrame;
import net.ftb.gui.dialogs.PasswordDialog;
import net.ftb.log.Logger;
import net.ftb.util.ErrorUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.authlib.Agent;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
import com.mojang.authlib.exceptions.InvalidCredentialsException;
import com.mojang.authlib.exceptions.UserMigratedException;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;

public class AuthlibHelper {
    private static String uniqueID;

    protected static LoginResponse authenticateWithAuthlib (String user, String pass, String mojangData, String selectedProfileName) {
        String displayName;
        boolean hasMojangData = false;
        boolean hasPassword = false;
        GameProfile selectedProfile = null;
        YggdrasilUserAuthentication authentication = (YggdrasilUserAuthentication) new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1").createUserAuthentication(Agent.MINECRAFT);
        if (user != null) {
            Logger.logDebug(user.contains("@") ? "Email address given" : "Username given" + " Not 100% sure, mojangdata might contain different username");
            Logger.logInfo("Beginning authlib authentication attempt");
            Logger.logInfo("successfully created YggdrasilAuthenticationService");
            authentication.setUsername(user);
            if (pass != null && !pass.isEmpty()) {
                authentication.setPassword(pass);
                hasPassword = true;
            }
            if (mojangData != null && !mojangData.isEmpty()) {
                Logger.logDebug("mojangData was passed to current method");
                Map<String, Object> m = decode(mojangData);
                if (m != null) {
                    Logger.logDebug("Loading mojangData into authlib");
                    authentication.loadFromStorage(m);
                    hasMojangData = true;
                }
            } else {
                Logger.logDebug("mojangData is null or empty");
            }
            if (authentication.canLogIn()) {
                try {
                    authentication.logIn();
                } catch (UserMigratedException e) {
                    Logger.logError(e.toString());
                    ErrorUtils.tossError("Invalid credentials. You have migrated your account. Use account email instead of username");
                    return null;
                } catch (InvalidCredentialsException e) {
                    Logger.logError("Invalid credentials recieved for user: " + user, e);
                    if (hasMojangData && hasPassword) {
                        uniqueID = authentication.getSelectedProfile().getId().toString();
                        //could be bad or expired keys, etc. will re-run w/o auth data to refresh and error after password was entered
                    } else {
                        if (user.contains("@")) {
                            ErrorUtils.tossError("Invalid username or password. You need use your official and paid minecraft.net account credentials.");
                        } else {
                            ErrorUtils.tossError("Invalid username or password. You need use your official and paid minecraft.net account credentials. \nAlso try email address instead of username");
                        }
                        return null;
                    }
                } catch (AuthenticationUnavailableException e) {
                    Logger.logDebug("Error while authenticating, trying offline mode");
                    if (hasMojangData) {
                        //if the UUID is valid we can proceed to offline mode later
                        uniqueID = authentication.getSelectedProfile().getId().toString();
                        if (uniqueID != null && !uniqueID.isEmpty()) {
                            Logger.logDebug("Setting UUID");
                        }
                        UserManager.setUUID(user, uniqueID);
                    }
                    if (uniqueID != null && !uniqueID.isEmpty()) {
                        UserManager.setUUID(user, uniqueID);
                        Logger.logDebug("Setting UUID and creating and returning new LoginResponse");
                        return new LoginResponse(Integer.toString(authentication.getAgent().getVersion()), "token", user, null, uniqueID, authentication);
                    }
                    ErrorUtils.tossError("Minecraft authentication servers might be down. Check @ help.mojang.com");
                    Logger.logDebug("failed", e);
                    Logger.logDebug("AuthenticationUnavailableException caused by", e.getCause());
                    return null;
                } catch (AuthenticationException e) {
                    Logger.logError("Unknown error from authlib:", e);
                    Logger.logDebug("AuthenticationException caused by", e.getCause());
                } catch (Exception e) {
                    Logger.logError("Unknown error from authlib: ", e);
                    Logger.logDebug("Exception caused by", e.getCause());
                }
            } else {
                Logger.logDebug("authentication.canLogIn() returned false");
            }

            if (isValid(authentication)) {
                Logger.logDebug("Authentication is valid ");
                displayName = authentication.getSelectedProfile().getName();
                if ((authentication.isLoggedIn()) && (authentication.canPlayOnline())) {
                    Logger.logDebug("loggedIn() && CanPlayOnline()");
                    if ((authentication instanceof YggdrasilUserAuthentication)) {
                        UserManager.setStore(user, encode(authentication.saveForStorage()));
                        UserManager.setUUID(user, authentication.getSelectedProfile().getId().toString());//enables use of offline mode later if needed on newer MC Versions
                        Logger.logDebug("Authentication done, returning LoginResponse");
                        return new LoginResponse(Integer.toString(authentication.getAgent().getVersion()), "token", displayName, authentication.getAuthenticatedToken(), authentication
                                .getSelectedProfile().getId().toString(), authentication);
                    }
                }
                Logger.logDebug("this should never happen: isLoggedIn: " + authentication.isLoggedIn() + " canPlayOnline(): " + authentication.canPlayOnline());
            } else if (authentication.getSelectedProfile() == null && (authentication.getAvailableProfiles() != null && authentication.getAvailableProfiles().length != 0)) {
                // user has more than one profile in his mojang acoount
                Logger.logInfo("You seem to have multiple profiles in  your account. Please contact FTB Launcher team if profiles are not working!");
                Logger.logDebug("User has more than one profile: " + toString(authentication));
                for (GameProfile profile : authentication.getAvailableProfiles()) {
                    if (selectedProfileName.equals(profile.getName())) {
                        Logger.logInfo("Selected profile: " + profile.getName());
                        selectedProfile = profile;
                    }
                }
                if (selectedProfile == null) {
                    Logger.logInfo("Profile not found, defaulting to first");
                    selectedProfile = authentication.getAvailableProfiles()[0];
                }
                Logger.logDebug("Authentication done, returning LoginResponse");
                return new LoginResponse(Integer.toString(authentication.getAgent().getVersion()), "token", selectedProfile.getName(), authentication.getAuthenticatedToken(),
                        selectedProfile.getId().toString(), authentication);
            } else if (authentication.getSelectedProfile() == null && (authentication.getAvailableProfiles() != null && authentication.getAvailableProfiles().length == 0)) {
                // user has 0 paid profiles in mojang account
                Logger.logDebug("No paid profiles in mojang account: " + toString(authentication));
                Logger.logError("You need paid minecraft to play FTB Modpacks...");
                ErrorUtils.showClickableMessage("You need paid minecraft to play FTB Modpacks:"
                        + "<ul>"
                        + "<li>Your login credentials are correct but mojang's authentication server does not find paid profile in your account"
                        + "<li>If you believe this is error, please try vanilla launcher and minecraft.net before contacting FTB support"
                        + "</ul>"
                        , "https://help.mojang.com/customer/portal/articles/1218766-can-only-play-minecraft-demo");
                return null;
            } else {
                Logger.logDebug("this should never happen: " + toString(authentication));
            }

        } else {
            Logger.logDebug("this should never happen");
        }

        if (hasMojangData) {
            Logger.logError("Failed to authenticate with mojang data, attempting to use username & password");
            if (!hasPassword) {
                new PasswordDialog(LaunchFrame.getInstance(), true).setVisible(true);
                if (LaunchFrame.tempPass.isEmpty()) {
                    return null;
                }
                pass = LaunchFrame.tempPass;
            }

            LoginResponse l = authenticateWithAuthlib(user, pass, null, selectedProfileName);
            if (l == null) {
                Logger.logError("Failed to login with username & password");
                return null;
            } else {
                Logger.logDebug("authentication ready, returning LoginResponse from authlib");
                return l;
            }
        }
        Logger.logError("Failed to authenticate");
        return null;

    }

    private static boolean isValid (YggdrasilUserAuthentication authentication) {
        boolean ret = true;
        if (!authentication.isLoggedIn()) {
            Logger.logDebug("authentication not valid");
            ret = false;
        }
        if (authentication.getAuthenticatedToken() == null) {
            Logger.logDebug("authentication not valid");
            ret = false;
        }
        if (authentication.getSelectedProfile() == null) {
            Logger.logDebug("authentication not valid");
            ret = false;
        }
        return ret;
    }

    @SuppressWarnings("unchecked")
    private static Map<String, Object> decode (String s) {
        try {
            Map<String, Object> ret;
            JsonObject jso = new JsonParser().parse(s).getAsJsonObject();
            ret = (Map<String, Object>) decodeElement(jso);
            return ret;
        } catch (Exception e) {
            Logger.logError("Error decoding Authlib JSON", e);
            return null;
        }
    }

    private static Object decodeElement (JsonElement e) {
        if (e instanceof JsonObject) {
            Map<String, Object> ret = Maps.newLinkedHashMap();
            for (Map.Entry<String, JsonElement> jse : ((JsonObject) e).entrySet()) {
                ret.put(jse.getKey(), decodeElement(jse.getValue()));
            }
            return ret;
        }
        if (e instanceof JsonArray) {
            List<Object> ret = Lists.newArrayList();
            for (JsonElement jse : e.getAsJsonArray()) {
                ret.add(decodeElement(jse));
            }
            return ret;

        }
        return e.getAsString();
    }

    private static String encode (Map<String, Object> m) {
        try {
            Gson gson;
            final GsonBuilder builder = new GsonBuilder();
            builder.registerTypeAdapterFactory(new EnumAdaptorFactory());
            builder.registerTypeAdapter(Date.class, new DateAdapter());
            builder.registerTypeAdapter(File.class, new FileAdapter());
            builder.enableComplexMapKeySerialization();
            builder.setPrettyPrinting();
            gson = builder.create();
            return gson.toJson(m);
        } catch (Exception e) {
            Logger.logError("Error encoding Authlib JSON", e);
            return null;
        }

    }

    public static String toString (YggdrasilUserAuthentication y) {
        return "YggdrasilAuthenticationService{profiles=" + Arrays.toString(y.getAvailableProfiles()) + ", selectedProfile=" + y.getSelectedProfile() + ", isLoggedIn=" + y.isLoggedIn() + ", userType="
                + y.getUserType() + ", canPlayOnline=" + y.canPlayOnline() + "}";
    }

}
TOP

Related Classes of net.ftb.workers.AuthlibHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.