Author: stillalex
Date: Thu Mar  7 14:15:14 2019
New Revision: 1854982

URL: http://svn.apache.org/viewvc?rev=1854982&view=rev
Log:
OAK-8102 LoginModule error metrics


Added:
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java
   (with props)
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java
   (with props)
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java
   (with props)
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java
   (with props)
    
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java
   (with props)
    jackrabbit/oak/trunk/oak-security-spi/src/test/resources/
    jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml   
(with props)
Modified:
    
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
    
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
    
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
    
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.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/LoginContextProviderImpl.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/security/authentication/token/TokenProviderImpl.java
    
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/internal/SecurityProviderRegistration.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java
    jackrabbit/oak/trunk/oak-security-spi/pom.xml
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java
    
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
    
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java

Modified: 
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-auth-external/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/external/impl/ExternalLoginModule.java
 Thu Mar  7 14:15:14 2019
@@ -246,12 +246,14 @@ public class ExternalLoginModule extends
             }
         } catch (ExternalIdentityException e) {
             log.error("Error while authenticating '{}' with {}", logId, 
idp.getName(), e);
+            onError();
             return false;
         } catch (LoginException e) {
             log.debug("IDP {} throws login exception for '{}': {}", 
idp.getName(), logId, e.getMessage());
             throw e;
-        } catch (Exception e) {
-            log.debug("SyncHandler {} throws sync exception for '{}'", 
syncHandler.getName(), logId, e);
+        } catch (SyncException | RepositoryException e) {
+            onError();
+            log.error("SyncHandler {} throws sync exception for '{}'", 
syncHandler.getName(), logId, e);
             LoginException le = new LoginException("Error while syncing 
user.");
             le.initCause(e);
             throw le;

Modified: 
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java
 Thu Mar  7 14:15:14 2019
@@ -488,7 +488,7 @@ public class BenchmarkRunner {
             // benchmarks for oak-auth-external
                 new ExternalLoginTest(numberOfUsers.value(options), 
numberOfGroups.value(options),
                         expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options),
-                        report.value(options)),
+                        report.value(options), statsProvider),
             new SyncAllExternalUsersTest(numberOfUsers.value(options), 
numberOfGroups.value(options), expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options)),
             new SyncAllUsersTest(numberOfUsers.value(options), 
numberOfGroups.value(options), expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options)),
             new SyncExternalUsersTest(numberOfUsers.value(options), 
numberOfGroups.value(options), expiration.value(options), 
dynamicMembership.value(options), autoMembership.values(options), 
batchSize.value(options)),

Modified: 
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-benchmarks/src/main/java/org/apache/jackrabbit/oak/benchmark/authentication/external/ExternalLoginTest.java
 Thu Mar  7 14:15:14 2019
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.oak.benchmark.authentication.external;
 
+import static 
javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
+import static 
javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
+
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -24,16 +27,17 @@ import javax.jcr.SimpleCredentials;
 import javax.security.auth.login.AppConfigurationEntry;
 import javax.security.auth.login.Configuration;
 
-import com.google.common.collect.ImmutableMap;
-
 import 
org.apache.jackrabbit.oak.security.authentication.token.TokenLoginModule;
 import org.apache.jackrabbit.oak.security.authentication.user.LoginModuleImpl;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
 import org.apache.jackrabbit.oak.spi.security.authentication.GuestLoginModule;
+import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStats;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStatsCollector;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModule;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
 import org.jetbrains.annotations.NotNull;
 
-import static 
javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.SUFFICIENT;
-import static 
javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL;
+import com.google.common.collect.ImmutableMap;
 
 /**
  * Login against the {@link ExternalLoginModule} with a randomly selected user.
@@ -48,16 +52,18 @@ public class ExternalLoginTest extends A
     private final int numberOfUsers;
     private final int numberOfGroups;
     private final Reporter reporter;
+    private final LoginModuleStats lmStats;
 
     private String id;
     private Set<String> uniques;
 
-    public ExternalLoginTest(int numberOfUsers, int numberOfGroups, long 
expTime,
-                             boolean dynamicMembership, @NotNull List<String> 
autoMembership, boolean report) {
+    public ExternalLoginTest(int numberOfUsers, int numberOfGroups, long 
expTime, boolean dynamicMembership,
+            @NotNull List<String> autoMembership, boolean report, 
StatisticsProvider statsProvider) {
         super(numberOfUsers, numberOfGroups, expTime, dynamicMembership, 
autoMembership);
         this.numberOfUsers = numberOfUsers;
         this.numberOfGroups = numberOfGroups;
         this.reporter = new Reporter(report);
+        this.lmStats = new LoginModuleStats(statsProvider);
     }
 
     @Override
@@ -65,6 +71,11 @@ public class ExternalLoginTest extends A
         super.beforeSuite();
         reporter.beforeSuite();
         uniques = new HashSet<>(numberOfUsers);
+        AuthenticationConfiguration authenticationConfiguration = 
getSecurityProvider()
+                .getConfiguration(AuthenticationConfiguration.class);
+        if (authenticationConfiguration instanceof LoginModuleStatsCollector) {
+            ((LoginModuleStatsCollector) 
authenticationConfiguration).setLoginModuleMonitor(lmStats);
+        }
     }
 
     @Override

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/AuthenticationConfigurationImpl.java
 Thu Mar  7 14:15:14 2019
@@ -24,6 +24,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStatsCollector;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAware;
 import org.jetbrains.annotations.NotNull;
@@ -49,7 +51,7 @@ import org.slf4j.LoggerFactory;
  */
 @Component(service = {AuthenticationConfiguration.class, 
SecurityConfiguration.class})
 @Designate(ocd = AuthenticationConfigurationImpl.Configuration.class)
