Author: angela Date: Wed Oct 31 15:09:27 2012 New Revision: 1404185 URL: http://svn.apache.org/viewvc?rev=1404185&view=rev Log: OAK-91 - Implement Authentication Support (WIP)
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/DefaultLoginModuleTest.java Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java?rev=1404185&r1=1404184&r2=1404185&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/LoginModuleImpl.java Wed Oct 31 15:09:27 2012 @@ -72,22 +72,24 @@ import org.slf4j.LoggerFactory; * <li>{@link ImpersonationCredentials}</li> * </ul> * - * The {@link Credentials} obtained during the {@link #login()} are added to - * the shared state and - upon successful {@link #commit()} to the {@link Subject}. + * The {@link Credentials} obtained during the {@code #login()} are added to + * the shared state and - upon successful {@code #commit()} to the {@code Subject}. * * <h3>Principals</h3> - * - * TODO - * - principal lookup -> principal provider - * - principal resolution based on credentials + * Upon successful login the principals associated with the user are calculated + * (see also {@link AbstractLoginModule#getPrincipals(String)}. These principals + * are finally added to the subject during {@code #commit()}. * * <h3>Impersonation</h3> - * - * TODO - * - * - * - * + * Impersonation such as defined by {@link javax.jcr.Session#impersonate(javax.jcr.Credentials)} + * is covered by this login module by the means of {@link ImpersonationCredentials}. + * Impersonation will succeed if the {@link ImpersonationCredentials#getBaseCredentials() base credentials} + * refer to a valid user that has not been disabled. If the authenticating + * subject is not allowed to impersonate the specified user, the login attempt + * will fail with {@code LoginException}.<p/> + * Please note, that a user will always be allowed to impersonate him/herself + * irrespective of the impersonation definitions exposed by + * {@link org.apache.jackrabbit.api.security.user.User#getImpersonation()} */ public final class LoginModuleImpl extends AbstractLoginModule { @@ -116,7 +118,7 @@ public final class LoginModuleImpl exten return false; } - Authentication authentication = new UserAuthentication(userId, getUserManager(), getPrincipalProvider()); + Authentication authentication = new UserAuthentication(userId, getUserManager()); boolean success = authentication.authenticate(credentials); if (success) { principals = getPrincipals(userId); Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java?rev=1404185&r1=1404184&r2=1404185&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/user/UserAuthentication.java Wed Oct 31 15:09:27 2012 @@ -31,7 +31,6 @@ import org.apache.jackrabbit.oak.api.Aut import org.apache.jackrabbit.oak.security.user.CredentialsImpl; import org.apache.jackrabbit.oak.spi.security.authentication.Authentication; import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials; -import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider; import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtility; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -63,12 +62,10 @@ class UserAuthentication implements Auth private final String userId; private final UserManager userManager; - private final PrincipalProvider principalProvider; - UserAuthentication(String userId, UserManager userManager, PrincipalProvider principalProvider) { + UserAuthentication(String userId, UserManager userManager) { this.userId = userId; this.userManager = userManager; - this.principalProvider = principalProvider; } @Override @@ -120,9 +117,15 @@ class UserAuthentication implements Auth } private boolean impersonate(AuthInfo info, User user) { - Subject subject = new Subject(true, info.getPrincipals(), Collections.emptySet(), Collections.emptySet()); try { - return user.getImpersonation().allows(subject); + if (info.getUserID().equals(user.getID())) { + log.debug("User " + info.getUserID() + " wants to impersonate himself -> success."); + return true; + } else { + log.debug("User " + info.getUserID() + " wants to impersonate " + user.getID()); + Subject subject = new Subject(true, info.getPrincipals(), Collections.emptySet(), Collections.emptySet()); + return user.getImpersonation().allows(subject); + } } catch (RepositoryException e) { log.debug("Error while validating impersonation", e.getMessage()); } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java?rev=1404185&r1=1404184&r2=1404185&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java Wed Oct 31 15:09:27 2012 @@ -363,14 +363,22 @@ public abstract class AbstractLoginModul return principalProvider; } + /** + * Retrieves all principals associated with the specified {@code userId} for + * the configured principal provider. + * + * @param userId The id of the user. + * @return The set of principals associated with the given {@code userId}. + * @see #getPrincipalProvider() + */ @Nonnull - protected Set<? extends Principal> getPrincipals(String userID) { + protected Set<? extends Principal> getPrincipals(String userId) { PrincipalProvider principalProvider = getPrincipalProvider(); if (principalProvider == null) { log.debug("Cannot retrieve principals. No principal provider configured."); return Collections.emptySet(); } else { - return principalProvider.getPrincipals(userID); + return principalProvider.getPrincipals(userId); } } } Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/DefaultLoginModuleTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/DefaultLoginModuleTest.java?rev=1404185&r1=1404184&r2=1404185&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/DefaultLoginModuleTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/DefaultLoginModuleTest.java Wed Oct 31 15:09:27 2012 @@ -32,6 +32,7 @@ import org.apache.jackrabbit.oak.api.Roo import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.security.AbstractSecurityTest; import org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl; +import org.apache.jackrabbit.oak.spi.security.authentication.ImpersonationCredentials; import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; import org.apache.jackrabbit.oak.spi.security.user.util.UserUtility; @@ -149,4 +150,81 @@ public class DefaultLoginModuleTest exte } } + @Test + public void testSelfImpersonation() throws Exception { + Root root = admin.getLatestRoot(); + UserManager userManager = uc.getUserManager(root, NamePathMapper.DEFAULT); + + ContentSession cs = null; + User user = null; + try { + user = userManager.createUser("test", "pw"); + root.commit(); + + SimpleCredentials sc = new SimpleCredentials("test", "pw".toCharArray()); + cs = login(sc); + + AuthInfo authInfo = cs.getAuthInfo(); + assertEquals("test", authInfo.getUserID()); + + cs.close(); + + sc = new SimpleCredentials("test", new char[0]); + ImpersonationCredentials ic = new ImpersonationCredentials(sc, authInfo); + cs = login(ic); + + authInfo = cs.getAuthInfo(); + assertEquals("test", authInfo.getUserID()); + } finally { + if (user != null) { + user.remove(); + root.commit(); + } + if (cs != null) { + cs.close(); + } + } + } + + @Test + public void testInvalidImpersonation() throws Exception { + Root root = admin.getLatestRoot(); + UserManager userManager = uc.getUserManager(root, NamePathMapper.DEFAULT); + + ContentSession cs = null; + User user = null; + try { + user = userManager.createUser("test", "pw"); + root.commit(); + + SimpleCredentials sc = new SimpleCredentials("test", "pw".toCharArray()); + cs = login(sc); + + AuthInfo authInfo = cs.getAuthInfo(); + assertEquals("test", authInfo.getUserID()); + + cs.close(); + cs = null; + + String adminId = UserUtility.getAdminId(securityProvider.getUserConfiguration().getConfigurationParameters()); + sc = new SimpleCredentials(adminId, new char[0]); + ImpersonationCredentials ic = new ImpersonationCredentials(sc, authInfo); + + try { + cs = login(ic); + fail("User 'test' should not be allowed to impersonate " + adminId); + } catch (LoginException e) { + // success + } + } finally { + if (user != null) { + user.remove(); + root.commit(); + } + if (cs != null) { + cs.close(); + } + } + } + }