Skip to content
Open
Show file tree
Hide file tree
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
18 changes: 12 additions & 6 deletions common/src/main/java/me/djtheredstoner/devauth/common/DevAuth.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public class DevAuth {

private static final Set<String> authOptions =
new HashSet<>(Arrays.asList("--accessToken", "--uuid", "--username", "--userType", "--userProperties"));
new HashSet<>(Arrays.asList("--accessToken", "--uuid", "--username", "--userType", "--userProperties"));

private final Properties.BooleanState enabled;
private final Logger logger;
Expand Down Expand Up @@ -40,7 +40,8 @@ public String[] processArguments(String[] args) {
String arg = args[i];
if (authOptions.contains(arg)) {
i++;
} else {
}
else {
newArgs.add(arg);
}
}
Expand All @@ -59,8 +60,11 @@ public SessionData login() {

IAuthProvider authProvider = account.getType().getAuthProviderFactory().create(this);

SessionData session = authProvider.login(account);

SessionData session = authProvider.login(account, false);
while (account.getForceUsername() != null && !account.getForceUsername().equals(session.getUsername())) {
logger.error("Login Blocked: You logined with the wrong Account. You want to login as " + account.getForceUsername() + " but logined as " + session.getUsername() + "!");
session = authProvider.login(account, true);
}
logger.info("Successfully logged in as " + session.getUsername());
return session;
}
Expand All @@ -74,7 +78,8 @@ public Account getSelectedAccount() {
return config.getAccounts().get(commandLineAccount);
}
throw new RuntimeException("Account '" + commandLineAccount + "' not found, valid accounts are: " + getValidAccounts());
} else if (defaultAccount != null) {
}
else if (defaultAccount != null) {
if (config.getAccounts().containsKey(defaultAccount)) {
return config.getAccounts().get(defaultAccount);
}
Expand All @@ -86,7 +91,8 @@ public Account getSelectedAccount() {
public boolean isEnabled(boolean defaultEnabled) {
if (enabled == Properties.BooleanState.NOT_SET) {
return defaultEnabled;
} else {
}
else {
return enabled.toBoolean();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

public interface IAuthProvider {

SessionData login(Account account);
SessionData login(Account account, Boolean reLogin);

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
public class MojangAuthProvider implements IAuthProvider {

@Override
public SessionData login(Account account) {
public SessionData login(Account account, Boolean relogin) {
UserAuthentication auth = new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1")
.createUserAuthentication(Agent.MINECRAFT);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Supplier;

/**
* (the third rewrite of) <br/>
Expand All @@ -58,7 +57,7 @@ public class MicrosoftAuthProvider implements IAuthProvider {
private final DevAuth devAuth;
private final OAuthProvider oAuthProvider = new CodeOAuthProvider(logger, SCOPES);

private final Map<TokenKey<?>, Supplier<? extends Token>> tokenRegistry = new LinkedHashMap<>();
private final Map<TokenKey<?>, TokenSupplier<? extends Token>> tokenRegistry = new LinkedHashMap<>();
private final Map<TokenKey<?>, Token> tokenStore = new LinkedHashMap<>();

private JsonObject accountsData;
Expand All @@ -75,14 +74,15 @@ protected void initTokenRegistry() {
register(TokenKey.SESSION_TOKEN, this::getMcSession);
}

protected <T extends Token> void register(TokenKey<T> tokenKey, Supplier<T> supplier) {
protected <T extends Token> void register(TokenKey<T> tokenKey, TokenSupplier<T> supplier) {
tokenRegistry.put(tokenKey, supplier);
}

@SuppressWarnings("unchecked")
protected <T extends Token> T get(TokenKey<T> tokenKey) {
Supplier<T> supplier = (Supplier<T>) tokenRegistry.get(tokenKey);
protected <T extends Token> T get(TokenKey<T> tokenKey, Boolean relogin) {
TokenSupplier<T> supplier = (TokenSupplier<T>) tokenRegistry.get(tokenKey);
T token = (T) tokenStore.get(tokenKey);
if (relogin) token = null;
if (token == null || token.isExpired()) {
logger.info("Fetching token " + tokenKey.getName());
if (token instanceof OAuthToken) {
Expand All @@ -92,10 +92,11 @@ protected <T extends Token> T get(TokenKey<T> tokenKey) {
token = (T) oAuthProvider.refreshToken(oAuthToken);
} catch (Exception e) {
logger.error("Failed to refresh OAuth token", e);
token = supplier.get();
token = supplier.get(relogin);
}
} else {
token = supplier.get();
}
else {
token = supplier.get(relogin);
}

OffsetDateTime expiry = OffsetDateTime.ofInstant(Instant.ofEpochSecond(token.getExpiry()), ZoneOffset.UTC);
Expand All @@ -109,12 +110,12 @@ protected <T extends Token> T get(TokenKey<T> tokenKey) {
return token;
}

protected OAuthToken getOAuthToken() {
protected OAuthToken getOAuthToken(Boolean relogin) {
return oAuthProvider.getOAuthToken();
}

protected XBLToken getXBLToken() {
OAuthToken oAuthToken = get(TokenKey.OAUTH_TOKEN);
protected XBLToken getXBLToken(Boolean relogin) {
OAuthToken oAuthToken = get(TokenKey.OAUTH_TOKEN, relogin);

JsonObject object = new JsonObject();

Expand All @@ -133,8 +134,8 @@ protected XBLToken getXBLToken() {
return XBLToken.fromJson(res, true);
}

protected XBLToken getXSTSToken() {
XBLToken xblToken = get(TokenKey.XBL_TOKEN);
protected XBLToken getXSTSToken(Boolean relogin) {
XBLToken xblToken = get(TokenKey.XBL_TOKEN, relogin);

JsonObject object = new JsonObject();

Expand All @@ -153,8 +154,8 @@ protected XBLToken getXSTSToken() {
return XBLToken.fromJson(res, true);
}

protected Token getMcSession() {
XBLToken xstsToken = get(TokenKey.XSTS_TOKEN);
protected Token getMcSession(Boolean relogin) {
XBLToken xstsToken = get(TokenKey.XSTS_TOKEN, relogin);

JsonObject object = new JsonObject();
object.addProperty("identityToken", "XBL3.0 x=" + xstsToken.getUserHash() + ";" + xstsToken.getToken());
Expand All @@ -165,10 +166,10 @@ protected Token getMcSession() {
}

@Override
public SessionData login(Account account) {
public SessionData login(Account account, Boolean reLogin) {
readAccountsJson(account);
try {
SessionData data = getMinecraftProfile();
SessionData data = getMinecraftProfile(reLogin);
writeAccountsJson(account, true);
return data;
} catch (Exception e) {
Expand All @@ -177,8 +178,8 @@ public SessionData login(Account account) {
}
}

protected SessionData getMinecraftProfile() {
Token mcSession = get(TokenKey.SESSION_TOKEN);
protected SessionData getMinecraftProfile(Boolean relogin) {
Token mcSession = get(TokenKey.SESSION_TOKEN, relogin);

try {
HttpGet request = new HttpGet(MINECRAFT_PROFILE_URL);
Expand All @@ -195,11 +196,11 @@ protected SessionData getMinecraftProfile() {
JsonObject profileObject = Util.parser.parse(body).getAsJsonObject();

return new SessionData(
mcSession.getToken(),
profileObject.get("id").getAsString(),
profileObject.get("name").getAsString(),
"msa",
"{}"
mcSession.getToken(),
profileObject.get("id").getAsString(),
profileObject.get("name").getAsString(),
"msa",
"{}"
);
} catch (Exception e) {
throw new RuntimeException("Failed to fetch minecraft profile", e);
Expand Down Expand Up @@ -255,4 +256,8 @@ private void writeAccountsJson(Account account, boolean writeCurrentAccount) {
logger.error("Failed to write microsoft_accounts.json", e);
}
}
@FunctionalInterface
public interface TokenSupplier<T>{
T get(Boolean reLogin);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ public class Account {
private final AccountType type;
private final String username;
private final String password;
private final String forceUsername;

public Account(String name, AccountType type, String username, String password) {
public Account(String name, AccountType type, String username, String password, String forceUsername) {
this.name = name;
this.type = type;
this.username = username;
this.password = password;
this.forceUsername = forceUsername;
}

public String getName() {
Expand All @@ -29,4 +31,8 @@ public String getUsername() {
public String getPassword() {
return password;
}

public String getForceUsername() {
return forceUsername;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public static DevAuthConfig load(boolean createDefaultConfig) {
entry.getKey(),
AccountType.of(value.get("type")),
value.get("username"),
value.get("password")
value.get("password"),
value.get("forcedusername")
));
}

Expand Down
2 changes: 2 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,10 @@ defaultAccount = "main"
type = "microsoft"

# A second account, which can be selected by changing defaultAccount above or using the devauth.account property
# forcedusername makes it so you can only login with the username specified. This is so If you want to use different Accounts you cant login with the other one by accident
[accounts.alt]
type = "microsoft"
forcedusername = "examplename"
```
When the `devauth.account` property is specified it takes precedence over the
`defaultAccount` config option.
Expand Down