-public class AuthenticationConfigurationImpl extends ConfigurationBase 
implements AuthenticationConfiguration {
+public class AuthenticationConfigurationImpl extends ConfigurationBase 
implements AuthenticationConfiguration, LoginModuleStatsCollector {
 
     @ObjectClassDefinition(name = "Apache Jackrabbit Oak 
AuthenticationConfiguration")
     @interface Configuration {
@@ -71,6 +73,9 @@ public class AuthenticationConfiguration
 
     private static final Logger log = 
LoggerFactory.getLogger(AuthenticationConfigurationImpl.class);
 
+    // stats
+    private LoginModuleMonitor lmMonitor = LoginModuleMonitor.NOOP;
+
     /**
      * Constructor for OSGi
      */
@@ -137,6 +142,12 @@ public class AuthenticationConfiguration
         } else {
             log.warn("Unable to obtain whiteboard from SecurityProvider");
         }
-        return new LoginContextProviderImpl(appName, getParameters(), 
contentRepository, getSecurityProvider(), whiteboard);
+        return new LoginContextProviderImpl(appName, getParameters(), 
contentRepository, getSecurityProvider(),
+                whiteboard, lmMonitor);
+    }
+
+    @Override
+    public void setLoginModuleMonitor(@NotNull LoginModuleMonitor lmMonitor) {
+        this.lmMonitor = lmMonitor;
     }
 }

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=1854982&r1=1854981&r2=1854982&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
 Thu Mar  7 14:15:14 2019
@@ -26,6 +26,7 @@ import javax.security.auth.callback.Unsu
 
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.callback.WhiteboardCallback;
@@ -49,16 +50,19 @@ class CallbackHandlerImpl implements Cal
     private final ContentRepository contentRepository;
     private final SecurityProvider securityProvider;
     private final Whiteboard whiteboard;
+    private final LoginModuleMonitor loginModuleMonitor;
 
     CallbackHandlerImpl(Credentials credentials, String workspaceName,
                         ContentRepository contentRepository,
                         SecurityProvider securityProvider,
-                        Whiteboard whiteboard) {
+                        Whiteboard whiteboard,
+                        LoginModuleMonitor loginModuleMonitor) {
         this.credentials = credentials;
         this.workspaceName = workspaceName;
         this.contentRepository = contentRepository;
         this.securityProvider = securityProvider;
         this.whiteboard = whiteboard;
+        this.loginModuleMonitor = loginModuleMonitor;
     }
 
     //----------------------------------------------------< CallbackHandler 
>---
@@ -76,6 +80,7 @@ class CallbackHandlerImpl implements Cal
                 repositoryCallback.setContentRepository(contentRepository);
                 repositoryCallback.setSecurityProvider(securityProvider);
                 repositoryCallback.setWorkspaceName(workspaceName);
+                repositoryCallback.setLoginModuleMonitor(loginModuleMonitor);
             } else if (callback instanceof WhiteboardCallback) {
                 ((WhiteboardCallback) callback).setWhiteboard(whiteboard);
             } else {

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImpl.java
 Thu Mar  7 14:15:14 2019
@@ -33,6 +33,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.JaasLoginContext;
 import org.apache.jackrabbit.oak.spi.security.authentication.LoginContext;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
 import org.apache.jackrabbit.oak.spi.security.authentication.PreAuthContext;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
 import org.jetbrains.annotations.NotNull;
@@ -54,18 +55,21 @@ class LoginContextProviderImpl implement
     private final ContentRepository contentRepository;
     private final SecurityProvider securityProvider;
     private final Whiteboard whiteboard;
+    private final LoginModuleMonitor loginModuleMonitor;
 
     private Configuration configuration;
 
     LoginContextProviderImpl(String appName, ConfigurationParameters params,
                              ContentRepository contentRepository,
                              SecurityProvider securityProvider,
-                             Whiteboard whiteboard) {
+                             Whiteboard whiteboard,
+                             LoginModuleMonitor loginModuleMonitor) {
         this.appName = appName;
         this.params = params;
         this.contentRepository = contentRepository;
         this.securityProvider = securityProvider;
         this.whiteboard = whiteboard;
+        this.loginModuleMonitor = loginModuleMonitor;
     }
 
     @Override
@@ -99,7 +103,7 @@ class LoginContextProviderImpl implement
 
     @NotNull
     private CallbackHandler getCallbackHandler(Credentials credentials, String 
workspaceName) {
-        return new CallbackHandlerImpl(credentials, workspaceName, 
contentRepository, securityProvider, whiteboard);
+        return new CallbackHandlerImpl(credentials, workspaceName, 
contentRepository, securityProvider, whiteboard, loginModuleMonitor);
     }
 
     @NotNull

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=1854982&r1=1854981&r2=1854982&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
 Thu Mar  7 14:15:14 2019
@@ -173,8 +173,9 @@ public final class TokenLoginModule exte
                         updateSubject(tc, null, null);
                     } else {
                         // failed to create token -> fail commit()
+                        onError();
                         Object logId = (userId != null) ? userId : 
sharedState.get(SHARED_KEY_LOGIN_NAME);
-                        log.debug("TokenProvider failed to create a login 
token for user " + logId);
+                        log.error("TokenProvider failed to create a login 
token for user " + logId);
                         throw new LoginException("Failed to create login token 
for user " + logId);
                     }
                 }
@@ -225,7 +226,8 @@ public final class TokenLoginModule exte
                 callbackHandler.handle(new Callback[] {tcCallback});
                 provider = tcCallback.getTokenProvider();
             } catch (IOException | UnsupportedCallbackException e) {
-                log.warn(e.getMessage());
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
         return provider;

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authentication/token/TokenProviderImpl.java
 Thu Mar  7 14:15:14 2019
@@ -244,10 +244,10 @@ class TokenProviderImpl implements Token
                 log.error(error, e.getMessage());
             } catch (CommitFailedException | RepositoryException e) {
                 // conflict while committing changes
-                log.warn(error, e.getMessage());
+                log.error(error, e.getMessage());
             }
         } else {
-            log.warn("Unable to get/create token store for user " + userId);
+            log.error("Unable to get/create token store for user {}.", userId);
         }
         return null;
     }

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=1854982&r1=1854981&r2=1854982&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
 Thu Mar  7 14:15:14 2019
