You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by an...@apache.org on 2012/10/16 09:04:24 UTC

svn commit: r1398676 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/security/ main/java/org/apache/jackrabbit/oak/security/authentication/ main/java/org/apache/jackrabbit/oak/security/authentication/token/ main/java/org/ap...

Author: angela
Date: Tue Oct 16 07:04:23 2012
New Revision: 1398676

URL: http://svn.apache.org/viewvc?rev=1398676&view=rev
Log:
 OAK-91 - Implement Authentication Support (WIP)

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/UserAuthentication.java
      - copied, changed from r1397539, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationImpl.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java
Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/ConfigurationImpl.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginModuleImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/GuestLoginModule.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/SecurityProviderCallback.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/SecurityProviderImpl.java Tue Oct 16 07:04:23 2012
@@ -16,15 +16,17 @@
  */
 package org.apache.jackrabbit.oak.security;
 
+import java.util.Collections;
 import javax.annotation.Nonnull;
 import javax.jcr.Session;
+import javax.security.auth.login.AppConfigurationEntry;
 import javax.security.auth.login.Configuration;
 
 import org.apache.jackrabbit.api.security.principal.PrincipalManager;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
-import org.apache.jackrabbit.oak.security.authentication.ConfigurationImpl;
 import org.apache.jackrabbit.oak.security.authentication.LoginContextProviderImpl;
+import org.apache.jackrabbit.oak.security.authentication.LoginModuleImpl;
 import org.apache.jackrabbit.oak.security.authentication.token.TokenProviderImpl;
 import org.apache.jackrabbit.oak.security.authorization.AccessControlProviderImpl;
 import org.apache.jackrabbit.oak.security.principal.PrincipalManagerImpl;
@@ -41,14 +43,24 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.user.UserContext;
 import org.apache.jackrabbit.oak.spi.security.user.UserProvider;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class SecurityProviderImpl implements SecurityProvider {
 
+    private static final Logger log = LoggerFactory.getLogger(SecurityProviderImpl.class);
+
     @Nonnull
     @Override
     public LoginContextProvider getLoginContextProvider(NodeStore nodeStore) {
-        // TODO: use configurable authentication config
-        Configuration configuration = new ConfigurationImpl();
+        Configuration configuration;
+        try {
+            configuration = Configuration.getConfiguration();
+        } catch (SecurityException e) {
+            log.warn("Failed to read login configuration: using default.", e);
+            configuration = new OakConfiguration();
+            Configuration.setConfiguration(configuration);
+        }
         return new LoginContextProviderImpl(configuration, nodeStore, this);
     }
 
@@ -91,4 +103,17 @@ public class SecurityProviderImpl implem
             }
         };
     }
