Allow multiple auth tokens per player

This commit is contained in:
kuroppoi 2021-06-09 22:12:18 +02:00
parent c9df56cf32
commit 4eec43f55c
3 changed files with 51 additions and 32 deletions

View file

@ -45,8 +45,7 @@ public class GatewayService {
return;
}
playerManager.registerPlayer(name);
String token = playerManager.refreshAuthToken(name);
String token = playerManager.register(name);
ctx.json(new ServerConnectInfo(api.getGameServerHost(), name, token));
});
@ -58,7 +57,9 @@ public class GatewayService {
String token = request.getToken();
if(password != null) {
if(!playerManager.verifyPassword(name, password)) {
token = playerManager.login(name, password);
if(token == null) {
ContextUtils.error(ctx, "Username or password is incorrect. Please check your credentials.");
return;
}
@ -72,8 +73,7 @@ public class GatewayService {
return;
}
String newToken = playerManager.refreshAuthToken(name);
ctx.json(new ServerConnectInfo(api.getGameServerHost(), name, newToken));
ctx.json(new ServerConnectInfo(api.getGameServerHost(), name, token));
});
// Password reset request

View file

@ -61,7 +61,7 @@ import brainwine.gameserver.zone.Chunk;
import brainwine.gameserver.zone.MetaBlock;
import brainwine.gameserver.zone.Zone;
@JsonIncludeProperties({"name", "email", "password_hash", "token_hash", "admin", "karma", "crowns", "inventory", "equipped_clothing", "equipped_colors", "current_zone"})
@JsonIncludeProperties({"name", "email", "password_hash", "auth_tokens", "admin", "karma", "crowns", "inventory", "equipped_clothing", "equipped_colors", "current_zone"})
public class Player extends Entity implements CommandExecutor {
public static final int MAX_SKILL_LEVEL = 15;
@ -80,8 +80,8 @@ public class Player extends Entity implements CommandExecutor {
@JsonProperty("password_hash")
private String password;
@JsonProperty("token_hash")
private String authToken;
@JsonProperty("auth_tokens")
private final List<String> authTokens = new ArrayList<>();
@JsonProperty("admin")
private boolean admin;
@ -512,12 +512,16 @@ public class Player extends Entity implements CommandExecutor {
return password;
}
protected void setAuthToken(String authToken) {
this.authToken = authToken;
protected void clearAuthTokens() {
authTokens.clear();
}
protected String getAuthToken() {
return authToken;
protected void addAuthToken(String authToken) {
authTokens.add(authToken);
}
protected List<String> getAuthTokens() {
return authTokens;
}
public void setAdmin(boolean admin) {
@ -699,7 +703,7 @@ public class Player extends Entity implements CommandExecutor {
Map<String, Object> map = new HashMap<>();
map.put("email", email);
map.put("password_hash", password);
map.put("token_hash", authToken);
map.put("auth_tokens", authTokens);
map.put("name", name);
map.put("admin", admin);
map.put("karma", karma);

View file

@ -94,32 +94,47 @@ public class PlayerManager {
}
}
public String refreshAuthToken(String name) {
Player player = getPlayer(name);
String token = UUID.randomUUID().toString();
player.setAuthToken(BCrypt.hashpw(token, BCrypt.gensalt()));
return token;
}
public boolean verifyPassword(String name, String password) {
Player player = getPlayer(name);
return player == null ? false : player.getPassword() == null ? false : BCrypt.checkpw(password, player.getPassword());
}
public boolean verifyAuthToken(String name, String token) {
Player player = getPlayer(name);
return player == null ? false : BCrypt.checkpw(token, player.getAuthToken());
}
public void registerPlayer(String name) {
public String register(String name) {
if(getPlayer(name) != null) {
return;
return null;
}
String id = UUID.randomUUID().toString();
Player player = new Player(id, name, GameServer.getInstance().getZoneManager().getRandomZone()); // TODO tutorial zone
playersById.put(id, player);
playersByName.put(name.toLowerCase(), player);
String authToken = UUID.randomUUID().toString();
player.addAuthToken(BCrypt.hashpw(authToken, BCrypt.gensalt()));
return authToken;
}
public String login(String name, String password) {
Player player = getPlayer(name);
if(player == null || player.getPassword() == null) {
return null;
}
if(!BCrypt.checkpw(password, player.getPassword())) {
return null;
}
String authToken = UUID.randomUUID().toString();
player.addAuthToken(BCrypt.hashpw(authToken, BCrypt.gensalt()));
return authToken;
}
public boolean verifyAuthToken(String name, String authToken) {
Player player = getPlayer(name);
// Might not be very efficient...
for(String hashedToken : player.getAuthTokens()) {
if(BCrypt.checkpw(authToken, hashedToken)) {
return true;
}
}
return false;
}
public void onPlayerAuthenticate(Connection connection, String version, String name, String authToken) {