@@ -214,12 +214,11 @@ public final class LoginModuleImpl exten
             } else {
                 try {
                     NameCallback callback = new NameCallback("User-ID: ");
-                    callbackHandler.handle(new Callback[]{callback});
+                    callbackHandler.handle(new Callback[] { callback });
                     uid = callback.getName();
-                } catch (UnsupportedCallbackException e) {
-                    log.warn("Credentials- or NameCallback must be supported");
-                } catch (IOException e) {
-                    log.error("Name-Callback failed: " + e.getMessage());
+                } catch (IOException | UnsupportedCallbackException e) {
+                    onError();
+                    log.error(e.getMessage(), e);
                 }
             }
         }

Modified: 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/internal/SecurityProviderRegistration.java
 Thu Mar  7 14:15:14 2019
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.oak.security.internal;
 
+import java.io.Closeable;
+import java.util.Collections;
 import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.List;
@@ -31,10 +33,15 @@ import org.apache.jackrabbit.oak.securit
 import 
org.apache.jackrabbit.oak.security.user.whiteboard.WhiteboardAuthorizableNodeName;
 import 
org.apache.jackrabbit.oak.security.user.whiteboard.WhiteboardUserAuthenticationFactory;
 import org.apache.jackrabbit.oak.spi.security.CompositeConfiguration;
+import org.apache.jackrabbit.oak.spi.security.ConfigurationBase;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
 import org.apache.jackrabbit.oak.spi.security.SecurityConfiguration;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.AuthenticationConfiguration;
+import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMBean;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
+import org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStats;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleStatsCollector;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.token.CompositeTokenConfiguration;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.token.TokenConfiguration;
 import 
org.apache.jackrabbit.oak.spi.security.authorization.AuthorizationConfiguration;
@@ -48,6 +55,9 @@ import org.apache.jackrabbit.oak.spi.sec
 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.action.AuthorizableActionProvider;
+import org.apache.jackrabbit.oak.spi.whiteboard.Registration;
+import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
 import org.jetbrains.annotations.NotNull;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -66,10 +76,14 @@ import org.osgi.service.metatype.annotat
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.io.Closer;
+
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Lists.newCopyOnWriteArrayList;
 import static 
org.apache.jackrabbit.oak.spi.security.RegistrationConstants.OAK_SECURITY_NAME;
+import static org.apache.jackrabbit.oak.commons.IOUtils.closeQuietly;
 import static 
