From 31d7eccd2b0effdadaaa5b6349e5b6b6ea753e3c Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Thu, 10 Jan 2019 16:50:51 +0100 Subject: [PATCH] Improve tokens management --- .../org/argeo/cms/e4/users/GroupsView.java | 12 ++- .../argeo/cms/auth/UserAdminLoginModule.java | 24 ++--- .../osgi/useradmin/AbstractUserDirectory.java | 1 - .../useradmin/AggregatingAuthorization.java | 2 - .../osgi/useradmin/AggregatingUserAdmin.java | 3 +- .../osgi/useradmin/AuthenticatingUser.java | 4 +- .../argeo/osgi/useradmin/LdapUserAdmin.java | 1 - .../argeo/osgi/useradmin/LdifUserAdmin.java | 2 - .../org/argeo/osgi/useradmin/TokenUtils.java | 87 +++++++++++++++++++ 9 files changed, 111 insertions(+), 25 deletions(-) create mode 100644 org.argeo.enterprise/src/org/argeo/osgi/useradmin/TokenUtils.java diff --git a/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java b/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java index 53937c9d7..7d36a9507 100644 --- a/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java +++ b/org.argeo.cms.e4/src/org/argeo/cms/e4/users/GroupsView.java @@ -210,6 +210,10 @@ public class GroupsView implements ArgeoNames { if (tmpBuilder.length() > 1) { builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") .append(LdapObjs.groupOfNames.name()).append(")"); + // hide tokens + builder.append("(!(").append(LdapAttrs.DN).append("=*").append(NodeConstants.TOKENS_BASEDN) + .append("))"); + if (!showSystemRoles) builder.append("(!(").append(LdapAttrs.DN).append("=*").append(NodeConstants.ROLES_BASEDN) .append("))"); @@ -220,10 +224,12 @@ public class GroupsView implements ArgeoNames { if (!showSystemRoles) builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") .append(LdapObjs.groupOfNames.name()).append(")(!(").append(LdapAttrs.DN).append("=*") - .append(NodeConstants.ROLES_BASEDN).append(")))"); + .append(NodeConstants.ROLES_BASEDN).append("))(!(").append(LdapAttrs.DN).append("=*") + .append(NodeConstants.TOKENS_BASEDN).append(")))"); else - builder.append("(").append(LdapAttrs.objectClass.name()).append("=") - .append(LdapObjs.groupOfNames.name()).append(")"); + builder.append("(&(").append(LdapAttrs.objectClass.name()).append("=") + .append(LdapObjs.groupOfNames.name()).append(")(!(").append(LdapAttrs.DN).append("=*") + .append(NodeConstants.TOKENS_BASEDN).append(")))"); } roles = userAdminWrapper.getUserAdmin().getRoles(builder.toString()); diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index ad9eb24c5..7297513c2 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -1,11 +1,9 @@ package org.argeo.cms.auth; import static org.argeo.naming.LdapAttrs.cn; -import static org.argeo.naming.LdapAttrs.description; import java.io.IOException; import java.security.PrivilegedAction; -import java.time.Instant; import java.util.Arrays; import java.util.HashSet; import java.util.List; @@ -32,12 +30,12 @@ import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; import org.argeo.cms.internal.kernel.Activator; import org.argeo.naming.LdapAttrs; -import org.argeo.naming.NamingUtils; import org.argeo.node.NodeConstants; import org.argeo.node.security.CryptoKeyring; import org.argeo.osgi.useradmin.AuthenticatingUser; import org.argeo.osgi.useradmin.IpaUtils; import org.argeo.osgi.useradmin.OsUserUtils; +import org.argeo.osgi.useradmin.TokenUtils; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; @@ -336,15 +334,17 @@ public class UserAdminLoginModule implements LoginModule { } protected Authorization getAuthorizationFromToken(UserAdmin userAdmin, Group tokenGroup) { - String expiryDateStr = (String) tokenGroup.getProperties().get(description.name()); - if (expiryDateStr != null) { - Instant expiryDate = NamingUtils.ldapDateToInstant(expiryDateStr); - if (expiryDate.isBefore(Instant.now())) { - if (log.isDebugEnabled()) - log.debug("Token " + tokenGroup.getName() + " has expired."); - return null; - } - } + if (TokenUtils.isExpired(tokenGroup)) + return null; +// String expiryDateStr = (String) tokenGroup.getProperties().get(description.name()); +// if (expiryDateStr != null) { +// Instant expiryDate = NamingUtils.ldapDateToInstant(expiryDateStr); +// if (expiryDate.isBefore(Instant.now())) { +// if (log.isDebugEnabled()) +// log.debug("Token " + tokenGroup.getName() + " has expired."); +// return null; +// } +// } Authorization auth = userAdmin.getAuthorization(tokenGroup); return auth; } diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index 95b1f07ad..385ea740e 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -232,7 +232,6 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory return user; } - @SuppressWarnings("unchecked") @Override public Role[] getRoles(String filter) throws InvalidSyntaxException { UserDirectoryWorkingCopy wc = getWorkingCopy(); diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java index b450b729e..6729a2c2d 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingAuthorization.java @@ -6,8 +6,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import javax.security.auth.x500.X500Principal; - import org.osgi.service.useradmin.Authorization; class AggregatingAuthorization implements Authorization { diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java index cc1dadb9b..b09c8df5e 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AggregatingUserAdmin.java @@ -13,7 +13,6 @@ import java.util.Set; import javax.naming.InvalidNameException; import javax.naming.ldap.LdapName; -import org.argeo.naming.LdapAttrs; import org.osgi.framework.InvalidSyntaxException; import org.osgi.service.useradmin.Authorization; import org.osgi.service.useradmin.Group; @@ -89,7 +88,7 @@ public class AggregatingUserAdmin implements UserAdmin { String usernameToUse; String displayNameToUse; if (user instanceof Group) { - String ownerDn = (String) user.getProperties().get(LdapAttrs.owner.name()); + String ownerDn = TokenUtils.userDn((Group) user); if (ownerDn != null) {// tokens UserAdmin ownerUserAdmin = findUserAdmin(ownerDn); User ownerUser = (User) ownerUserAdmin.getRole(ownerDn); diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AuthenticatingUser.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AuthenticatingUser.java index 6bf1441b5..939b03852 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AuthenticatingUser.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AuthenticatingUser.java @@ -48,13 +48,13 @@ public class AuthenticatingUser implements User { return User.USER; } - @SuppressWarnings("rawtypes") + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Dictionary getProperties() { throw new UnsupportedOperationException(); } - @SuppressWarnings("rawtypes") + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public Dictionary getCredentials() { return credentials; diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java index 6dbf6c2d7..10a75feb0 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -78,7 +78,6 @@ public class LdapUserAdmin extends AbstractUserDirectory { } } - @SuppressWarnings("unchecked") @Override protected AbstractUserDirectory scope(User user) { Dictionary credentials = user.getCredentials(); diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdifUserAdmin.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdifUserAdmin.java index 8668152d6..e75c69822 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdifUserAdmin.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdifUserAdmin.java @@ -51,7 +51,6 @@ public class LdifUserAdmin extends AbstractUserDirectory { super(uri, properties); } - @SuppressWarnings("unchecked") @Override protected AbstractUserDirectory scope(User user) { Dictionary credentials = user.getCredentials(); @@ -180,7 +179,6 @@ public class LdifUserAdmin extends AbstractUserDirectory { return users.containsKey(dn) || groups.containsKey(dn); } - @SuppressWarnings("unchecked") protected List doGetRoles(Filter f) { ArrayList res = new ArrayList(); if (f == null) { diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/TokenUtils.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/TokenUtils.java new file mode 100644 index 000000000..83c1d76f6 --- /dev/null +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/TokenUtils.java @@ -0,0 +1,87 @@ +package org.argeo.osgi.useradmin; + +import static org.argeo.naming.LdapAttrs.description; +import static org.argeo.naming.LdapAttrs.owner; + +import java.security.Principal; +import java.time.Instant; +import java.util.HashSet; +import java.util.Set; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.security.auth.Subject; + +import org.argeo.naming.NamingUtils; +import org.osgi.service.useradmin.Group; + +/** + * Canonically implements the Argeo token conventions. + */ +public class TokenUtils { + public static Set tokensUsed(Subject subject, String tokensBaseDn) { + Set res = new HashSet<>(); + for (Principal principal : subject.getPrincipals()) { + String name = principal.getName(); + if (name.endsWith(tokensBaseDn)) { + try { + LdapName ldapName = new LdapName(name); + String token = ldapName.getRdn(ldapName.size()).getValue().toString(); + res.add(token); + } catch (InvalidNameException e) { + throw new UserDirectoryException("Invalid principal " + principal, e); + } + } + } + return res; + } + + /** The user related to this token group */ + public static String userDn(Group tokenGroup) { + return (String) tokenGroup.getProperties().get(owner.name()); + } + + public static boolean isExpired(Group tokenGroup) { + return isExpired(tokenGroup, Instant.now()); + + } + + public static boolean isExpired(Group tokenGroup, Instant instant) { + String expiryDateStr = (String) tokenGroup.getProperties().get(description.name()); + if (expiryDateStr != null) { + Instant expiryDate = NamingUtils.ldapDateToInstant(expiryDateStr); + if (expiryDate.isBefore(instant)) { + return true; + } + } + return false; + } + +// private final String token; +// +// public TokenUtils(String token) { +// this.token = token; +// } +// +// public String getToken() { +// return token; +// } +// +// @Override +// public int hashCode() { +// return token.hashCode(); +// } +// +// @Override +// public boolean equals(Object obj) { +// if ((obj instanceof TokenUtils) && ((TokenUtils) obj).token.equals(token)) +// return true; +// return false; +// } +// +// @Override +// public String toString() { +// return "Token #" + hashCode(); +// } + +} -- 2.30.2