+
+    //--------------------------------------------------------------------------
+    private class OakConfiguration extends Configuration {
+
+        @Override
+        public AppConfigurationEntry[] getAppConfigurationEntry(String s) {
+            AppConfigurationEntry entry = new AppConfigurationEntry(
+                    LoginModuleImpl.class.getName(),
+                    AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
+                    Collections.<String, Object>emptyMap());
+            return new AppConfigurationEntry[] {entry};
+        }
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImpl.java Tue Oct 16 07:04:23 2012
@@ -27,12 +27,9 @@ import javax.security.auth.callback.Unsu
 
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback;
-import org.apache.jackrabbit.oak.spi.security.authentication.callback.PrincipalProviderCallback;
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback;
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.SecurityProviderCallback;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Default implementation of the {@link CallbackHandler} interface. It currently
@@ -42,16 +39,12 @@ import org.slf4j.LoggerFactory;
  *     <li>{@link CredentialsCallback}</li>
  *     <li>{@link NameCallback}</li>
  *     <li>{@link PasswordCallback}</li>
- *     <li>{@link PrincipalProviderCallback}</li>
+ *     <li>{@link SecurityProviderCallback}</li>
+ *     <li>{@link RepositoryCallback}</li>
  * </ul>
  */
 public class CallbackHandlerImpl implements CallbackHandler {
 
-    /**
-     * logger instance
-     */
-    private static final Logger log = LoggerFactory.getLogger(CallbackHandlerImpl.class);
-
     private final Credentials credentials;
     private final String workspaceName;
     private final NodeStore nodeStore;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginModuleImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginModuleImpl.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginModuleImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginModuleImpl.java Tue Oct 16 07:04:23 2012
@@ -28,7 +28,6 @@ import javax.jcr.GuestCredentials;
 import javax.jcr.SimpleCredentials;
 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.UnsupportedCallbackException;
 import javax.security.auth.login.LoginException;
@@ -104,10 +103,6 @@ public final class LoginModuleImpl exten
     private String userId;
 
     //--------------------------------------------------------< LoginModule >---
-    @Override
-    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
-        super.initialize(subject, callbackHandler, sharedState, options);
-    }
 
     @Override
     public boolean login() throws LoginException {
@@ -119,7 +114,7 @@ public final class LoginModuleImpl exten
             return false;
         }
 
-        Authentication authentication = new AuthenticationImpl(userId, getUserProvider(), getPrincipalProvider());
+        Authentication authentication = new UserAuthentication(userId, getUserProvider(), getPrincipalProvider());
         boolean success = authentication.authenticate(credentials);
         if (success) {
             principals = getPrincipals(userId);

Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/UserAuthentication.java (from r1397539, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationImpl.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/UserAuthentication.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/UserAuthentication.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationImpl.java&r1=1397539&r2=1398676&rev=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/UserAuthentication.java Tue Oct 16 07:04:23 2012
@@ -38,15 +38,15 @@ import org.slf4j.LoggerFactory;
 /**
  * AuthenticationImpl...
  */
-public class AuthenticationImpl implements Authentication {
+public class UserAuthentication implements Authentication {
 
-    private static final Logger log = LoggerFactory.getLogger(AuthenticationImpl.class);
+    private static final Logger log = LoggerFactory.getLogger(UserAuthentication.class);
 
     private final String userId;
     private final UserProvider userProvider;
     private final PrincipalProvider principalProvider;
 
-    public AuthenticationImpl(String userId, UserProvider userProvider, PrincipalProvider principalProvider) {
+    public UserAuthentication(String userId, UserProvider userProvider, PrincipalProvider principalProvider) {
         this.userId = userId;
         this.userProvider = userProvider;
         this.principalProvider = principalProvider;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenLoginModule.java Tue Oct 16 07:04:23 2012
@@ -98,6 +98,7 @@ public final class TokenLoginModule exte
         // the login attempt on this module did not succeed: clear state
         // and check if another successful login asks for a new token to be created.
         clearState();
+
         if (tokenProvider != null && sharedState.containsKey(SHARED_KEY_CREDENTIALS)) {
             Credentials shared = getSharedCredentials();
             if (shared != null && tokenProvider.doCreateToken(shared)) {

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=1398676&r1=1398675&r2=1398676&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 Tue Oct 16 07:04:23 2012
@@ -39,6 +39,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.PrincipalProviderCallback;
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback;
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.SecurityProviderCallback;
+import org.apache.jackrabbit.oak.spi.security.authentication.callback.UserProviderCallback;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
 import org.apache.jackrabbit.oak.spi.security.user.UserProvider;
 import org.slf4j.Logger;
@@ -53,71 +54,80 @@ import org.slf4j.LoggerFactory;
  * This base class provides a simple implementation for the following methods
  * of the {@code LoginModule} interface:
  *
- * <h3>{@link LoginModule#initialize(Subject, CallbackHandler, Map, Map) Initialize}</h3>
- * Initialization of this abstract module sets the following protected instance
- * fields:
  * <ul>
- *     <li>subject: The subject to be authenticated,</li>
- *     <li>callbackHandler: The callback handler passed to the login module,</li>
- *     <li>shareState: The map used to share state information with other login
- *     modules,</li>
- *     <li>options: The configuration options of this login module as specified
- *     in the {@link javax.security.auth.login.Configuration}.</li>
+ *     <li>{@link LoginModule#initialize(Subject, CallbackHandler, Map, Map) Initialize}:
+ *     Initialization of this abstract module sets the following protected instance
+ *     fields:
+ *     <ul>
+ *         <li>subject: The subject to be authenticated,</li>
+ *         <li>callbackHandler: The callback handler passed to the login module,</li>
+ *         <li>shareState: The map used to share state information with other login modules,</li>
+ *         <li>options: The configuration options of this login module as specified
+ *         in the {@link javax.security.auth.login.Configuration}.</li>
+ *     </ul>
+ *     </li>
+ *     <li>{@link LoginModule#logout() Logout}:
+ *     If the authenticated subject is not empty this logout implementation
+ *     attempts to clear both principals and public credentials and returns
+ *     {@code true}.</li>
+ *     <li>{@link LoginModule#abort() Abort}: Clears the state of this login
+ *     module by setting all private instance variables created in phase 1 or 2
+ *     to {@code null}. Subclasses are in charge of releasing their own state
+ *     information by either overriding {@link #clearState()}.</li>
  * </ul>
  *
- * <h3>{@link LoginModule#logout() Logout}</h3>
- * If the authenticated subject is not empty this logout implementation attempts
- * to clear both principals and public credentials and returns {@code true}.
- *
- * <h3>{@link LoginModule#abort() Abort}</h3>
- * Clears the state of this login module by setting all private instance
- * variables created in phase 1 or 2 to {@code null}. Subclasses are in charge of
- * releasing their own state information by either overriding {@link #clearState()}.
- *
  * <h2>Utility Methods</h2>
  * The following methods are provided in addition:
  *
- * <h3>{@link #clearState()}</h3>
- * Clears all private state information that has be created during login. This
- * method in called in {@link #abort()} and subclasses are expected to override
- * this method.
- *
- * <h3>{@link #getSupportedCredentials()}</h3>
- * Abstract method used by {@link #getCredentials()} that reveals which credential
- * implementations are supported by the {@code LoginModule}.
- *
- * <h3>{@link #getCredentials()}</h3>
- * Tries to retrieve valid (supported) Credentials in the following order:
- * <ol>
+ * <ul>
+ *     <li>{@link #clearState()}: Clears all private state information that has
+ *     be created during login. This method in called in {@link #abort()} and
+ *     subclasses are expected to override this method.</li>
+ *
+ *     <li>{@link #getSupportedCredentials()}: Abstract method used by
+ *     {@link #getCredentials()} that reveals which credential implementations
+ *     are supported by the {@code LoginModule}.</li>
+ *
+ *     <li>{@link #getCredentials()}: Tries to retrieve valid (supported)
+ *     Credentials in the following order:
+ *     <ol>
  *     <li>using a {@link CredentialsCallback},</li>
  *     <li>looking for a {@link #SHARED_KEY_CREDENTIALS} entry in the shared
  *     state (see also {@link #getSharedCredentials()} and finally by</li>
  *     <li>searching for valid credentials in the subject.</li>
- * </ol>
- *
- * <h3>{@link #getSharedCredentials()}</h3>
- * This method returns any credentials passed to the login module with the
- * share state. The key to share credentials with a another module extending from
- * this base class is {@link #SHARED_KEY_CREDENTIALS}.
- *
- * <h3>{@link #getSharedLoginName()}</h3>
- * If the shared state contains an entry for {@link #SHARED_KEY_LOGIN_NAME} this
- * method returns the value as login name.
- *
- * <h3>{@link #getPrincipals(String)}</h3>
- * Returns all principals associated with a given user id. This method should
- * be called after a successful authentication in order to be able to populate
- * the subject during {@link #commit()}.
- *
- * <h3>{@link #getPrincipalProvider()}</h3>
- * // TODO
- * <h3>{@link #getUserProvider()}</h3>
- * // TODO
- * <h3>{@link #getSecurityProvider()}</h3>
- * // TODO
- * <h3>{@link #getRoot()}</h3>
- * // TODO
+ *     </ol></li>
  *
+ *     <li>{@link #getSharedCredentials()}: This method returns credentials
+ *     passed to the login module with the share state. The key to share credentials
+ *     with a another module extending from this base class is
+ *     {@link #SHARED_KEY_CREDENTIALS}. Note, that this method does not verify
+ *     if the credentials provided by the shared state are
+ *     {@link #getSupportedCredentials() supported}.</li>
+ *
+ *     <li>{@link #getSharedLoginName()}: If the shared state contains an entry
+ *     for {@link #SHARED_KEY_LOGIN_NAME} this method returns the value as login name.</li>
+ *
+ *     <li>{@link #getSecurityProvider()}: Returns the configured security
+ *     provider or {@code null}.</li>
+ *
+ *     <li>{@link #getRoot()}: Provides access to the latest state of the
+ *     repository in order to retrieve user or principal information required to
+ *     authenticate the subject as well as to write back information during
+ *     {@link #commit()}.</li>
+ *
+ *     <li>{@link #getUserProvider()}: Returns an instance of the configured
+ *     {@link UserProvider} or {@code null}.</li>
+ *
+ *     <li>{@link #getPrincipalProvider()}: Returns an instance of the configured
+ *     principal provider or {@code null}.</li>
+ *
+ *     <li>{@link #getPrincipals(String)}: Utility that returns all principals
+ *     associated with a given user id. This method might be be called after
+ *     successful authentication in order to be able to populate the subject
+ *     during {@link #commit()}. The implementation is a shortcut for calling
+ *     {@link PrincipalProvider#getPrincipals(String) getPrincipals(String userId}
+ *     on the provider exposed by {@link #getPrincipalProvider()}</li>
+ * </ul>
  */
 public abstract class AbstractLoginModule implements LoginModule {
 
@@ -166,7 +176,6 @@ public abstract class AbstractLoginModul
             }
             success = true;
         }
-        // TODO: check if state should be cleared
         return success;
     }
 
@@ -185,10 +194,23 @@ public abstract class AbstractLoginModul
         root = null;
     }
 
+    /**
+     * @return A set of supported credential classes.
+     */
     @Nonnull
     protected abstract Set<Class> getSupportedCredentials();
 
-
+    /**
+     * Tries to retrieve valid (supported) Credentials:
+     * <ol>
+     *     <li>using a {@link CredentialsCallback},</li>
+     *     <li>looking for a {@link #SHARED_KEY_CREDENTIALS} entry in the
+     *     shared state (see also {@link #getSharedCredentials()} and finally by</li>
+     *     <li>searching for valid credentials in the subject.</li>
+     *  </ol>
+     *
+     * @return Valid (supported) credentials or {@code null}.
+     */
     @CheckForNull
     protected Credentials getCredentials() {
         Set<Class> supported = getSupportedCredentials();
@@ -230,6 +252,10 @@ public abstract class AbstractLoginModul
         return null;
     }
 
+    /**
+     * @return The credentials passed to this login module with the shared state.
+     * @see #SHARED_KEY_CREDENTIALS
+     */
     @CheckForNull
     protected Credentials getSharedCredentials() {
         Credentials shared = null;
@@ -245,90 +271,106 @@ public abstract class AbstractLoginModul
         return shared;
     }
 
+    /**
+     * @return The login name passed to this login module with the shared state.
+     * @see #SHARED_KEY_LOGIN_NAME
+     */
     @CheckForNull
     protected String getSharedLoginName() {
         if (sharedState.containsKey(SHARED_KEY_LOGIN_NAME)) {
-            return (String) sharedState.get(SHARED_KEY_LOGIN_NAME);
+            return sharedState.get(SHARED_KEY_LOGIN_NAME).toString();
         } else {
             return null;
         }
     }
 
+    @CheckForNull
+    protected SecurityProvider getSecurityProvider() {
+        if (securityProvider == null && callbackHandler != null) {
+            SecurityProviderCallback scb = new SecurityProviderCallback();
+            try {
+                callbackHandler.handle(new Callback[] {scb});
+                securityProvider = scb.getSecurityProvider();
+            } catch (UnsupportedCallbackException e) {
+                log.debug(e.getMessage());
+            } catch (IOException e) {
+                log.debug(e.getMessage());
+            }
+        }
+        return securityProvider;
+    }
 
-    @Nonnull
-    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);
+    @CheckForNull
+    protected Root getRoot() {
+        if (root == null && callbackHandler != null) {
+            RepositoryCallback rcb = new RepositoryCallback();
+            try {
+                callbackHandler.handle(new Callback[] {rcb});
+                root = rcb.getRoot();
+            } catch (UnsupportedCallbackException e) {
+                log.debug(e.getMessage());
+            } catch (IOException e) {
+                log.debug(e.getMessage());
+            }
         }
+        return root;
     }
 
     @CheckForNull
-    protected PrincipalProvider getPrincipalProvider() {
-        PrincipalProvider principalProvider = null;
+    protected UserProvider getUserProvider() {
+        UserProvider userProvider = null;
         SecurityProvider sp = getSecurityProvider();
         Root root = getRoot();
         if (root != null && sp != null) {
-            principalProvider = sp.getPrincipalConfiguration().getPrincipalProvider(root, NamePathMapper.DEFAULT);
+            userProvider = sp.getUserContext().getUserProvider(root);
         }
 
-        if (principalProvider == null && callbackHandler != null) {
+        if (userProvider == null && callbackHandler != null) {
             try {
-                PrincipalProviderCallback principalCallBack = new PrincipalProviderCallback();
-                callbackHandler.handle(new Callback[] {principalCallBack});
-                principalProvider = principalCallBack.getPrincipalProvider();
+                UserProviderCallback userCallBack = new UserProviderCallback();
+                callbackHandler.handle(new Callback[] {userCallBack});
+                userProvider = userCallBack.getUserProvider();
             } catch (IOException e) {
                 log.debug(e.getMessage());
             } catch (UnsupportedCallbackException e) {
                 log.debug(e.getMessage());
             }
         }
-        return principalProvider;
+
+        return userProvider;
     }
 
     @CheckForNull
-    protected UserProvider getUserProvider() {
+    protected PrincipalProvider getPrincipalProvider() {
+        PrincipalProvider principalProvider = null;
         SecurityProvider sp = getSecurityProvider();
         Root root = getRoot();
         if (root != null && sp != null) {
-            return sp.getUserContext().getUserProvider(root);
-        } else {
-            return null;
+            principalProvider = sp.getPrincipalConfiguration().getPrincipalProvider(root, NamePathMapper.DEFAULT);
         }
-    }
 
-    @CheckForNull
-    protected SecurityProvider getSecurityProvider() {
-        if (securityProvider == null && callbackHandler != null) {
-            SecurityProviderCallback scb = new SecurityProviderCallback();
+        if (principalProvider == null && callbackHandler != null) {
             try {
-                callbackHandler.handle(new Callback[] {scb});
-                securityProvider = scb.getSecurityProvider();
-            } catch (UnsupportedCallbackException e) {
-                log.debug(e.getMessage());
+                PrincipalProviderCallback principalCallBack = new PrincipalProviderCallback();
+                callbackHandler.handle(new Callback[] {principalCallBack});
+                principalProvider = principalCallBack.getPrincipalProvider();
             } catch (IOException e) {
                 log.debug(e.getMessage());
+            } catch (UnsupportedCallbackException e) {
+                log.debug(e.getMessage());
             }
         }
-        return securityProvider;
+        return principalProvider;
     }
 
-    @CheckForNull
-    protected Root getRoot() {
-        if (root == null && callbackHandler != null) {
-            RepositoryCallback rcb = new RepositoryCallback();
-            try {
-                callbackHandler.handle(new Callback[] {rcb});
-                root = rcb.getRoot();
-            } catch (UnsupportedCallbackException e) {
-                log.debug(e.getMessage());
-            } catch (IOException e) {
-                log.debug(e.getMessage());
-            }
+    @Nonnull
+    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 root;
     }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/GuestLoginModule.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/GuestLoginModule.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/GuestLoginModule.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/GuestLoginModule.java Tue Oct 16 07:04:23 2012
@@ -24,7 +24,6 @@ import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
 import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.LoginException;
 import javax.security.auth.spi.LoginModule;
 
 import org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback;
@@ -73,7 +72,7 @@ import org.slf4j.LoggerFactory;
  * In this case calling {@link javax.jcr.Repository#login()} would be equivalent
  * to {@link javax.jcr.Repository#login(javax.jcr.Credentials) repository.login(new GuestCredentials()}.
  */
-public class GuestLoginModule implements LoginModule {
+public final class GuestLoginModule implements LoginModule {
 
     private static final Logger log = LoggerFactory.getLogger(GuestLoginModule.class);
 
@@ -92,7 +91,7 @@ public class GuestLoginModule implements
     }
 
     @Override
-    public boolean login() throws LoginException {
+    public boolean login() {
         if (callbackHandler != null) {
             CredentialsCallback ccb = new CredentialsCallback();
             try {
@@ -115,7 +114,7 @@ public class GuestLoginModule implements
     }
 
     @Override
-    public boolean commit() throws LoginException {
+    public boolean commit() {
         if (guestCredentials != null && !subject.isReadOnly()) {
             subject.getPublicCredentials().add(guestCredentials);
             subject.getPrincipals().add(EveryonePrincipal.getInstance());
@@ -124,13 +123,13 @@ public class GuestLoginModule implements
     }
 
     @Override
-    public boolean abort() throws LoginException {
-        // nothing to do
+    public boolean abort() {
+        guestCredentials = null;
         return true;
     }
 
     @Override
-    public boolean logout() throws LoginException {
+    public boolean logout() {
         // nothing to do.
         return true;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java Tue Oct 16 07:04:23 2012
@@ -30,7 +30,10 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * RepositoryCallback... TODO
+ * Callback implementation used to access the repository. It allows to set and
+ * get the {@code NodeStore} and the name of the workspace for which the login
+ * applies. In addition it provides access to a {@link Root} object based on
+ * the given node store and workspace name.
  */
 public class RepositoryCallback implements Callback {
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/SecurityProviderCallback.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/SecurityProviderCallback.java?rev=1398676&r1=1398675&r2=1398676&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/SecurityProviderCallback.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/SecurityProviderCallback.java Tue Oct 16 07:04:23 2012
@@ -22,7 +22,7 @@ import javax.security.auth.callback.Call
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 
 /**
- * SecurityProviderCallback... TODO
+ * Callback implementation to set and get the {@link SecurityProvider}.
  */
 public class SecurityProviderCallback implements Callback {
 

Added: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java?rev=1398676&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java Tue Oct 16 07:04:23 2012
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.jackrabbit.oak.spi.security.authentication;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.jcr.Credentials;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.LoginException;
+
+import org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback;
+import org.junit.Test;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertTrue;
+
+/**
+ * AbstractLoginModuleTest...
+ */
+public class AbstractLoginModuleTest {
+
+    private AbstractLoginModule initLoginModule(Class supportedCredentials, Map sharedState) {
+        AbstractLoginModule lm = new TestLoginModule(supportedCredentials);
+        lm.initialize(new Subject(), null, sharedState, null);
+        return lm;
+    }
+
+
+    private AbstractLoginModule initLoginModule(Class supportedCredentials, CallbackHandler cbh) {
+        AbstractLoginModule lm = new TestLoginModule(supportedCredentials);
+        lm.initialize(new Subject(), cbh, Collections.<String, Object>emptyMap(), null);
+        return lm;
+    }
+
+    @Test
+    public void testGetSharedLoginName() {
+        Map<String, String> sharedState = new HashMap<String, String>();
+
+        sharedState.put(AbstractLoginModule.SHARED_KEY_LOGIN_NAME, "test");
+        AbstractLoginModule lm = initLoginModule(TestCredentials.class, sharedState);
+        assertEquals("test", lm.getSharedLoginName());
+
+        sharedState.clear();
+        lm = initLoginModule(TestCredentials.class, sharedState);
+        assertNull(lm.getSharedLoginName());
+    }
+
+    @Test
+    public void testGetSharedCredentials() {
+        Map<String, Object> sharedState = new HashMap<String, Object>();
+
+        sharedState.put(AbstractLoginModule.SHARED_KEY_CREDENTIALS, new TestCredentials());
+        AbstractLoginModule lm = initLoginModule(TestCredentials.class, sharedState);
+        assertTrue(lm.getSharedCredentials() instanceof TestCredentials);
+
+        sharedState.put(AbstractLoginModule.SHARED_KEY_CREDENTIALS, new SimpleCredentials("test", "test".toCharArray()));
+        lm = initLoginModule(TestCredentials.class, sharedState);
+        assertTrue(lm.getSharedCredentials() instanceof SimpleCredentials);
+
+        lm = initLoginModule(SimpleCredentials.class, sharedState);
+        assertTrue(lm.getSharedCredentials() instanceof SimpleCredentials);
+
+        sharedState.put(AbstractLoginModule.SHARED_KEY_CREDENTIALS, "no credentials object");
+        lm = initLoginModule(TestCredentials.class, sharedState);
+        assertNull(lm.getSharedCredentials());
+
+        sharedState.clear();
+        lm = initLoginModule(TestCredentials.class, sharedState);
+        assertNull(lm.getSharedCredentials());
+    }
+
+    @Test
+    public void testGetCredentialsFromSharedState() {
+        Map<String, Credentials> sharedState = new HashMap<String, Credentials>();
+
+        sharedState.put(AbstractLoginModule.SHARED_KEY_CREDENTIALS, new TestCredentials());
+        AbstractLoginModule lm = initLoginModule(TestCredentials.class, sharedState);
+        assertTrue(lm.getCredentials() instanceof TestCredentials);
+
+        SimpleCredentials sc = new SimpleCredentials("test", "test".toCharArray());
+        sharedState.put(AbstractLoginModule.SHARED_KEY_CREDENTIALS, sc);
+        lm = initLoginModule(TestCredentials.class, sharedState);
+        assertNull(lm.getCredentials());
+
+        sharedState.put(AbstractLoginModule.SHARED_KEY_CREDENTIALS, sc);
+        lm = initLoginModule(SimpleCredentials.class, sharedState);
+        assertTrue(lm.getCredentials() instanceof SimpleCredentials);
+
+        sharedState.clear();
+        lm = initLoginModule(TestCredentials.class, sharedState);
+        assertNull(lm.getCredentials());
+    }
+
+    public void testGetCredentialsFromCallbackHandler() {
+        CallbackHandler cbh = new CallbackHandler() {
+            @Override
+            public void handle(Callback[] callbacks) {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof CredentialsCallback) {
+                        ((CredentialsCallback) cb).setCredentials(new TestCredentials());
+                    }
+                }
+            }
+        };
+
+        AbstractLoginModule lm = initLoginModule(TestCredentials.class, cbh);
+        assertTrue(lm.getCredentials() instanceof TestCredentials);
+
+        lm = initLoginModule(SimpleCredentials.class, cbh);
+        assertNull(lm.getCredentials());
+    }
+
+    //--------------------------------------------------------------------------
+
+    private final class TestCredentials implements Credentials {}
+
+    private final class TestLoginModule extends AbstractLoginModule {
+
+        private Class supportedCredentialsClass;
+
+        private TestLoginModule(Class supportedCredentialsClass) {
+            this.supportedCredentialsClass = supportedCredentialsClass;
+        }
+
+        @Nonnull
+        @Override
+        protected Set<Class> getSupportedCredentials() {
+            return Collections.singleton(supportedCredentialsClass);
+        }
+
+        @Override
+        public boolean login() throws LoginException {
+            return true;
+        }
+
+        @Override
+        public boolean commit() throws LoginException {
+            return true;
+        }
+    }
+}
\ No newline at end of file