org.apache.jackrabbit.oak.spi.security.ConfigurationParameters.EMPTY;
+import static 
org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils.registerMBean;
 
 @Component(immediate=true)
 @Designate(ocd = SecurityProviderRegistration.Configuration.class)
@@ -143,6 +157,10 @@ public class SecurityProviderRegistratio
     private RootProvider rootProvider;
     private TreeProvider treeProvider;
 
+    @Reference
+    private StatisticsProvider statisticsProvider = StatisticsProvider.NOOP;
+    private Closer closer;
+
     //----------------------------------------------------< SCR integration 
>---
 
     @Activate
@@ -466,9 +484,10 @@ public class SecurityProviderRegistratio
 
         properties.put("type", "default");
 
+        Whiteboard whiteboard = new OsgiWhiteboard(context);
         ServiceRegistration registration = context.registerService(
                 SecurityProvider.class.getName(),
-                createSecurityProvider(context),
+                createSecurityProvider(whiteboard),
                 properties
         );
 
@@ -477,6 +496,19 @@ public class SecurityProviderRegistratio
             this.registering = false;
         }
 
+        closer = Closer.create();
+        if (authenticationConfiguration instanceof LoginModuleStatsCollector) {
+            LoginModuleStats lmMonitor = new 
LoginModuleStats(statisticsProvider);
+            ((LoginModuleStatsCollector) 
authenticationConfiguration).setLoginModuleMonitor(lmMonitor);
+
+            Registration mon = whiteboard.register(LoginModuleMonitor.class, 
lmMonitor, Collections.emptyMap());
+            closer.register((Closeable) mon::unregister);
+
+            Registration mbean = registerMBean(whiteboard, 
LoginModuleMBean.class, lmMonitor, LoginModuleMBean.TYPE,
+                    "LoginModule statistics");
+            closer.register((Closeable) mbean::unregister);
+        }
+
         log.info("SecurityProvider instance registered");
     }
 
@@ -509,11 +541,12 @@ public class SecurityProviderRegistratio
         }
 
         registration.unregister();
+        closeQuietly(closer);
 
         log.info("SecurityProvider instance unregistered");
     }
 
-    private SecurityProvider createSecurityProvider(@NotNull BundleContext 
context) {
+    private SecurityProvider createSecurityProvider(@NotNull Whiteboard 
whiteboard) {
         ConfigurationParameters userParams = ConfigurationParameters.of(
               
ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_ACTION_PROVIDER, 
createWhiteboardAuthorizableActionProvider()),
               
ConfigurationParameters.of(UserConstants.PARAM_AUTHORIZABLE_NODE_NAME, 
createWhiteboardAuthorizableNodeName()),
@@ -526,7 +559,7 @@ public class SecurityProviderRegistratio
                 .with(authenticationConfiguration, EMPTY, 
privilegeConfiguration, EMPTY, userConfiguration, userParams,
                         authorizationConfiguration, authorizationParams, 
principalConfiguration, EMPTY,
                         tokenConfiguration, EMPTY)
-                .withWhiteboard(new OsgiWhiteboard(context)).build();
+                .withWhiteboard(whiteboard).build();
     }
 
     private RestrictionProvider createWhiteboardRestrictionProvider() {

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/CallbackHandlerImplTest.java
 Thu Mar  7 14:15:14 2019
@@ -24,6 +24,7 @@ import javax.security.auth.callback.Pass
 import javax.security.auth.callback.UnsupportedCallbackException;
 
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.callback.CredentialsCallback;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.callback.RepositoryCallback;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.callback.WhiteboardCallback;
@@ -52,7 +53,7 @@ public class CallbackHandlerImplTest ext
     }
 
     private CallbackHandlerImpl create(@NotNull Credentials creds) {
-        return new CallbackHandlerImpl(creds, 
root.getContentSession().getWorkspaceName(), getContentRepository(), 
getSecurityProvider(), whiteboard);
+        return new CallbackHandlerImpl(creds, 
root.getContentSession().getWorkspaceName(), getContentRepository(), 
getSecurityProvider(), whiteboard, LoginModuleMonitor.NOOP);
     }
 
     @Test

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authentication/LoginContextProviderImplTest.java
 Thu Mar  7 14:15:14 2019
@@ -34,6 +34,7 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.authentication.JaasLoginContext;
 import org.apache.jackrabbit.oak.spi.security.authentication.LoginContext;
 import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
 import org.apache.jackrabbit.oak.spi.security.authentication.PreAuthContext;
 import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard;
 import org.junit.Test;
@@ -50,8 +51,12 @@ public class LoginContextProviderImplTes
     @Override
     public void before() throws Exception {
         super.before();
+        lcProvider = 
newLoginContextProviderImpl(ConfigurationParameters.EMPTY);
+    }
 
-        lcProvider = new 
LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, 
ConfigurationParameters.EMPTY, getContentRepository(), getSecurityProvider(), 
new DefaultWhiteboard());
+    private LoginContextProviderImpl 
newLoginContextProviderImpl(ConfigurationParameters params) {
+        return new 
LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, params,
+                getContentRepository(), getSecurityProvider(), new 
DefaultWhiteboard(), LoginModuleMonitor.NOOP);
     }
 
     @Test
