From 6e7769555f6ee64159bbdb5780e34957d6d8895e Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 13 Feb 2015 22:18:02 +0000 Subject: [PATCH] Improve login git-svn-id: https://svn.argeo.org/commons/trunk@7854 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../cms/internal/kernel/NodeSecurity.java | 21 ++- .../org/argeo/cms/internal/kernel/jaas.cfg | 6 +- .../internal/useradmin/AbstractJcrUser.java | 13 +- .../internal/useradmin/JcrAuthorization.java | 39 +++++ .../cms/internal/useradmin/JcrEndUser.java | 25 ++- .../cms/internal/useradmin/JcrGroup.java | 24 +++ .../argeo/cms/internal/useradmin/JcrRole.java | 13 +- .../cms/internal/useradmin/JcrUserAdmin.java | 36 ++-- .../src/org/argeo/security/ArgeoGroup.java | 7 - .../src/org/argeo/security/ArgeoUser.java | 9 - .../security/NodeAuthenticationToken.java | 13 ++ .../security/core/AuthorizationPrincipal.java | 24 --- .../JackrabbitUserAdminService.java | 7 +- ...le.java => AbstractSpringLoginModule.java} | 32 ++-- .../security/login/AnonymousLoginModule.java | 2 +- .../ConsoleCallbackHandler.java | 2 +- .../security/login/EndUserLoginModule.java | 8 +- .../security/login/SystemLoginModule.java | 2 +- .../security/login/UserAdminLoginModule.java | 157 ------------------ .../security/jackrabbit/ArgeoLoginModule.java | 53 +----- 20 files changed, 186 insertions(+), 307 deletions(-) create mode 100644 org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrAuthorization.java delete mode 100644 org.argeo.security.core/src/org/argeo/security/ArgeoGroup.java delete mode 100644 org.argeo.security.core/src/org/argeo/security/ArgeoUser.java delete mode 100644 org.argeo.security.core/src/org/argeo/security/core/AuthorizationPrincipal.java rename org.argeo.security.core/src/org/argeo/security/login/{AbstractSpringSecurityLoginModule.java => AbstractSpringLoginModule.java} (81%) rename org.argeo.security.core/src/org/argeo/security/{core => login}/ConsoleCallbackHandler.java (98%) delete mode 100644 org.argeo.security.core/src/org/argeo/security/login/UserAdminLoginModule.java diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java index be94cd5df..d0aec2023 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java @@ -7,6 +7,8 @@ import javax.jcr.RepositoryException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; +import org.argeo.cms.internal.useradmin.JcrUserAdmin; +import org.argeo.security.SecurityUtils; import org.argeo.security.UserAdminService; import org.argeo.security.core.InternalAuthentication; import org.argeo.security.core.InternalAuthenticationProvider; @@ -14,6 +16,7 @@ import org.argeo.security.jcr.SimpleJcrSecurityModel; import org.argeo.security.jcr.jackrabbit.JackrabbitUserAdminService; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; +import org.osgi.service.useradmin.UserAdmin; import org.springframework.security.authentication.AnonymousAuthenticationProvider; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.AuthenticationManager; @@ -31,13 +34,13 @@ class NodeSecurity implements AuthenticationManager { private final InternalAuthenticationProvider internalAuth; private final AnonymousAuthenticationProvider anonymousAuth; private final JackrabbitUserAdminService userAdminService; - // private final JcrUserAdmin userAdmin; + private final JcrUserAdmin userAdmin; private ServiceRegistration authenticationManagerReg; private ServiceRegistration userAdminServiceReg; private ServiceRegistration userDetailsManagerReg; - // private ServiceRegistration userAdminReg; + private ServiceRegistration userAdminReg; public NodeSecurity(BundleContext bundleContext, JackrabbitNode node) throws RepositoryException { @@ -49,9 +52,9 @@ class NodeSecurity implements AuthenticationManager { this.bundleContext = bundleContext; internalAuth = new InternalAuthenticationProvider( - KernelConstants.DEFAULT_SECURITY_KEY); + SecurityUtils.getStaticKey()); anonymousAuth = new AnonymousAuthenticationProvider( - KernelConstants.DEFAULT_SECURITY_KEY); + SecurityUtils.getStaticKey()); // user admin userAdminService = new JackrabbitUserAdminService(); @@ -59,8 +62,8 @@ class NodeSecurity implements AuthenticationManager { userAdminService.setSecurityModel(new SimpleJcrSecurityModel()); userAdminService.init(); - // userAdmin = new JcrUserAdmin(bundleContext); - // userAdmin.setUserAdminService(userAdminService); + userAdmin = new JcrUserAdmin(bundleContext, node); + userAdmin.setUserAdminService(userAdminService); } public void publish() { @@ -70,8 +73,8 @@ class NodeSecurity implements AuthenticationManager { UserAdminService.class, userAdminService, null); userDetailsManagerReg = bundleContext.registerService( UserDetailsManager.class, userAdminService, null); - // userAdminReg = bundleContext.registerService(UserAdmin.class, - // userAdmin, null); + userAdminReg = bundleContext.registerService(UserAdmin.class, + userAdmin, null); } void destroy() { @@ -83,7 +86,7 @@ class NodeSecurity implements AuthenticationManager { userDetailsManagerReg.unregister(); userAdminServiceReg.unregister(); authenticationManagerReg.unregister(); - // userAdminReg.unregister(); + userAdminReg.unregister(); } @Override diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg index 0155fc5ee..55194eab8 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg @@ -1,16 +1,16 @@ USER { org.argeo.security.login.EndUserLoginModule requisite; - org.springframework.security.authentication.jaas.SecurityContextLoginModule required; + org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; ANONYMOUS { org.argeo.security.login.AnonymousLoginModule requisite; - org.springframework.security.authentication.jaas.SecurityContextLoginModule required; + org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; SYSTEM { org.argeo.security.login.SystemLoginModule requisite; - org.springframework.security.authentication.jaas.SecurityContextLoginModule required; + org.springframework.security.authentication.jaas.SecurityContextLoginModule requisite; }; KEYRING { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/AbstractJcrUser.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/AbstractJcrUser.java index 25510f605..f13da0128 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/AbstractJcrUser.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/AbstractJcrUser.java @@ -2,9 +2,18 @@ package org.argeo.cms.internal.useradmin; import java.util.Dictionary; -import org.argeo.security.ArgeoUser; +import org.osgi.service.useradmin.Role; +import org.osgi.service.useradmin.User; -abstract class AbstractJcrUser extends JcrRole implements ArgeoUser { +abstract class AbstractJcrUser extends JcrRole implements User { + public AbstractJcrUser(String name) { + super(name); + } + + @Override + public int getType() { + return Role.USER; + } @Override public Dictionary getCredentials() { diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrAuthorization.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrAuthorization.java new file mode 100644 index 000000000..76f67ce71 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrAuthorization.java @@ -0,0 +1,39 @@ +package org.argeo.cms.internal.useradmin; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.argeo.security.jcr.JcrUserDetails; +import org.osgi.service.useradmin.Authorization; +import org.springframework.security.core.GrantedAuthority; + +class JcrAuthorization implements Authorization { + private final String name; + private final List roles; + + public JcrAuthorization(JcrUserDetails userDetails) { + this.name = userDetails.getUsername(); + List t = new ArrayList(); + for (GrantedAuthority ga : userDetails.getAuthorities()) { + t.add(ga.getAuthority()); + } + roles = Collections.unmodifiableList(t); + } + + @Override + public String getName() { + return name; + } + + @Override + public boolean hasRole(String name) { + return roles.contains(name); + } + + @Override + public String[] getRoles() { + return roles.toArray(new String[roles.size()]); + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrEndUser.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrEndUser.java index b2ce05f21..fbbbdd01f 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrEndUser.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrEndUser.java @@ -1,16 +1,31 @@ package org.argeo.cms.internal.useradmin; -import org.springframework.security.core.userdetails.UserDetails; +import org.argeo.security.jcr.JcrUserDetails; -class JcrEndUser extends AbstractJcrUser { - private final UserDetails userDetails; +class JcrEndUser extends AbstractJcrUser { + private final JcrUserDetails userDetails; - public JcrEndUser(UserDetails userDetails) { + public JcrEndUser(JcrUserDetails userDetails) { + super(userDetails.getUsername()); this.userDetails = userDetails; } - UserDetails getUserDetails() { + JcrUserDetails getUserDetails() { return userDetails; } + public String toString() { + return "ArgeoUser: " + getName(); + } + + public boolean equals(Object obj) { + if (!(obj instanceof JcrEndUser)) + return false; + else + return ((JcrEndUser) obj).getName().equals(getName()); + } + + public int hashCode() { + return getName().hashCode(); + } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrGroup.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrGroup.java index ffbeb1306..93f758758 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrGroup.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrGroup.java @@ -5,6 +5,15 @@ import org.osgi.service.useradmin.Role; class JcrGroup extends AbstractJcrUser implements Group { public JcrGroup(String name) { + super(name); + } + + // + // OSGi MODEL + // + @Override + public int getType() { + return Role.GROUP; } @Override @@ -37,4 +46,19 @@ class JcrGroup extends AbstractJcrUser implements Group { return null; } + public String toString() { + return "ArgeoGroup: " + getName(); + } + + public boolean equals(Object obj) { + if (!(obj instanceof JcrGroup)) + return false; + else + return ((JcrGroup) obj).getName().equals(getName()); + } + + public int hashCode() { + return getName().hashCode(); + } + } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrRole.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrRole.java index 5bd0d578c..43ded9e59 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrRole.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrRole.java @@ -4,18 +4,21 @@ import java.util.Dictionary; import org.osgi.service.useradmin.Role; -class JcrRole implements Role { +abstract class JcrRole implements Role { + private String name; + + public JcrRole(String name) { + this.name = name; + } @Override public String getName() { - // TODO Auto-generated method stub - return null; + return name; } @Override public int getType() { - // TODO Auto-generated method stub - return 0; + return Role.ROLE; } @Override diff --git a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java index cc4028874..94051d92e 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/useradmin/JcrUserAdmin.java @@ -1,8 +1,5 @@ package org.argeo.cms.internal.useradmin; -import static org.argeo.jcr.ArgeoJcrConstants.ALIAS_NODE; -import static org.argeo.jcr.ArgeoJcrConstants.JCR_REPOSITORY_ALIAS; - import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -14,6 +11,7 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; import org.argeo.ArgeoException; +import org.argeo.jcr.JcrUtils; import org.argeo.security.UserAdminService; import org.argeo.security.jcr.JcrSecurityModel; import org.argeo.security.jcr.JcrUserDetails; @@ -28,7 +26,6 @@ import org.osgi.service.useradmin.UserAdmin; import org.osgi.service.useradmin.UserAdminEvent; import org.osgi.service.useradmin.UserAdminListener; import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UsernameNotFoundException; public class JcrUserAdmin implements UserAdmin { @@ -38,20 +35,19 @@ public class JcrUserAdmin implements UserAdmin { private final JcrSecurityModel jcrSecurityModel = new SimpleJcrSecurityModel(); private final Session session; - public JcrUserAdmin(BundleContext bundleContext) { + public JcrUserAdmin(BundleContext bundleContext, Repository node) { try { this.bundleContext = bundleContext; - - ServiceReference nodeRepo = bundleContext - .getServiceReferences(Repository.class, - "(" + JCR_REPOSITORY_ALIAS + "=" + ALIAS_NODE + ")") - .iterator().next(); - this.session = bundleContext.getService(nodeRepo).login(); + this.session = node.login(); } catch (Exception e) { throw new ArgeoException("Cannot initialize user admin", e); } } + public void destroy() { + JcrUtils.logoutQuietly(session); + } + @Override public Role createRole(String name, int type) { try { @@ -95,14 +91,15 @@ public class JcrUserAdmin implements UserAdmin { @Override public Role getRole(String name) { - if (userAdminService().listEditableRoles().contains(name)) - return new JcrGroup(name); try { - UserDetails userDetails = userAdminService().loadUserByUsername( - name); + JcrUserDetails userDetails = (JcrUserDetails) userAdminService() + .loadUserByUsername(name); return new JcrEndUser(userDetails); } catch (UsernameNotFoundException e) { - return null; + if (userAdminService().listEditableRoles().contains(name)) + return new JcrGroup(name); + else + return null; } } @@ -118,8 +115,9 @@ public class JcrUserAdmin implements UserAdmin { for (int i = 0; i < roles.size(); i++) res[i] = new JcrGroup(roles.get(i)); for (int i = 0; i < users.size(); i++) - res[roles.size() + i] = new JcrEndUser(userAdminService() - .loadUserByUsername(users.get(i))); + res[roles.size() + i] = new JcrEndUser( + (JcrUserDetails) userAdminService().loadUserByUsername( + users.get(i))); return res; } @@ -130,7 +128,7 @@ public class JcrUserAdmin implements UserAdmin { @Override public Authorization getAuthorization(User user) { - return null; + return new JcrAuthorization(((JcrEndUser) user).getUserDetails()); } private synchronized UserAdminService userAdminService() { diff --git a/org.argeo.security.core/src/org/argeo/security/ArgeoGroup.java b/org.argeo.security.core/src/org/argeo/security/ArgeoGroup.java deleted file mode 100644 index 42c09e6e2..000000000 --- a/org.argeo.security.core/src/org/argeo/security/ArgeoGroup.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.argeo.security; - -import org.osgi.service.useradmin.Group; - -public interface ArgeoGroup extends ArgeoUser, Group, java.security.acl.Group { - -} diff --git a/org.argeo.security.core/src/org/argeo/security/ArgeoUser.java b/org.argeo.security.core/src/org/argeo/security/ArgeoUser.java deleted file mode 100644 index 193858a60..000000000 --- a/org.argeo.security.core/src/org/argeo/security/ArgeoUser.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.argeo.security; - -import java.security.Principal; - -import org.osgi.service.useradmin.User; - -public interface ArgeoUser extends Principal, User { - -} diff --git a/org.argeo.security.core/src/org/argeo/security/NodeAuthenticationToken.java b/org.argeo.security.core/src/org/argeo/security/NodeAuthenticationToken.java index 4a802553b..600811d75 100644 --- a/org.argeo.security.core/src/org/argeo/security/NodeAuthenticationToken.java +++ b/org.argeo.security.core/src/org/argeo/security/NodeAuthenticationToken.java @@ -53,4 +53,17 @@ public class NodeAuthenticationToken extends public Boolean isRemote() { return url != null; } + + public String toString() { + String username = getName(); + StringBuilder buf = new StringBuilder("groups="); + for (GrantedAuthority ga : getAuthorities()) { + if (!ga.getAuthority().equals(username)) { + buf.append(ga.getAuthority()); + buf.append(','); + } + } + buf.deleteCharAt(buf.length() - 1); + return "uid=" + getName() + " " + buf.toString(); + } } diff --git a/org.argeo.security.core/src/org/argeo/security/core/AuthorizationPrincipal.java b/org.argeo.security.core/src/org/argeo/security/core/AuthorizationPrincipal.java deleted file mode 100644 index ac3b23369..000000000 --- a/org.argeo.security.core/src/org/argeo/security/core/AuthorizationPrincipal.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.argeo.security.core; - -import java.security.Principal; - -import org.osgi.service.useradmin.Authorization; - -/** Wraps an OSGi {@link Authorization} as a JAAS {@link Principal} */ -public final class AuthorizationPrincipal implements Principal { - private Authorization authorization; - - public AuthorizationPrincipal(Authorization authorization) { - this.authorization = authorization; - } - - @Override - public String getName() { - return authorization.getName(); - } - - public Authorization getAuthorization() { - return authorization; - } - -} diff --git a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java b/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java index 711c9d598..c0b4b4b15 100644 --- a/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java +++ b/org.argeo.security.core/src/org/argeo/security/jcr/jackrabbit/JackrabbitUserAdminService.java @@ -22,6 +22,7 @@ import org.apache.jackrabbit.core.security.authentication.CryptedSimpleCredentia import org.argeo.ArgeoException; import org.argeo.jcr.JcrUtils; import org.argeo.jcr.UserJcrUtils; +import org.argeo.security.NodeAuthenticationToken; import org.argeo.security.UserAdminService; import org.argeo.security.jcr.JcrSecurityModel; import org.argeo.security.jcr.JcrUserDetails; @@ -300,7 +301,7 @@ public class JackrabbitUserAdminService implements UserAdminService, // AUTHENTICATION PROVIDER public synchronized Authentication authenticate( Authentication authentication) throws AuthenticationException { - UsernamePasswordAuthenticationToken siteAuth = (UsernamePasswordAuthenticationToken) authentication; + NodeAuthenticationToken siteAuth = (NodeAuthenticationToken) authentication; String username = siteAuth.getName(); if (!(siteAuth.getCredentials() instanceof char[])) throw new ArgeoException("Only char array passwords are supported"); @@ -334,8 +335,8 @@ public class JackrabbitUserAdminService implements UserAdminService, try { JcrUserDetails userDetails = loadJcrUserDetails(adminSession, username); - UsernamePasswordAuthenticationToken authenticated = new UsernamePasswordAuthenticationToken( - siteAuth, "", userDetails.getAuthorities()); + NodeAuthenticationToken authenticated = new NodeAuthenticationToken( + siteAuth, userDetails.getAuthorities()); authenticated.setDetails(userDetails); return authenticated; } catch (RepositoryException e) { diff --git a/org.argeo.security.core/src/org/argeo/security/login/AbstractSpringSecurityLoginModule.java b/org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java similarity index 81% rename from org.argeo.security.core/src/org/argeo/security/login/AbstractSpringSecurityLoginModule.java rename to org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java index 923646f05..8a09a08e0 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/AbstractSpringSecurityLoginModule.java +++ b/org.argeo.security.core/src/org/argeo/security/login/AbstractSpringLoginModule.java @@ -25,15 +25,20 @@ import javax.security.auth.login.LoginException; import javax.security.auth.spi.LoginModule; import org.osgi.framework.BundleContext; +import org.osgi.service.useradmin.UserAdmin; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; /** Login module which caches one subject per thread. */ -abstract class AbstractSpringSecurityLoginModule implements LoginModule { +abstract class AbstractSpringLoginModule implements LoginModule { + // private final static Log log = LogFactory + // .getLog(AbstractSpringLoginModule.class); private CallbackHandler callbackHandler; private Subject subject; + private Authentication authentication; + protected abstract Authentication processLogin( CallbackHandler callbackHandler) throws LoginException, UnsupportedCallbackException, IOException, InterruptedException; @@ -54,7 +59,8 @@ abstract class AbstractSpringSecurityLoginModule implements LoginModule { .getAuthentication(); if (currentAuth != null) { if (subject.getPrincipals(Authentication.class).size() == 0) { - subject.getPrincipals().add(currentAuth); + throw new LoginException( + "Security context set but not Authentication principal"); } else { Authentication principal = subject .getPrincipals(Authentication.class).iterator() @@ -66,18 +72,10 @@ abstract class AbstractSpringSecurityLoginModule implements LoginModule { return true; } - // reset all principals and credentials - // if (log.isTraceEnabled()) - // log.trace("Resetting all principals and credentials of " - // + subject); - // subject.getPrincipals().clear(); - // subject.getPrivateCredentials().clear(); - // subject.getPublicCredentials().clear(); - if (callbackHandler == null) throw new LoginException("No callback handler available"); - Authentication authentication = processLogin(callbackHandler); + authentication = processLogin(callbackHandler); if (authentication != null) { SecurityContextHolder.getContext().setAuthentication( authentication); @@ -102,7 +100,7 @@ abstract class AbstractSpringSecurityLoginModule implements LoginModule { @Override public boolean logout() throws LoginException { - // subject.getPrincipals().clear(); + SecurityContextHolder.getContext().setAuthentication(null); return true; } @@ -113,6 +111,7 @@ abstract class AbstractSpringSecurityLoginModule implements LoginModule { @Override public boolean abort() throws LoginException { + SecurityContextHolder.getContext().setAuthentication(null); return true; } @@ -123,4 +122,13 @@ abstract class AbstractSpringSecurityLoginModule implements LoginModule { .getServiceReference(AuthenticationManager.class)); } + + protected UserAdmin getUserAdmin(BundleContextCallback bundleContextCallback) { + BundleContext bc = bundleContextCallback.getBundleContext(); + return bc.getService(bc.getServiceReference(UserAdmin.class)); + } + + protected Subject getSubject() { + return subject; + } } diff --git a/org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java b/org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java index e94c3e0fe..0a1279cae 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java +++ b/org.argeo.security.core/src/org/argeo/security/login/AnonymousLoginModule.java @@ -33,7 +33,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.authority.SimpleGrantedAuthority; /** Login module which caches one subject per thread. */ -public class AnonymousLoginModule extends AbstractSpringSecurityLoginModule { +public class AnonymousLoginModule extends AbstractSpringLoginModule { private String anonymousRole = "ROLE_ANONYMOUS"; /** Comma separated list of locales */ private String availableLocales = null; diff --git a/org.argeo.security.core/src/org/argeo/security/core/ConsoleCallbackHandler.java b/org.argeo.security.core/src/org/argeo/security/login/ConsoleCallbackHandler.java similarity index 98% rename from org.argeo.security.core/src/org/argeo/security/core/ConsoleCallbackHandler.java rename to org.argeo.security.core/src/org/argeo/security/login/ConsoleCallbackHandler.java index faa81b004..4c47ac637 100644 --- a/org.argeo.security.core/src/org/argeo/security/core/ConsoleCallbackHandler.java +++ b/org.argeo.security.core/src/org/argeo/security/login/ConsoleCallbackHandler.java @@ -1,4 +1,4 @@ -package org.argeo.security.core; +package org.argeo.security.login; import java.io.Console; import java.io.IOException; diff --git a/org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java b/org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java index d89643919..e01e714fd 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java +++ b/org.argeo.security.core/src/org/argeo/security/login/EndUserLoginModule.java @@ -32,7 +32,7 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.core.Authentication; /** Authenticates an end user */ -public class EndUserLoginModule extends AbstractSpringSecurityLoginModule { +public class EndUserLoginModule extends AbstractSpringLoginModule { final static String NODE_REPO_URI = "argeo.node.repo.uri"; private Long waitBetweenFailedLoginAttempts = 5 * 1000l; @@ -92,9 +92,15 @@ public class EndUserLoginModule extends AbstractSpringSecurityLoginModule { Thread.sleep(waitBetweenFailedLoginAttempts); throw e; } + if (selectedLocale != null) LocaleUtils.threadLocale.set(selectedLocale); return auth; } + + @Override + public boolean commit() throws LoginException { + return super.commit(); + } } diff --git a/org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java b/org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java index b1b1d3434..54e80e847 100644 --- a/org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java +++ b/org.argeo.security.core/src/org/argeo/security/login/SystemLoginModule.java @@ -27,7 +27,7 @@ import org.argeo.security.core.InternalAuthentication; import org.springframework.security.core.Authentication; /** Login module which caches one subject per thread. */ -public class SystemLoginModule extends AbstractSpringSecurityLoginModule { +public class SystemLoginModule extends AbstractSpringLoginModule { @Override protected Authentication processLogin(CallbackHandler callbackHandler) throws LoginException, UnsupportedCallbackException, IOException, diff --git a/org.argeo.security.core/src/org/argeo/security/login/UserAdminLoginModule.java b/org.argeo.security.core/src/org/argeo/security/login/UserAdminLoginModule.java deleted file mode 100644 index 530c0608e..000000000 --- a/org.argeo.security.core/src/org/argeo/security/login/UserAdminLoginModule.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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 org.argeo.security.login; - -import java.util.Locale; -import java.util.Map; - -import javax.security.auth.Subject; -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.login.LoginException; -import javax.security.auth.spi.LoginModule; - -import org.argeo.jcr.ArgeoNames; -import org.argeo.security.core.AuthorizationPrincipal; -import org.argeo.util.LocaleCallback; -import org.argeo.util.LocaleUtils; -import org.osgi.framework.BundleContext; -import org.osgi.service.useradmin.Authorization; -import org.osgi.service.useradmin.User; -import org.osgi.service.useradmin.UserAdmin; -import org.springframework.security.authentication.encoding.LdapShaPasswordEncoder; - -/** Login module which caches one subject per thread. */ -public class UserAdminLoginModule implements LoginModule { - // private final static Log log = LogFactory - // .getLog(UserAdminLoginModule.class); - - private CallbackHandler callbackHandler; - - private Subject subject; - - private Long waitBetweenFailedLoginAttempts = 5 * 1000l; - - /** Comma separated list of locales */ - private String availableLocales = ""; - - private AuthorizationPrincipal auth = null; - private Locale selectedLocale = null; - - @SuppressWarnings("unused") - private LdapShaPasswordEncoder shaPasswordEncoder = new LdapShaPasswordEncoder(); - - public UserAdminLoginModule() { - - } - - @SuppressWarnings("rawtypes") - public void initialize(Subject subject, CallbackHandler callbackHandler, - Map sharedState, Map options) { - this.callbackHandler = callbackHandler; - this.subject = subject; - } - - public boolean login() throws LoginException { - try { - // TODO thread already logged in - // AuthorizationPrincipal principal = subject - // .getPrincipals(AuthorizationPrincipal.class).iterator(); - - if (callbackHandler == null) - throw new LoginException("No call back handler available"); - - // ask for username and password - NameCallback nameCallback = new NameCallback("User"); - PasswordCallback passwordCallback = new PasswordCallback( - "Password", false); - LocaleCallback localeCallback = new LocaleCallback(availableLocales); - BundleContextCallback bundleContextCallback = new BundleContextCallback(); - - callbackHandler.handle(new Callback[] { nameCallback, - passwordCallback, localeCallback, bundleContextCallback }); - - selectedLocale = localeCallback.getSelectedLocale(); - - // create credentials - final String username = nameCallback.getName(); - if (username == null || username.trim().equals("")) - return false; - - char[] password = {}; - if (passwordCallback.getPassword() != null) - password = passwordCallback.getPassword(); - - BundleContext bc = bundleContextCallback.getBundleContext(); - UserAdmin userAdmin = bc.getService(bc - .getServiceReference(UserAdmin.class)); - - User user = (User) userAdmin.getRole(username); - // TODO use hash - boolean authenticated = user.hasCredential( - ArgeoNames.ARGEO_PASSWORD, new String(password)); - - if (!authenticated) { - // wait between failed login attempts - Thread.sleep(waitBetweenFailedLoginAttempts); - return false; - } - - Authorization authorization = userAdmin.getAuthorization(user); - auth = new AuthorizationPrincipal(authorization); - return true; - } catch (LoginException e) { - throw e; - } catch (ThreadDeath e) { - LoginException le = new LoginException( - "Spring Security login thread died"); - le.initCause(e); - throw le; - } catch (Exception e) { - LoginException le = new LoginException( - "Spring Security login failed"); - le.initCause(e); - throw le; - } - } - - @Override - public boolean logout() throws LoginException { - subject.getPrincipals(AuthorizationPrincipal.class).remove(auth); - return true; - } - - @Override - public boolean commit() throws LoginException { - subject.getPrincipals().add(auth); - if (selectedLocale != null) - LocaleUtils.threadLocale.set(selectedLocale); - return true; - } - - @Override - public boolean abort() throws LoginException { - auth = null; - selectedLocale = null; - return true; - } - - public void setAvailableLocales(String locales) { - this.availableLocales = locales; - } -} \ No newline at end of file diff --git a/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoLoginModule.java b/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoLoginModule.java index a80f26682..6d8adeb08 100644 --- a/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoLoginModule.java +++ b/org.argeo.security.jackrabbit/src/org/argeo/security/jackrabbit/ArgeoLoginModule.java @@ -24,7 +24,6 @@ import java.util.Set; import javax.jcr.Credentials; import javax.jcr.RepositoryException; import javax.jcr.Session; -import javax.jcr.SimpleCredentials; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginException; @@ -41,49 +40,16 @@ import org.springframework.security.core.context.SecurityContextHolder; public class ArgeoLoginModule extends AbstractLoginModule { private String adminRole = "ROLE_ADMIN"; - @SuppressWarnings("unused") - @Override - public boolean login() throws LoginException { - boolean loginOk = super.login(); - if (!loginOk) { - org.springframework.security.core.Authentication authen = (org.springframework.security.core.Authentication) SecurityContextHolder - .getContext().getAuthentication(); - } - return loginOk; - } - - @SuppressWarnings("unused") - @Override - public boolean commit() throws LoginException { - boolean commitOk = super.commit(); - if (!commitOk) { - org.springframework.security.core.Authentication authen = (org.springframework.security.core.Authentication) SecurityContextHolder - .getContext().getAuthentication(); - } - return commitOk; - } - /** * Returns the Spring {@link org.springframework.security.Authentication} * (which can be null) */ @Override protected Principal getPrincipal(Credentials credentials) { - org.springframework.security.core.Authentication authen = SecurityContextHolder - .getContext().getAuthentication(); - return authen; + return SecurityContextHolder.getContext().getAuthentication(); } protected Set getPrincipals() { - // clear already registered Jackrabbit principals - // clearPrincipals(AdminPrincipal.class); - // clearPrincipals(AnonymousPrincipal.class); - // clearPrincipals(GrantedAuthorityPrincipal.class); - - return syncPrincipals(); - } - - protected Set syncPrincipals() { // use linked HashSet instead of HashSet in order to maintain the order // of principals (as in the Subject). org.springframework.security.core.Authentication authen = (org.springframework.security.core.Authentication) principal; @@ -106,13 +72,10 @@ public class ArgeoLoginModule extends AbstractLoginModule { } // remove previous credentials - Set thisCredentials = subject - .getPublicCredentials(SimpleCredentials.class); - if (thisCredentials != null) - thisCredentials.clear(); - // override credentials since we did not used the one passed to us - // credentials = new SimpleCredentials(authen.getName(), authen - // .getCredentials().toString().toCharArray()); + // Set thisCredentials = subject + // .getPublicCredentials(SimpleCredentials.class); + // if (thisCredentials != null) + // thisCredentials.clear(); return principals; } @@ -128,12 +91,6 @@ public class ArgeoLoginModule extends AbstractLoginModule { clearPrincipals(ArgeoSystemPrincipal.class); clearPrincipals(AnonymousPrincipal.class); clearPrincipals(GrantedAuthorityPrincipal.class); - - // we resync with Spring Security since the subject may have been reused - // in beetween - // TODO: check if this is clean - // subject.getPrincipals().addAll(syncPrincipals()); - return true; } -- 2.30.2