diff --git a/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java b/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java index 684227384da07555055b8fa3ba3e46bcd0fc26ff..4eab50036f5a24e0c95664fe69e1a5f878a4aba2 100644 --- a/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java +++ b/src/main/java/caosdb/server/accessControl/SelfValidatingAuthenticationToken.java @@ -27,6 +27,7 @@ package caosdb.server.accessControl; import caosdb.server.utils.Utils; import java.util.Arrays; import java.util.Collection; +import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.eclipse.jetty.util.ajax.JSON; @@ -35,14 +36,21 @@ import org.eclipse.jetty.util.ajax.JSON; * * <ul> * <li>date: The creation time. - * <li>timeout: How long this token is valud after creation. - * <li>checksum: ? Used for validation, but how? + * <li>timeout: How long this token is valid after creation. + * <li>checksum: The checksum is calculated from all relevant parts of the authentication token + * (including the salt, timeout, permissions, roles, and date) and most importantly, the + * pepper which serves as a randomized password of the server. The salt makes it hard to guess + * the pepper by creating a rainbow table with plausible values for the other properties. * <li>salt: Salt for the password checksum, may be used by inheriting classes. * <li>pepper: A static property, generated when class is loaded and used until the server - * reboots. Hence all tokens of this kkinf invalidate when the server reboots. - * - * @todo Explain: Checksum - * @todo Is this really a pepper in the sense in which it is usually used? + * reboots. It servers as randomized password of the server. "In cryptography, a pepper is a + * secret added to an input such as a password prior to being hashed with a cryptographic hash + * function." (from: Pepper (cryptography), + * https://en.wikipedia.org/w/index.php?title=Pepper_(cryptography)&oldid=960047694 (last + * visited July 7, 2020)) In our case, the pepper is added to the token before hashing, but + * not exposed to the public, while the salt is. That also means that the resulting hash + * cannot be generated by any client nor be validated by any client, and that all tokens of + * this kind invalidate when the server reboots. */ public abstract class SelfValidatingAuthenticationToken extends Principal implements AuthenticationToken { @@ -194,17 +202,19 @@ public abstract class SelfValidatingAuthenticationToken extends Principal /** * Parse a JSON string and return the generated token. Depending on the first element of the JSON, - * this is either (if it is "O") a OneTimeAuthenticationToken or else a SessionToken + * this is either (if it is "O") a OneTimeAuthenticationToken or (if it is "S") a SessionToken. * - * @todo Only allow "O" and "S"? + * @throws AuthenticationToken if the string could not be parsed into a token. */ public static SelfValidatingAuthenticationToken parse(String token) { Object[] array = (Object[]) JSON.parse(token); switch (array[0].toString()) { case "O": return OneTimeAuthenticationToken.parse(array); - default: + case "S": return SessionToken.parse(array); + default: + throw new AuthenticationException("Could not parse the authtoken string."); } } diff --git a/src/main/java/caosdb/server/accessControl/UserSources.java b/src/main/java/caosdb/server/accessControl/UserSources.java index 2aae14faddb3a35308ba6982a426db5e6e2e9b8f..cdf219c017608c621a59d427b2132630fef0631d 100644 --- a/src/main/java/caosdb/server/accessControl/UserSources.java +++ b/src/main/java/caosdb/server/accessControl/UserSources.java @@ -149,12 +149,11 @@ public class UserSources extends HashMap<String, UserSource> { /** * Return the roles of a given user. * - * @todo Refactor name: resolveRoles(...)? * @param realm * @param username - * @return + * @return A set of user roles. */ - public static Set<String> resolve(String realm, final String username) { + public static Set<String> resolveRoles(String realm, final String username) { if (realm == null) { realm = guessRealm(username); } @@ -206,7 +205,7 @@ public class UserSources extends HashMap<String, UserSource> { return roles; } - return resolve(principal.getRealm(), principal.getUsername()); + return resolveRoles(principal.getRealm(), principal.getUsername()); } public static boolean isRoleExisting(final String role) { diff --git a/src/main/java/caosdb/server/transaction/RetrieveUserRolesTransaction.java b/src/main/java/caosdb/server/transaction/RetrieveUserRolesTransaction.java index 76740a73c9439e4ea9e45479e57501c4c4e1a0d0..e864c20bcf040faf78dc54e24dbcdefc1a8be795 100644 --- a/src/main/java/caosdb/server/transaction/RetrieveUserRolesTransaction.java +++ b/src/main/java/caosdb/server/transaction/RetrieveUserRolesTransaction.java @@ -58,7 +58,7 @@ public class RetrieveUserRolesTransaction implements TransactionInterface { @Override public void execute() throws Exception { if (UserSources.isUserExisting(new Principal(this.realm, this.user))) { - this.roles = UserSources.resolve(this.realm, this.user); + this.roles = UserSources.resolveRoles(this.realm, this.user); } else { throw ServerMessages.ACCOUNT_DOES_NOT_EXIST; } diff --git a/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java b/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java index 257e8c06cc9d9c9f24774e541cea611663f5ff0d..f11400c3826170de658fd9e5a634665f00e1cb44 100644 --- a/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java +++ b/src/main/java/caosdb/server/transaction/UpdateUserRolesTransaction.java @@ -68,7 +68,7 @@ public class UpdateUserRolesTransaction extends AccessControlTransaction { } public Element getUserRolesElement() { - final Set<String> resulting_roles = UserSources.resolve(this.realm, this.user); + final Set<String> resulting_roles = UserSources.resolveRoles(this.realm, this.user); final Element rolesElem = RetrieveUserRolesTransaction.getUserRolesElement(resulting_roles); if (!this.roles.equals(resulting_roles) && resulting_roles != null) { final Element warning = new Element("Warning");