@@ -93,7 +98,7 @@ public class LoginContextProviderImplTes
     @Test
     public void testGetLoginContextWithInvalidProviderConfig() throws 
Exception {
         ConfigurationParameters params = 
ConfigurationParameters.of(AuthenticationConfiguration.PARAM_CONFIG_SPI_NAME, 
"invalid");
-        LoginContextProvider provider = new 
LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, params, 
getContentRepository(), getSecurityProvider(), new DefaultWhiteboard());
+        LoginContextProvider provider = newLoginContextProviderImpl(params);
 
         // invalid configuration falls back to default configuration
         LoginContext ctx = provider.getLoginContext(new 
SimpleCredentials(getTestUser().getID(), getTestUser().getID().toCharArray()), 
null);
@@ -106,12 +111,12 @@ public class LoginContextProviderImplTes
             @Override
             public AppConfigurationEntry[] getAppConfigurationEntry(String 
applicationName) {
                 return new AppConfigurationEntry[]{
-                        new 
AppConfigurationEntry(GuestLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap())
+                        new 
AppConfigurationEntry(GuestLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap<>())
                 };
             }
         });
 
-        LoginContextProvider provider = new 
LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, 
ConfigurationParameters.EMPTY, getContentRepository(), getSecurityProvider(), 
new DefaultWhiteboard());
+        LoginContextProvider provider = 
newLoginContextProviderImpl(ConfigurationParameters.EMPTY);
         LoginContext ctx = provider.getLoginContext(null, null);
         ctx.login();
 
@@ -124,12 +129,12 @@ public class LoginContextProviderImplTes
             @Override
             public AppConfigurationEntry[] getAppConfigurationEntry(String 
applicationName) {
                 return new AppConfigurationEntry[]{
-                        new 
AppConfigurationEntry(GuestLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap())
+                        new 
AppConfigurationEntry(GuestLoginModule.class.getName(), 
AppConfigurationEntry.LoginModuleControlFlag.OPTIONAL, new HashMap<>())
                 };
             }
         });
 
-        LoginContextProvider provider = new 
LoginContextProviderImpl(AuthenticationConfiguration.DEFAULT_APP_NAME, 
ConfigurationParameters.EMPTY, getContentRepository(), getSecurityProvider(), 
new DefaultWhiteboard());
+        LoginContextProvider provider = 
newLoginContextProviderImpl(ConfigurationParameters.EMPTY);
         provider.getLoginContext(null, null);
         LoginContext ctx = provider.getLoginContext(null, null);
 

Modified: jackrabbit/oak/trunk/oak-security-spi/pom.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/pom.xml?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-security-spi/pom.xml Thu Mar  7 14:15:14 2019
@@ -171,6 +171,11 @@
       <artifactId>mockito-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-classic</artifactId>
+        <scope>test</scope>
+    </dependency>
   </dependencies>
 
 </project>

Modified: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModule.java
 Thu Mar  7 14:15:14 2019
@@ -170,7 +170,7 @@ public abstract class AbstractLoginModul
     protected ConfigurationParameters options;
 
     private SecurityProvider securityProvider;
-
+    private LoginModuleMonitor loginModuleMonitor;
     private Whiteboard whiteboard;
 
     private ContentSession systemSession;
@@ -217,7 +217,8 @@ public abstract class AbstractLoginModul
             try {
                 systemSession.close();
             } catch (IOException e) {
-                log.debug(e.getMessage());
+                onError();
+                log.error(e.getMessage(), e);
             }
             systemSession = null;
         }
@@ -255,10 +256,9 @@ public abstract class AbstractLoginModul
                 } else {
                     log.debug("Login: No supported credentials obtained from 
callback; trying shared state.");
                 }
-            } catch (UnsupportedCallbackException e) {
-                log.warn(e.getMessage());
-            } catch (IOException e) {
-                log.error(e.getMessage());
+            } catch (UnsupportedCallbackException | IOException e) {
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
 
@@ -343,8 +343,9 @@ public abstract class AbstractLoginModul
             try {
                 callbackHandler.handle(new Callback[]{rcb});
                 securityProvider = rcb.getSecurityProvider();
-            } catch (Exception e) {
-                log.debug("Unable to retrieve the SecurityProvider via 
callback", e);
+            } catch (IOException | UnsupportedCallbackException e) {
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
         return securityProvider;
@@ -366,8 +367,9 @@ public abstract class AbstractLoginModul
             try {
                 callbackHandler.handle(new Callback[]{cb});
                 whiteboard = cb.getWhiteboard();
-            } catch (Exception e) {
-                log.debug("Unable to retrieve the Whiteboard via callback", e);
+            } catch (IOException | UnsupportedCallbackException e) {
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
         return whiteboard;
@@ -401,8 +403,9 @@ public abstract class AbstractLoginModul
                 } else {
                     log.debug("Unable to retrieve the Root via 
RepositoryCallback; ContentRepository not available.");
                 }
-            } catch (UnsupportedCallbackException | PrivilegedActionException 
| IOException e) {
-                log.debug(e.getMessage());
+            } catch (IOException | UnsupportedCallbackException | 
PrivilegedActionException e) {
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
         return root;
@@ -431,7 +434,8 @@ public abstract class AbstractLoginModul
                 callbackHandler.handle(new Callback[]{userCallBack});
                 userManager = userCallBack.getUserManager();
             } catch (IOException | UnsupportedCallbackException e) {
-                log.debug(e.getMessage());
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
 
@@ -461,7 +465,8 @@ public abstract class AbstractLoginModul
                 callbackHandler.handle(new Callback[]{principalCallBack});
                 principalProvider = principalCallBack.getPrincipalProvider();
             } catch (IOException | UnsupportedCallbackException e) {
-                log.debug(e.getMessage());
+                onError();
+                log.error(e.getMessage(), e);
             }
         }
         return principalProvider;
@@ -507,4 +512,24 @@ public abstract class AbstractLoginModul
         }
         subject.getPublicCredentials().add(authInfo);
     }
+
+    protected LoginModuleMonitor getLoginModuleMonitor() {
+        if (loginModuleMonitor == null && callbackHandler != null) {
+            RepositoryCallback rcb = new RepositoryCallback();
+            try {
+                callbackHandler.handle(new Callback[] { rcb });
+                loginModuleMonitor = rcb.getLoginModuleMonitor();
+            } catch (IOException | UnsupportedCallbackException e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+        return loginModuleMonitor;
+    }
+
+    protected void onError() {
+        LoginModuleMonitor lmm = getLoginModuleMonitor();
+        if (lmm != null) {
+            lmm.loginError();
+        }
+    }
 }

Added: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java?rev=1854982&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java
 Thu Mar  7 14:15:14 2019
@@ -0,0 +1,32 @@
+/*
+ * 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 javax.management.openmbean.CompositeData;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public interface LoginModuleMBean {
+
+    String TYPE = "LoginModuleStats";
+
+    long getLoginErrors();
+
+    CompositeData getLoginErrorsHistory();
+
+}

Propchange: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMBean.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java?rev=1854982&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java
 Thu Mar  7 14:15:14 2019
@@ -0,0 +1,39 @@
+/*
+ * 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 org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public interface LoginModuleMonitor {
+
+    LoginModuleMonitor NOOP = new LoginModuleMonitor() {
+
+        @Override
+        public void loginError() {
+        }
+    };
+
+    /**
+     * Event to be called in the case there is an erorr in the login chain. 
This
+     * is not covering failed logins, but actual operational errors that
+     * probably need to be investigated. Any triggered even should have a
+     * corresponding error logged to make this investigation possible.
+     */
+    void loginError();
+
+}

Propchange: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleMonitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java?rev=1854982&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java
 Thu Mar  7 14:15:14 2019
@@ -0,0 +1,68 @@
+/*
+ * 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 javax.management.openmbean.CompositeData;
+
+import org.apache.jackrabbit.api.stats.TimeSeries;
+import org.apache.jackrabbit.oak.stats.MeterStats;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.apache.jackrabbit.oak.stats.StatsOptions;
+import org.apache.jackrabbit.stats.TimeSeriesStatsUtil;
+
+public class LoginModuleStats implements LoginModuleMBean, LoginModuleMonitor {
+
+    private final StatisticsProvider statisticsProvider;
+
+    static final String LOGIN_ERRORS = "LOGIN_ERRORS";
+
+    private final MeterStats loginErrors;
+
+    public LoginModuleStats(StatisticsProvider statisticsProvider) {
+        this.statisticsProvider = statisticsProvider;
+        this.loginErrors = statisticsProvider.getMeter(LOGIN_ERRORS, 
StatsOptions.DEFAULT);
+    }
+
+    // -- LoginModuleMonitor
+
+    @Override
+    public void loginError() {
+        loginErrors.mark();
+    }
+
+    // -- LoginModuleMBean
+
+    @Override
+    public long getLoginErrors() {
+        return loginErrors.getCount();
+    }
+
+    @Override
+    public CompositeData getLoginErrorsHistory() {
+        return getTimeSeriesData(LOGIN_ERRORS, "Number of login errors.");
+    }
+
+    // -- internal
+
+    private CompositeData getTimeSeriesData(String name, String desc) {
+        return TimeSeriesStatsUtil.asCompositeData(getTimeSeries(name), desc);
+    }
+
+    private TimeSeries getTimeSeries(String name) {
+        return statisticsProvider.getStats().getTimeSeries(name, true);
+    }
+}

Propchange: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStats.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java?rev=1854982&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java
 Thu Mar  7 14:15:14 2019
@@ -0,0 +1,26 @@
+/*
+ * 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 org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public interface LoginModuleStatsCollector {
+
+    void setLoginModuleMonitor(LoginModuleMonitor lmm);
+
+}

Propchange: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsCollector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/RepositoryCallback.java
 Thu Mar  7 14:15:14 2019
@@ -20,6 +20,7 @@ import javax.security.auth.callback.Call
 
 import org.apache.jackrabbit.oak.api.ContentRepository;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import 
org.apache.jackrabbit.oak.spi.security.authentication.LoginModuleMonitor;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -33,6 +34,7 @@ public class RepositoryCallback implemen
     private ContentRepository contentRepository;
     private SecurityProvider securityProvider;
     private String workspaceName;
+    private LoginModuleMonitor loginModuleMonitor;
 
     @Nullable
     public String getWorkspaceName() {
@@ -60,4 +62,13 @@ public class RepositoryCallback implemen
     public void setSecurityProvider(SecurityProvider securityProvider) {
         this.securityProvider = securityProvider;
     }
+
+    public LoginModuleMonitor getLoginModuleMonitor() {
+        return loginModuleMonitor;
+    }
+
+    @Nullable
+    public void setLoginModuleMonitor(LoginModuleMonitor loginModuleMonitor) {
+        this.loginModuleMonitor = loginModuleMonitor;
+    }
 }

Modified: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/callback/package-info.java
 Thu Mar  7 14:15:14 2019
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.0.1")
+@Version("1.1.0")
 package org.apache.jackrabbit.oak.spi.security.authentication.callback;
 
 import org.osgi.annotation.versioning.Version;

Modified: 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/main/java/org/apache/jackrabbit/oak/spi/security/authentication/package-info.java
 Thu Mar  7 14:15:14 2019
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-@Version("1.2.1")
+@Version("1.3.0")
 package org.apache.jackrabbit.oak.spi.security.authentication;
 
 import org.osgi.annotation.versioning.Version;

Modified: 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java?rev=1854982&r1=1854981&r2=1854982&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/AbstractLoginModuleTest.java
 Thu Mar  7 14:15:14 2019
@@ -22,6 +22,9 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
 import javax.jcr.Credentials;
 import javax.jcr.SimpleCredentials;
 import javax.security.auth.Subject;
@@ -52,6 +55,8 @@ import org.apache.jackrabbit.oak.spi.sec
 import org.apache.jackrabbit.oak.spi.security.principal.TestPrincipalProvider;
 import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard;
 import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard;
+import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.junit.Test;
@@ -72,7 +77,6 @@ public class AbstractLoginModuleTest {
         return lm;
     }
 
-
     private static AbstractLoginModule initLoginModule(Class<?> 
supportedCredentials, CallbackHandler cbh) {
         AbstractLoginModule lm = new TestLoginModule(supportedCredentials);
         lm.initialize(new Subject(), cbh, Collections.<String, 
Object>emptyMap(), null);
@@ -291,18 +295,30 @@ public class AbstractLoginModuleTest {
         assertSame(root, loginModule.getRoot());
     }
 
+    private static LoginModuleStats newLoginModuleStats() {
+        ScheduledExecutorService executor = 
Executors.newSingleThreadScheduledExecutor();
+        StatisticsProvider sp = new DefaultStatisticsProvider(executor);
+        return new LoginModuleStats(sp);
+    }
+
     @Test
     public void testGetRootIOException() {
-        AbstractLoginModule loginModule = 
initLoginModule(TestCredentials.class, new ThrowingCallbackHandler(true));
+        LoginModuleStats stats = newLoginModuleStats();
+        TestLoginModule lm = new TestLoginModule(TestCredentials.class, stats);
+        lm.initialize(new Subject(), new ThrowingCallbackHandler(true), 
Collections.emptyMap(), null);
 
-        assertNull(loginModule.getRoot());
+        assertNull(lm.getRoot());
+        assertEquals(1, stats.getLoginErrors());
     }
 
     @Test
     public void testGetRootUnsupportedCallbackException() {
-        AbstractLoginModule loginModule = 
initLoginModule(TestCredentials.class, new ThrowingCallbackHandler(false));
+        LoginModuleStats stats = newLoginModuleStats();
+        TestLoginModule lm = new TestLoginModule(TestCredentials.class, stats);
+        lm.initialize(new Subject(), new ThrowingCallbackHandler(false), 
Collections.emptyMap(), null);
 
-        assertNull(loginModule.getRoot());
+        assertNull(lm.getRoot());
+        assertEquals(1, stats.getLoginErrors());
     }
 
     @Test
@@ -497,18 +513,64 @@ public class AbstractLoginModuleTest {
         assertSame(authInfo, fromSubject.iterator().next());
     }
 
+    @Test
+    public void testOnError() {
+        LoginModuleStats stats = newLoginModuleStats();
+
+        CallbackHandler cbh = new CallbackHandler() {
+            @Override
+            public void handle(Callback[] callbacks) {
+                for (Callback cb : callbacks) {
+                    if (cb instanceof RepositoryCallback) {
+                        ((RepositoryCallback) cb).setLoginModuleMonitor(stats);
+                    }
+                }
+            }
+        };
+
+        AbstractLoginModule lm = new AbstractLoginModule() {
+
+            @Override
+            public boolean login() throws LoginException {
+                return false;
+            }
+
+            @Override
+            public boolean commit() throws LoginException {
+                return false;
+            }
+
+            @Override
+            protected Set<Class> getSupportedCredentials() {
+                return Collections.singleton(TestCredentials.class);
+            }
+        };
+        lm.initialize(new Subject(), cbh, Collections.<String, 
Object>emptyMap(), null);
+
+        assertTrue(lm.getLoginModuleMonitor() instanceof LoginModuleStats);
+        lm.onError();
+        assertEquals(1, stats.getLoginErrors());
+    }
+
     
//--------------------------------------------------------------------------
 
     private final class TestCredentials implements Credentials {}
 
     private static final class TestLoginModule extends AbstractLoginModule {
 
-        private Class supportedCredentialsClass;
+        private final Class supportedCredentialsClass;
+
+        private LoginModuleMonitor mon = LoginModuleMonitor.NOOP;
 
         private TestLoginModule(Class supportedCredentialsClass) {
             this.supportedCredentialsClass = supportedCredentialsClass;
         }
 
+        private TestLoginModule(Class supportedCredentialsClass, 
LoginModuleMonitor mon) {
+            this.supportedCredentialsClass = supportedCredentialsClass;
+            this.mon = mon;
+        }
+
         @NotNull
         @Override
         protected Set<Class> getSupportedCredentials() {
@@ -524,6 +586,11 @@ public class AbstractLoginModuleTest {
         public boolean commit() {
             return true;
         }
+
+        @Override
+        protected LoginModuleMonitor getLoginModuleMonitor() {
+            return mon;
+        }
     }
 
     private final class TestCallbackHandler implements CallbackHandler {
@@ -571,6 +638,7 @@ public class AbstractLoginModuleTest {
                     rcb.setContentRepository(contentRepository);
                     rcb.setSecurityProvider(securityProvider);
                     rcb.setWorkspaceName(workspaceName);
+                    rcb.setLoginModuleMonitor(LoginModuleMonitor.NOOP);
                 } else {
                     throw new UnsupportedCallbackException(cb);
                 }

Added: 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java?rev=1854982&view=auto
==============================================================================
--- 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java
 (added)
+++ 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java
 Thu Mar  7 14:15:14 2019
@@ -0,0 +1,42 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+
+import org.apache.jackrabbit.oak.stats.DefaultStatisticsProvider;
+import org.apache.jackrabbit.oak.stats.StatisticsProvider;
+import org.junit.Test;
+
+public class LoginModuleStatsTest {
+
+    @Test
+    public void testLoginError() throws Exception {
+        ScheduledExecutorService executor = 
Executors.newSingleThreadScheduledExecutor();
+        StatisticsProvider sp = new DefaultStatisticsProvider(executor);
+
+        LoginModuleStats s = new LoginModuleStats(sp);
+        s.loginError();
+        assertEquals(1, s.getLoginErrors());
+        assertNotNull(s.getLoginErrorsHistory());
+    }
+
+}
\ No newline at end of file

Propchange: 
jackrabbit/oak/trunk/oak-security-spi/src/test/java/org/apache/jackrabbit/oak/spi/security/authentication/LoginModuleStatsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml?rev=1854982&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml 
(added)
+++ jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml 
Thu Mar  7 14:15:14 2019
@@ -0,0 +1,39 @@
+        <!--
+           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.
+          -->
+<configuration>
+
+<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+        <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) 
%msg%n</pattern>
+    </encoder>
+</appender>
+
+<appender name="file" class="ch.qos.logback.core.FileAppender">
+    <file>target/unit-tests.log</file>
+    <encoder>
+        <pattern>%date{HH:mm:ss.SSS} %-5level %-40([%thread] %F:%L) 
%msg%n</pattern>
+    </encoder>
+</appender>
+
+<root level="INFO">
+    <!--
+    <appender-ref ref="console"/>
+    -->
+    <appender-ref ref="file"/>
+</root>
+
+</configuration>

Propchange: 
jackrabbit/oak/trunk/oak-security-spi/src/test/resources/logback-test.xml
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to