This is an automated email from the ASF dual-hosted git repository.

dklco pushed a commit to branch master
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-form.git


The following commit(s) were added to refs/heads/master by this push:
     new 11555fe  Resolved SLING-7671 and fixing the bundle specification issue 
in SLING-7264
11555fe is described below

commit 11555fe32802733b9b9c554f4e3153f5964b80e3
Author: Dan Klco <[email protected]>
AuthorDate: Wed May 16 00:30:18 2018 -0400

    Resolved SLING-7671 and fixing the bundle specification issue in
    SLING-7264
---
 pom.xml                                            |  374 ++--
 .../auth/form/impl/AuthenticationFormServlet.java  |   85 +-
 .../auth/form/impl/FormAuthenticationHandler.java  | 1816 +++++++++-----------
 .../form/impl/FormAuthenticationHandlerConfig.java |   86 +
 .../sling/auth/form/impl/jaas/JaasHelper.java      |   22 +-
 ...mpl.FormAuthenticationHandlerConfig.properties} |   52 +-
 .../form/impl/FormAuthenticationHandlerTest.java   |    2 +-
 7 files changed, 1164 insertions(+), 1273 deletions(-)

diff --git a/pom.xml b/pom.xml
index 312279b..a5c0131 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,206 +1,202 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
-    <!--
-        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
+<!-- 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. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
 
-        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.
-    -->
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.apache.sling</groupId>
+               <artifactId>sling</artifactId>
+               <version>33</version>
+               <relativePath />
+       </parent>
 
-    <modelVersion>4.0.0</modelVersion>
-    <parent>
-        <groupId>org.apache.sling</groupId>
-        <artifactId>sling</artifactId>
-        <version>26</version>
-        <relativePath />
-    </parent>
+       <artifactId>org.apache.sling.auth.form</artifactId>
+       <version>1.0.9-SNAPSHOT</version>
+       <packaging>bundle</packaging>
 
-    <artifactId>org.apache.sling.auth.form</artifactId>
-    <version>1.0.9-SNAPSHOT</version>
-    <packaging>bundle</packaging>
-
-    <name>Apache Sling Form Based Authentication Handler</name>
-    <description>
+       <name>Apache Sling Form Based Authentication Handler</name>
+       <description>
         Bundle implementing form based authentication with login
         and logout support. Authentication state is maintained in
         a Cookie or in an HTTP Session. The password is only submitted
         when first authenticating.
     </description>
 
-    <properties>
-        <site.jira.version.id>12314785</site.jira.version.id>
-        <site.javadoc.exclude>**.impl.**</site.javadoc.exclude>
-    </properties>
+       <properties>
+               <site.jira.version.id>12314785</site.jira.version.id>
+               <site.javadoc.exclude>**.impl.**</site.javadoc.exclude>
+       </properties>
 
-    <scm>
-        
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-form.git</connection>
-        
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-form.git</developerConnection>
-        
<url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-auth-form.git</url>
-    </scm>
+       <scm>
+               
<connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-form.git</connection>
+               
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-form.git</developerConnection>
+               
<url>https://gitbox.apache.org/repos/asf?p=sling-org-apache-sling-auth-form.git</url>
+       </scm>
 
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-scr-plugin</artifactId>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.felix</groupId>
-                <artifactId>maven-bundle-plugin</artifactId>
-                <extensions>true</extensions>
-                <configuration>
-                    <instructions>
-                        <Bundle-DocURL>
-                            
http://sling.apache.org/site/form-based-authenticationhandler.html
-                        </Bundle-DocURL>
-                        <Export-Package>
-                            org.apache.sling.auth.form;version=1.0
-                        </Export-Package>
-                        <Private-Package>
-                            org.apache.sling.auth.form.impl.*
-                        </Private-Package>
-                        <Import-Package>
-                            javax.security.auth.callback;
-                            javax.security.auth.login;
-                            org.apache.sling.jcr.jackrabbit.server.security;
-                            resolution:=optional,
-                            *
-                        </Import-Package>
-                        <Embed-Dependency>
-                            
org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/OsgiUtil.*",
-                            
commons-codec;inline="org/apache/commons/codec/binary/Base64.*
-                            |org/apache/commons/codec/binary/Hex*
-                            |org/apache/commons/codec/binary/StringUtils*
-                            |org/apache/commons/codec/BinaryEncoder*
-                            |org/apache/commons/codec/BinaryDecoder*
-                            |org/apache/commons/codec/Encoder*
-                            |org/apache/commons/codec/Decoder*
-                            |org/apache/commons/codec/EncoderException*
-                            |org/apache/commons/codec/DecoderException*"
-                        </Embed-Dependency>
-                    </instructions>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Bundle-DocURL>
+                                                       
http://sling.apache.org/site/form-based-authenticationhandler.html
+                                               </Bundle-DocURL>
+                                               <Export-Package>
+                                                       
org.apache.sling.auth.form;version=1.0
+                                               </Export-Package>
+                                               <Private-Package>
+                                                       
org.apache.sling.auth.form.impl.*
+                                               </Private-Package>
+                                               <Import-Package>
+                                                       
javax.security.auth.callback;
+                                                       
javax.security.auth.login;
+                                                       
org.apache.sling.jcr.jackrabbit.server.security;
+                                                       resolution:=optional,
+                                                       *
+                                               </Import-Package>
+                                               <Embed-Dependency>
+                                                       
org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/OsgiUtil.*",
+                                                       
commons-codec;inline="org/apache/commons/codec/binary/Base64.*
+                                                       
|org/apache/commons/codec/binary/Hex*
+                                                       
|org/apache/commons/codec/binary/StringUtils*
+                                                       
|org/apache/commons/codec/BinaryEncoder*
+                                                       
|org/apache/commons/codec/BinaryDecoder*
+                                                       
|org/apache/commons/codec/Encoder*
+                                                       
|org/apache/commons/codec/Decoder*
+                                                       
|org/apache/commons/codec/EncoderException*
+                                                       
|org/apache/commons/codec/DecoderException*"
+                                               </Embed-Dependency>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
 
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.scr.annotations</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.auth.core</artifactId>
-            <version>1.1.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>javax.jcr</groupId>
-            <artifactId>jcr</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.jcr.jackrabbit.server</artifactId>
-            <version>2.0.6</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.api</artifactId>
-            <version>2.1.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.compendium</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>javax.servlet</groupId>
-            <artifactId>servlet-api</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-api</artifactId>
-        </dependency>
+       <dependencies>
+               <dependency>
+                       <groupId>org.osgi</groupId>
+                       
<artifactId>org.osgi.service.component.annotations</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.osgi</groupId>
+                       
<artifactId>org.osgi.service.metatype.annotations</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.sling</groupId>
+                       <artifactId>org.apache.sling.auth.core</artifactId>
+                       <version>1.1.0</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>javax.jcr</groupId>
+                       <artifactId>jcr</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.sling</groupId>
+                       
<artifactId>org.apache.sling.jcr.jackrabbit.server</artifactId>
+                       <version>2.0.6</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.sling</groupId>
+                       <artifactId>org.apache.sling.api</artifactId>
+                       <version>2.1.0</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.osgi</groupId>
+                       <artifactId>osgi.core</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.osgi</groupId>
+                       <artifactId>osgi.cmpn</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>javax.servlet</groupId>
+                       <artifactId>javax.servlet-api</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-api</artifactId>
+               </dependency>
 
-        <!-- Embedded Dependencies -->
-        <dependency>
-            <groupId>org.apache.sling</groupId>
-            <artifactId>org.apache.sling.commons.osgi</artifactId>
-            <version>2.0.2-incubator</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>commons-codec</groupId>
-            <artifactId>commons-codec</artifactId>
-            <version>1.4</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>commons-lang</groupId>
-            <artifactId>commons-lang</artifactId>
-            <version>2.4</version>
-            <scope>provided</scope>
-        </dependency>
+               <!-- Embedded Dependencies -->
+               <dependency>
+                       <groupId>org.apache.sling</groupId>
+                       <artifactId>org.apache.sling.commons.osgi</artifactId>
+                       <version>2.0.2-incubator</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>commons-codec</groupId>
+                       <artifactId>commons-codec</artifactId>
+                       <version>1.4</version>
+                       <scope>provided</scope>
+               </dependency>
+               <dependency>
+                       <groupId>commons-lang</groupId>
+                       <artifactId>commons-lang</artifactId>
+                       <version>2.4</version>
+                       <scope>provided</scope>
+               </dependency>
 
-        <dependency>
-            <groupId>org.apache.jackrabbit</groupId>
-            <artifactId>oak-core</artifactId>
-            <version>1.0.0</version>
-            <optional>true</optional>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.felix</groupId>
-            <artifactId>org.apache.felix.jaas</artifactId>
-            <version>0.0.2</version>
-            <optional>true</optional>
-        </dependency>
+               <dependency>
+                       <groupId>org.apache.jackrabbit</groupId>
+                       <artifactId>oak-core</artifactId>
+                       <version>1.0.0</version>
+                       <optional>true</optional>
+               </dependency>
+               <dependency>
+                       <groupId>org.apache.felix</groupId>
+                       <artifactId>org.apache.felix.jaas</artifactId>
+                       <version>0.0.2</version>
+                       <optional>true</optional>
+               </dependency>
 
-        <!-- Test Dependencies -->
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.jmock</groupId>
-            <artifactId>jmock-junit4</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.easymock</groupId>
-            <artifactId>easymock</artifactId>
-            <version>3.4</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-module-junit4</artifactId>
-            <version>1.6.4</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.powermock</groupId>
-            <artifactId>powermock-api-easymock</artifactId>
-            <version>1.6.4</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
+               <!-- Test Dependencies -->
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.jmock</groupId>
+                       <artifactId>jmock-junit4</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.slf4j</groupId>
+                       <artifactId>slf4j-simple</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.easymock</groupId>
+                       <artifactId>easymock</artifactId>
+                       <version>3.4</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.powermock</groupId>
+                       <artifactId>powermock-module-junit4</artifactId>
+                       <version>1.6.4</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.powermock</groupId>
+                       <artifactId>powermock-api-easymock</artifactId>
+                       <version>1.6.4</version>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
 </project>
diff --git 
a/src/main/java/org/apache/sling/auth/form/impl/AuthenticationFormServlet.java 
b/src/main/java/org/apache/sling/auth/form/impl/AuthenticationFormServlet.java
index 5ad6667..78c865e 100644
--- 
a/src/main/java/org/apache/sling/auth/form/impl/AuthenticationFormServlet.java
+++ 
b/src/main/java/org/apache/sling/auth/form/impl/AuthenticationFormServlet.java
@@ -21,68 +21,55 @@ package org.apache.sling.auth.form.impl;
 import javax.servlet.Servlet;
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.auth.core.spi.AbstractAuthenticationFormServlet;
 import org.apache.sling.auth.core.spi.AuthenticationHandler;
 import org.apache.sling.auth.form.FormReason;
+import org.osgi.service.component.annotations.Component;
 
 /**
  * The <code>AuthenticationFormServlet</code> provides the default login form
  * used for Form Based Authentication.
  */
-@Component
-@Properties( {
-    @Property(name = "service.description", value = "Default Login Form for 
Form Based Authentication") })
-@Service(value = Servlet.class)
-@SuppressWarnings("serial")
+@Component(service = Servlet.class, property = { "sling.auth.requirements=" + 
AuthenticationFormServlet.AUTH_REQUIREMENTS,
+               "sling.servlet.paths=" + AuthenticationFormServlet.SERVLET_PATH,
+               "service.description=Default Login Form for Form Based 
Authentication" })
 public class AuthenticationFormServlet extends 
AbstractAuthenticationFormServlet {
 
-    /**
-     * The constant is used to provide the service registration path
-     */
-    @Property(name = "sling.servlet.paths")
-    static final String SERVLET_PATH = "/system/sling/form/login";
+       public static final String SERVLET_PATH = "/system/sling/form/login";
+       public static final String AUTH_REQUIREMENTS = "-" + SERVLET_PATH;
 
-    /**
-     * This constant is used to provide the service registration property
-     * indicating to pass requests to this servlet unauthenticated.
-     */
-    @Property(name = "sling.auth.requirements")
-    @SuppressWarnings("unused")
-    private static final String AUTH_REQUIREMENT = "-" + SERVLET_PATH;
+       private static final long serialVersionUID = -1497963620502763188L;
 
-    /**
-     * Returns an informational message according to the value provided in the
-     * <code>j_reason</code> request parameter. Supported reasons are invalid
-     * credentials and session timeout.
-     *
-     * @param request The request providing the parameter
-     * @return The "translated" reason to render the login form or an empty
-     *         string if there is no specific reason
-     */
-    @Override
-    protected String getReason(final HttpServletRequest request) {
-        // return the resource attribute if set to a non-empty string
-        Object resObj = 
request.getAttribute(AuthenticationHandler.FAILURE_REASON);
-        if (resObj instanceof FormReason) {
-            return ((FormReason) resObj).toString();
-        }
+       /**
+        * Returns an informational message according to the value provided in 
the
+        * <code>j_reason</code> request parameter. Supported reasons are 
invalid
+        * credentials and session timeout.
+        *
+        * @param request
+        *            The request providing the parameter
+        * @return The "translated" reason to render the login form or an empty 
string
+        *         if there is no specific reason
+        */
+       @Override
+       protected String getReason(final HttpServletRequest request) {
+               // return the resource attribute if set to a non-empty string
+               Object resObj = 
request.getAttribute(AuthenticationHandler.FAILURE_REASON);
+               if (resObj instanceof FormReason) {
+                       return ((FormReason) resObj).toString();
+               }
 
-        final String reason = 
request.getParameter(AuthenticationHandler.FAILURE_REASON);
-        if (reason != null) {
-            try {
-                return FormReason.valueOf(reason).toString();
-            } catch (IllegalArgumentException iae) {
-                // thrown if the reason is not an expected value, assume none
-            }
+               final String reason = 
request.getParameter(AuthenticationHandler.FAILURE_REASON);
+               if (reason != null) {
+                       try {
+                               return FormReason.valueOf(reason).toString();
+                       } catch (IllegalArgumentException iae) {
+                               // thrown if the reason is not an expected 
value, assume none
+                       }
 
-            // no valid FormReason value, use raw value
-            return reason;
-        }
+                       // no valid FormReason value, use raw value
+                       return reason;
+               }
 
-        return "";
-    }
+               return "";
+       }
 }
diff --git 
a/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java 
b/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
index b821dd6..8695712 100644
--- 
a/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
+++ 
b/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandler.java
@@ -23,7 +23,6 @@ import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.security.InvalidKeyException;
 import java.security.NoSuchAlgorithmException;
-import java.util.Dictionary;
 import java.util.HashMap;
 
 import javax.jcr.Credentials;
@@ -36,16 +35,6 @@ import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
 import org.apache.commons.codec.binary.Base64;
-import org.apache.felix.jaas.LoginModuleFactory;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Properties;
-import org.apache.felix.scr.annotations.Property;
-import org.apache.felix.scr.annotations.PropertyOption;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.ReferencePolicy;
-import org.apache.felix.scr.annotations.Service;
 import org.apache.sling.api.auth.Authenticator;
 import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.Resource;
@@ -59,11 +48,15 @@ import 
org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler;
 import org.apache.sling.auth.form.FormReason;
 import org.apache.sling.auth.form.impl.jaas.FormCredentials;
 import org.apache.sling.auth.form.impl.jaas.JaasHelper;
-import org.apache.sling.commons.osgi.OsgiUtil;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.metatype.annotations.Designate;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -71,991 +64,818 @@ import org.slf4j.LoggerFactory;
  * The <code>FormAuthenticationHandler</code> class implements the 
authorization
  * steps based on a cookie.
  */
-@Component(label = "%auth.form.name", description = "%auth.form.description", 
metatype = true, name = "org.apache.sling.auth.form.FormAuthenticationHandler")
-@Properties( {
-    @Property(name = Constants.SERVICE_DESCRIPTION, value = "Apache Sling Form 
Based Authentication Handler"),
-    @Property(name = AuthenticationHandler.PATH_PROPERTY, value = "/", 
cardinality = 100),
-    @Property(name = AuthenticationHandler.TYPE_PROPERTY, value = 
HttpServletRequest.FORM_AUTH, propertyPrivate = true),
-    @Property(name = Constants.SERVICE_RANKING, intValue = 0, propertyPrivate 
= false),
-
-    @Property(name = LoginModuleFactory.JAAS_CONTROL_FLAG, value = 
"sufficient"),
-    @Property(name = LoginModuleFactory.JAAS_REALM_NAME, value = 
"jackrabbit.oak"),
-    @Property(name = LoginModuleFactory.JAAS_RANKING, intValue = 1000)
-})
-@Service
+@Component(name = "org.apache.sling.auth.form.FormAuthenticationHandler", 
property = {
+               AuthenticationHandler.TYPE_PROPERTY + "="
+                               + HttpServletRequest.FORM_AUTH }, service = 
AuthenticationHandler.class, immediate = true)
+@Designate(ocd = FormAuthenticationHandlerConfig.class)
 public class FormAuthenticationHandler extends 
DefaultAuthenticationFeedbackHandler implements AuthenticationHandler {
 
-    /**
-     * The name of the parameter providing the login form URL.
-     */
-    @Property(value=AuthenticationFormServlet.SERVLET_PATH)
-    private static final String PAR_LOGIN_FORM = "form.login.form";
-
-    /**
-     * The value of the {@link #PAR_AUTH_STORAGE} parameter indicating the use
-     * of a Cookie to store the authentication data.
-     */
-    private static final String AUTH_STORAGE_COOKIE = "cookie";
-
-    /**
-     * The value of the {@link #PAR_AUTH_STORAGE} parameter indicating the use
-     * of a session attribute to store the authentication data.
-     */
-    private static final String AUTH_STORAGE_SESSION_ATTRIBUTE = "session";
-
-    /**
-     * To be used to determine if the auth has value comes from a cookie or 
from
-     * a session attribute.
-     */
-    private static final String DEFAULT_AUTH_STORAGE = AUTH_STORAGE_COOKIE;
-
-    @Property(value = DEFAULT_AUTH_STORAGE, options = {
-        @PropertyOption(name = AUTH_STORAGE_COOKIE, value = "Cookie"),
-        @PropertyOption(name = AUTH_STORAGE_SESSION_ATTRIBUTE, value = 
"Session Attribute") })
-    private static final String PAR_AUTH_STORAGE = "form.auth.storage";
-
-    /**
-     * The default Cookie or session attribute name
-     *
-     * @see #PAR_AUTH_NAME
-     */
-    private static final String DEFAULT_AUTH_NAME = "sling.formauth";
-
-    /**
-     * The name of the configuration parameter providing the Cookie or session
-     * attribute name.
-     */
-    @Property(value = DEFAULT_AUTH_NAME)
-    private static final String PAR_AUTH_NAME = "form.auth.name";
-
-    /**
-     * Default value for the {@link #PAR_CREDENTIALS_ATTRIBUTE_NAME} property
-     */
-    private static final String DEFAULT_CREDENTIALS_ATTRIBUTE_NAME = 
DEFAULT_AUTH_NAME;
-
-    /**
-     * This is the name of the SimpleCredentials attribute that holds the auth
-     * info extracted from the cookie value.
-     */
-    @Property(value = DEFAULT_CREDENTIALS_ATTRIBUTE_NAME)
-    private static final String PAR_CREDENTIALS_ATTRIBUTE_NAME = 
"form.credentials.name";
-
-    /**
-     * The default authentication data time out value.
-     *
-     * @see #PAR_AUTH_TIMEOUT
-     */
-    private static final int DEFAULT_AUTH_TIMEOUT = 30;
-
-    /**
-     * The number of minutes after which a login session times out. This value
-     * is used as the expiry time set in the authentication data.
-     */
-    @Property(intValue = DEFAULT_AUTH_TIMEOUT)
-    public static final String PAR_AUTH_TIMEOUT = "form.auth.timeout";
-
-    private static final String DEFAULT_TOKEN_FILE = "cookie-tokens.bin";
-
-    /**
-     * The name of the file used to persist the security tokens
-     */
-    @Property(value = DEFAULT_TOKEN_FILE)
-    private static final String PAR_TOKEN_FILE = "form.token.file";
-
-    private static final boolean DEFAULT_TOKEN_FAST_SEED = false;
-
-    /**
-     * Whether to use a less secure but faster seeding mechanism to seed the
-     * random number generator in the {@link TokenStore}. By default the faster
-     * mechanism is disabled and the platform provided seeding is used. This 
may
-     * however block the startup considerably, particularly on Linux and 
Solaris
-     * platforms which use the (blocking but secure) <code>/dev/random</code>
-     * device for seeding.
-     */
-    @Property(boolValue = DEFAULT_TOKEN_FAST_SEED)
-    private static final String PAR_TOKEN_FAST_SEED = "form.token.fastseed";
-
-    /**
-     * The default include value.
-     *
-     * @see #PAR_INCLUDE_FORM
-     */
-    private static final boolean DEFAULT_INCLUDE_FORM = false;
-
-    /**
-     * Whether to redirect to the login form or simple do an include.
-     */
-    @Property(boolValue = DEFAULT_INCLUDE_FORM)
-    public static final String PAR_INCLUDE_FORM = "form.use.include";
-
-    /**
-     * The default login after expire of a cookie.
-     *
-     * @see #PAR_LOGIN_AFTER_EXPIRE
-     */
-    private static final boolean DEFAULT_LOGIN_AFTER_EXPIRE = false;
-
-    /**
-     * Whether to present a login form when a users cookie expires, the default
-     * is not to present the form.
-     */
-    @Property(boolValue = DEFAULT_LOGIN_AFTER_EXPIRE)
-    private static final String PAR_LOGIN_AFTER_EXPIRE = "form.onexpire.login";
-
-    /**
-     * The default domain on which to see the auth cookie (if cookie storage 
is used)
-     */
-    @Property
-    private static final String PAR_DEFAULT_COOKIE_DOMAIN = 
"form.default.cookie.domain";
-
-    /**
-     * The request method required for user name and password submission by the
-     * form (value is "POST").
-     */
-    private static final String REQUEST_METHOD = "POST";
-
-    /**
-     * The last segment of the request URL for the user name and password
-     * submission by the form (value is "/j_security_check").
-     * <p>
-     * This name is derived from the prescription in the Servlet API 2.4
-     * Specification, Section SRV.12.5.3.1 Login Form Notes: <i>In order for 
the
-     * authentication to proceed appropriately, the action of the login form
-     * must always be set to <code>j_security_check</code>.</i>
-     */
-    private static final String REQUEST_URL_SUFFIX = "/j_security_check";
-
-    /**
-     * The name of the form submission parameter providing the name of the user
-     * to authenticate (value is "j_username").
-     * <p>
-     * This name is prescribed by the Servlet API 2.4 Specification, Section
-     * SRV.12.5.3 Form Based Authentication.
-     */
-    private static final String PAR_J_USERNAME = "j_username";
-
-    /**
-     * The name of the form submission parameter providing the password of the
-     * user to authenticate (value is "j_password").
-     * <p>
-     * This name is prescribed by the Servlet API 2.4 Specification, Section
-     * SRV.12.5.3 Form Based Authentication.
-     */
-    private static final String PAR_J_PASSWORD = "j_password";
-
-    /**
-     * Key in the AuthenticationInfo map which contains the domain on which the
-     * auth cookie should be set.
-     */
-    private static final String COOKIE_DOMAIN = "cookie.domain";
-
-    /**
-     * The factor to convert minute numbers into milliseconds used internally
-     */
-    private static final long MINUTES = 60L * 1000L;
-
-    /** default log */
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private AuthenticationStorage authStorage;
-
-    private String loginForm;
-
-    /**
-     * The timeout of a login session in milliseconds, converted from the
-     * configuration property {@link #PAR_AUTH_TIMEOUT} by multiplying with
-     * {@link #MINUTES}.
-     */
-    private long sessionTimeout;
-
-    /**
-     * The name of the credentials attribute which is set to the cookie data
-     * to validate.
-     */
-    private String attrCookieAuthData;
-
-    /**
-     * The {@link TokenStore} used to persist and check authentication data
-     */
-    private TokenStore tokenStore;
-
-    /**
-     * The {@link FormLoginModulePlugin} service registration created when
-     * this authentication handler is registered. If the login module plugin
-     * cannot be created this field is set to <code>null</code>.
-     */
-    private ServiceRegistration loginModule;
-
-    /**
-     * If true, the handler will attempt to include the login form instead of
-     * doing a redirect.
-     */
-    private boolean includeLoginForm;
-
-    /**
-     * The resource resolver factory used to resolve the login form as a 
resource
-     */
-    @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = 
ReferenceCardinality.OPTIONAL_UNARY)
-    private volatile ResourceResolverFactory resourceResolverFactory;
-
-    /**
-     * If true the login form will be presented when the token expires.
-     */
-    private boolean loginAfterExpire;
-
-    private JaasHelper jaasHelper;
-
-    /**
-     * Extracts cookie/session based credentials from the request. Returns
-     * <code>null</code> if the handler assumes HTTP Basic authentication would
-     * be more appropriate, if no form fields are present in the request and if
-     * the secure user data is not present either in the cookie or an HTTP
-     * Session.
-     */
-    @Override
-    public AuthenticationInfo extractCredentials(HttpServletRequest request,
-            HttpServletResponse response) {
-
-        AuthenticationInfo info = null;
-
-        // 1. try credentials from POST'ed request parameters
-        info = this.extractRequestParameterAuthentication(request);
-
-        // 2. try credentials from the cookie or session
-        if (info == null) {
-            String authData = authStorage.extractAuthenticationInfo(request);
-            if (authData != null) {
-                if (tokenStore.isValid(authData)) {
-                    info = createAuthInfo(authData);
-                } else {
-                    // clear the cookie, its invalid and we should get rid of 
it
-                    // so that the invalid cookie isn't present on the authN
-                    // operation.
-                    authStorage.clear(request, response);
-                    if (this.loginAfterExpire || 
AuthUtil.isValidateRequest(request)) {
-                        // signal the requestCredentials method a previous 
login
-                        // failure
-                        request.setAttribute(FAILURE_REASON, 
FormReason.TIMEOUT);
-                        info = AuthenticationInfo.FAIL_AUTH;
-                    }
-                }
-            }
-        }
-
-        return info;
-    }
-
-    /**
-     * Unless the <code>sling:authRequestLogin</code> to anything other than
-     * <code>Form</code> this method either sends back a 403/FORBIDDEN response
-     * if the <code>j_verify</code> parameter is set to <code>true</code> or
-     * redirects to the login form to ask for credentials.
-     * <p>
-     * This method assumes the <code>j_verify</code> request parameter to only
-     * be set in the initial username/password submission through the login
-     * form. No further checks are applied, though, before sending back the
-     * 403/FORBIDDEN response.
-     */
-    @Override
-    public boolean requestCredentials(HttpServletRequest request,
-            HttpServletResponse response) throws IOException {
-
-        // 0. ignore this handler if an authentication handler is requested
-        if (ignoreRequestCredentials(request)) {
-            // consider this handler is not used
-            return false;
-        }
-
-        //check the referrer to see if the request is for this handler
-        if (!AuthUtil.checkReferer(request, loginForm)) {
-               //not for this handler, so return
-               return false;
-        }
-
-        final String resource = AuthUtil.setLoginResourceAttribute(request,
-            request.getRequestURI());
-
-        if (includeLoginForm && (resourceResolverFactory != null)) {
-            ResourceResolver resourceResolver = null;
-            try {
-                resourceResolver = 
resourceResolverFactory.getAdministrativeResourceResolver(null);
-                Resource loginFormResource = 
resourceResolver.resolve(loginForm);
-                Servlet loginFormServlet = 
loginFormResource.adaptTo(Servlet.class);
-                if (loginFormServlet != null) {
-                    try {
-                        loginFormServlet.service(request, response);
-                        return true;
-                    } catch (ServletException e) {
-                        log.error("Failed to include the form: " + loginForm, 
e);
-                    }
-                }
-            } catch (LoginException e) {
-                log.error("Unable to get a resource resolver to include for 
the login resource. Will redirect instead.");
-            } finally {
-                if (resourceResolver != null) {
-                    resourceResolver.close();
-                }
-            }
-        }
-
-        HashMap<String, String> params = new HashMap<String, String>();
-        params.put(Authenticator.LOGIN_RESOURCE, resource);
-
-        // append indication of previous login failure
-        if (request.getAttribute(FAILURE_REASON) != null) {
-            final Object jReason = request.getAttribute(FAILURE_REASON);
-            @SuppressWarnings("rawtypes")
-            final String reason = (jReason instanceof Enum)
-                    ? ((Enum) jReason).name()
-                    : jReason.toString();
-            params.put(FAILURE_REASON, reason);
-        }
-
-        try {
-            AuthUtil.sendRedirect(request, response, request.getContextPath() 
+ loginForm, params);
-        } catch (IOException e) {
-            log.error("Failed to redirect to the login form " + loginForm, e);
-        }
-
-        return true;
-    }
-
-    /**
-     * Clears all authentication state which might have been prepared by this
-     * authentication handler.
-     */
-    @Override
-    public void dropCredentials(HttpServletRequest request,
-            HttpServletResponse response) {
-        authStorage.clear(request, response);
-    }
-
-    // ---------- AuthenticationFeedbackHandler
-
-    /**
-     * Called after an unsuccessful login attempt. This implementation makes
-     * sure the authentication data is removed either by removing the cookie or
-     * by remove the HTTP Session attribute.
-     */
-    @Override
-    public void authenticationFailed(HttpServletRequest request,
-            HttpServletResponse response, AuthenticationInfo authInfo) {
-
-        /*
-         * Note: This method is called if this handler provided credentials
-         * which cause a login failure
-         */
-
-        // clear authentication data from Cookie or Http Session
-        authStorage.clear(request, response);
-
-        // signal the reason for login failure
-        request.setAttribute(FAILURE_REASON, FormReason.INVALID_CREDENTIALS);
-    }
-
-    /**
-     * Called after successful login with the given authentication info. This
-     * implementation ensures the authentication data is set in either the
-     * cookie or the HTTP session with the correct security tokens.
-     * <p>
-     * If no authentication data already exists, it is created. Otherwise if 
the
-     * data has expired the data is updated with a new security token and a new
-     * expiry time.
-     * <p>
-     * If creating or updating the authentication data fails, it is actually
-     * removed from the cookie or the HTTP session and future requests will not
-     * be authenticated any longer.
-     */
-    @Override
-    public boolean authenticationSucceeded(HttpServletRequest request,
-            HttpServletResponse response, AuthenticationInfo authInfo) {
-
-        /*
-         * Note: This method is called if this handler provided credentials
-         * which succeeded login into the repository
-         */
-
-        // ensure fresh authentication data
-        refreshAuthData(request, response, authInfo);
-
-        final boolean result;
-        // SLING-1847: only consider a resource redirect if this is a POST 
request
-        // to the j_security_check URL
-        if (REQUEST_METHOD.equals(request.getMethod())
-                       && 
request.getRequestURI().endsWith(REQUEST_URL_SUFFIX)) {
-
-            if (DefaultAuthenticationFeedbackHandler.handleRedirect(request, 
response)) {
-               // terminate request, all done in the default handler
-               result = false;
-            } else {
-               // check whether redirect is requested by the resource parameter
-               final String targetResource = 
AuthUtil.getLoginResource(request, null);
-               if (targetResource != null) {
-                       try {
-                       if (response.isCommitted()) {
-                           throw new IllegalStateException("Response is 
already committed");
-                       }
-                       response.resetBuffer();
-
-                       StringBuilder b = new StringBuilder();
-                       if (AuthUtil.isRedirectValid(request, targetResource)) {
-                           b.append(targetResource);
-                       } else if (request.getContextPath().length() == 0) {
-                           b.append("/");
-                       } else {
-                           b.append(request.getContextPath());
-                       }
-                       response.sendRedirect(b.toString());
-                       } catch (IOException ioe) {
-                               log.error("Failed to send redirect to: " + 
targetResource, ioe);
-                       }
-
-                       // terminate request, all done
-                       result = true;
-               } else {
-                       // no redirect, hence continue processing
-                       result = false;
-               }
-            }
-        } else {
-            // no redirect, hence continue processing
-            result = false;
-        }
-
-        // no redirect
-        return result;
-    }
-
-    @Override
-    public String toString() {
-        return "Form Based Authentication Handler";
-    }
-
-    // --------- Force HTTP Basic Auth ---------
-
-    /**
-     * Returns <code>true</code> if this authentication handler should ignore
-     * the call to
-     * {@link #requestCredentials(HttpServletRequest, HttpServletResponse)}.
-     * <p>
-     * This method returns <code>true</code> if the
-     * {@link #REQUEST_LOGIN_PARAMETER} is set to any value other than "Form"
-     * (HttpServletRequest.FORM_AUTH).
-     */
-    private boolean ignoreRequestCredentials(final HttpServletRequest request) 
{
-        final String requestLogin = 
request.getParameter(REQUEST_LOGIN_PARAMETER);
-        return requestLogin != null
-            && !HttpServletRequest.FORM_AUTH.equals(requestLogin);
-    }
-
-    /**
-     * Ensures the authentication data is set (if not set yet) and the expiry
-     * time is prolonged (if auth data already existed).
-     * <p>
-     * This method is intended to be called in case authentication succeeded.
-     *
-     * @param request The current request
-     * @param response The current response
-     * @param authInfo The authentication info used to successful log in
-     */
-    private void refreshAuthData(final HttpServletRequest request,
-            final HttpServletResponse response,
-            final AuthenticationInfo authInfo) {
-
-        // get current authentication data, may be missing after first login
-        String authData = getCookieAuthData(authInfo);
-
-        // check whether we have to "store" or create the data
-        final boolean refreshCookie = needsRefresh(authData,
-            this.sessionTimeout);
-
-        // add or refresh the stored auth hash
-        if (refreshCookie) {
-            long expires = System.currentTimeMillis() + this.sessionTimeout;
-            try {
-                authData = null;
-                authData = tokenStore.encode(expires, authInfo.getUser());
-            } catch (InvalidKeyException e) {
-                log.error(e.getMessage(), e);
-            } catch (IllegalStateException e) {
-                log.error(e.getMessage(), e);
-            } catch (UnsupportedEncodingException e) {
-                log.error(e.getMessage(), e);
-            } catch (NoSuchAlgorithmException e) {
-                log.error(e.getMessage(), e);
-            }
-
-            if (authData != null) {
-                authStorage.set(request, response, authData, authInfo);
-            } else {
-                authStorage.clear(request, response);
-            }
-        }
-    }
-
-    // --------- Request Parameter Auth ---------
-
-    private AuthenticationInfo extractRequestParameterAuthentication(
-            HttpServletRequest request) {
-        AuthenticationInfo info = null;
-
-        // only consider login form parameters if this is a POST request
-        // to the j_security_check URL
-        if (REQUEST_METHOD.equals(request.getMethod())
-            && request.getRequestURI().endsWith(REQUEST_URL_SUFFIX)) {
-
-            String user = request.getParameter(PAR_J_USERNAME);
-            String pwd = request.getParameter(PAR_J_PASSWORD);
-
-            if (user != null && pwd != null) {
-                info = new AuthenticationInfo(HttpServletRequest.FORM_AUTH,
-                    user, pwd.toCharArray());
-                info.put(AuthConstants.AUTH_INFO_LOGIN, new Object());
-
-                // if this request is providing form credentials, we have to
-                // make sure, that the request is redirected after successful
-                // authentication, otherwise the request may be processed
-                // as a POST request to the j_security_check page (unless
-                // the j_validate parameter is set); but only if this is not
-                // a validation request
-                if (!AuthUtil.isValidateRequest(request)) {
-                    AuthUtil.setLoginResourceAttribute(request, 
request.getContextPath());
-                }
-            }
-        }
-
-        return info;
-    }
-
-    private AuthenticationInfo createAuthInfo(final String authData) {
-        final String userId = getUserId(authData);
-        if (userId == null) {
-            return null;
-        }
-
-        final AuthenticationInfo info = new AuthenticationInfo(
-            HttpServletRequest.FORM_AUTH, userId);
-
-        if (jaasHelper.enabled()) {
-            //JcrResourceConstants.AUTHENTICATION_INFO_CREDENTIALS
-            info.put("user.jcr.credentials", new FormCredentials(userId, 
authData));
-        } else {
-            info.put(attrCookieAuthData, authData);
-        }
-
-        return info;
-    }
-
-    private String getCookieAuthData(final AuthenticationInfo info) {
-        Object data = info.get(attrCookieAuthData);
-        if (data instanceof String) {
-            return (String) data;
-        }
-        return null;
-    }
-
-    // ---------- LoginModulePlugin support
-
-    private String getCookieAuthData(final Credentials credentials) {
-        if (credentials instanceof SimpleCredentials) {
-            Object data = ((SimpleCredentials) 
credentials).getAttribute(attrCookieAuthData);
-            if (data instanceof String) {
-                return (String) data;
-            }
-        } else if (credentials instanceof FormCredentials){
-            return ((FormCredentials) credentials).getAuthData();
-        }
-
-        // no SimpleCredentials or no valid attribute
-        return null;
-    }
-
-    boolean hasAuthData(final Credentials credentials) {
-        return getCookieAuthData(credentials) != null;
-    }
-
-    public boolean isValid(final Credentials credentials) {
-        String authData = getCookieAuthData(credentials);
-        if (authData != null) {
-            return tokenStore.isValid(authData);
-        }
-
-        // no authdata, not valid
-        return false;
-    }
-
-    // ---------- SCR Integration 
----------------------------------------------
-
-    /**
-     * Called by SCR to activate the authentication handler.
-     *
-     * @throws InvalidKeyException
-     * @throws NoSuchAlgorithmException
-     * @throws IllegalStateException
-     * @throws UnsupportedEncodingException
-     */
-    protected void activate(ComponentContext componentContext)
-            throws InvalidKeyException, NoSuchAlgorithmException,
-            IllegalStateException, UnsupportedEncodingException {
-
-        Dictionary<?, ?> properties = componentContext.getProperties();
-
-        this.jaasHelper = new JaasHelper(this, 
componentContext.getBundleContext(), properties);
-        this.loginForm = OsgiUtil.toString(properties.get(PAR_LOGIN_FORM),
-            AuthenticationFormServlet.SERVLET_PATH);
-        log.info("Login Form URL {}", loginForm);
-
-        final String authName = OsgiUtil.toString(
-            properties.get(PAR_AUTH_NAME), DEFAULT_AUTH_NAME);
-
-        String defaultCookieDomain = OsgiUtil.toString(
-            properties.get(PAR_DEFAULT_COOKIE_DOMAIN), "");
-        if (defaultCookieDomain.length() == 0) {
-            defaultCookieDomain = null;
-        }
-
-        final String authStorage = OsgiUtil.toString(
-            properties.get(PAR_AUTH_STORAGE), DEFAULT_AUTH_STORAGE);
-        if (AUTH_STORAGE_SESSION_ATTRIBUTE.equals(authStorage)) {
-
-            this.authStorage = new SessionStorage(authName);
-            log.info("Using HTTP Session store with attribute name {}",
-                authName);
-
-        } else {
-
-            this.authStorage = new CookieStorage(authName, 
defaultCookieDomain);
-            log.info("Using Cookie store with name {}", authName);
-
-        }
-
-        this.attrCookieAuthData = OsgiUtil.toString(
-            properties.get(PAR_CREDENTIALS_ATTRIBUTE_NAME),
-            DEFAULT_CREDENTIALS_ATTRIBUTE_NAME);
-        log.info("Setting Auth Data attribute name {}", attrCookieAuthData);
-
-        int timeoutMinutes = OsgiUtil.toInteger(
-            properties.get(PAR_AUTH_TIMEOUT), DEFAULT_AUTH_TIMEOUT);
-        if (timeoutMinutes < 1) {
-            timeoutMinutes = DEFAULT_AUTH_TIMEOUT;
-        }
-        log.info("Setting session timeout {} minutes", timeoutMinutes);
-        this.sessionTimeout = MINUTES * timeoutMinutes;
-
-        final String tokenFileName = OsgiUtil.toString(
-            properties.get(PAR_TOKEN_FILE), DEFAULT_TOKEN_FILE);
-        final File tokenFile = getTokenFile(tokenFileName,
-            componentContext.getBundleContext());
-        final boolean fastSeed = OsgiUtil.toBoolean(
-            properties.get(PAR_TOKEN_FAST_SEED), DEFAULT_TOKEN_FAST_SEED);
-        log.info("Storing tokens in {}", tokenFile.getAbsolutePath());
-        this.tokenStore = new TokenStore(tokenFile, sessionTimeout, fastSeed);
-
-        this.loginModule = null;
-        if (!jaasHelper.enabled()) {
-            try {
-                this.loginModule = FormLoginModulePlugin.register(this,
-                        componentContext.getBundleContext());
-            } catch (Throwable t) {
-                log.info("Cannot register FormLoginModulePlugin. This is 
expected if Sling LoginModulePlugin services are not supported");
-                log.debug("dump", t);
-            }
-        }
-
-        this.includeLoginForm = 
OsgiUtil.toBoolean(properties.get(PAR_INCLUDE_FORM), DEFAULT_INCLUDE_FORM);
-
-        this.loginAfterExpire = 
OsgiUtil.toBoolean(properties.get(PAR_LOGIN_AFTER_EXPIRE), 
DEFAULT_LOGIN_AFTER_EXPIRE);
-    }
-
-    @Deactivate
-    protected void deactivate() {
-        if (jaasHelper != null){
-            jaasHelper.close();
-            jaasHelper = null;
-        }
-
-        if (loginModule != null) {
-            loginModule.unregister();
-            loginModule = null;
-        }
-    }
-
-    /**
-     * Returns an absolute file indicating the file to use to persist the
-     * security tokens.
-     * <p>
-     * This method is not part of the API of this class and is package private
-     * to enable unit tests.
-     *
-     * @param tokenFileName The configured file name, must not be null
-     * @param bundleContext The BundleContext to use to make an relative file
-     *            absolute
-     * @return The absolute file
-     */
-    File getTokenFile(final String tokenFileName,
-            final BundleContext bundleContext) {
-        File tokenFile = new File(tokenFileName);
-        if (tokenFile.isAbsolute()) {
-            return tokenFile;
-        }
-
-        tokenFile = bundleContext.getDataFile(tokenFileName);
-        if (tokenFile == null) {
-            final String slingHome = bundleContext.getProperty("sling.home");
-            if (slingHome != null) {
-                tokenFile = new File(slingHome, tokenFileName);
-            } else {
-                tokenFile = new File(tokenFileName);
-            }
-        }
-
-        return tokenFile.getAbsoluteFile();
-    }
-
-    /**
-     * Returns the user id from the authentication data. If the authentication
-     * data is a non-<code>null</code> value with 3 fields separated by an @
-     * sign, the value of the third field is returned. Otherwise
-     * <code>null</code> is returned.
-     * <p>
-     * This method is not part of the API of this class and is package private
-     * to enable unit tests.
-     *
-     * @param authData
-     * @return
-     */
-    String getUserId(final String authData) {
-        if (authData != null) {
-            String[] parts = TokenStore.split(authData);
-            if (parts != null) {
-                return parts[2];
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Refresh the cookie periodically.
-     *
-     * @param sessionTimeout time to live for the session
-     * @return true or false
-     */
-    private boolean needsRefresh(final String authData,
-            final long sessionTimeout) {
-        boolean updateCookie = false;
-        if (authData == null) {
-            updateCookie = true;
-        } else {
-            String[] parts = TokenStore.split(authData);
-            if (parts != null && parts.length == 3) {
-                long cookieTime = Long.parseLong(parts[1].substring(1));
-                if (System.currentTimeMillis() + (sessionTimeout / 2) > 
cookieTime) {
-                    updateCookie = true;
-                }
-            }
-        }
-        return updateCookie;
-    }
-
-    /**
-     * The <code>AuthenticationStorage</code> interface abstracts the API
-     * required to store the authentication data in an HTTP cookie or in an
-     * HTTP Session. The concrete class -- {@link CookieStorage} or
-     * {@link SessionStorage} -- is selected using the
-     * {@link FormAuthenticationHandler#PAR_AUTH_STORAGE} configuration
-     * parameter, {@link CookieStorage} by default.
-     */
-    private static interface AuthenticationStorage {
-        String extractAuthenticationInfo(HttpServletRequest request);
-
-        void set(HttpServletRequest request, HttpServletResponse response,
-                String authData, AuthenticationInfo info);
-
-        void clear(HttpServletRequest request, HttpServletResponse response);
-    }
-
-    /**
-     * The <code>CookieStorage</code> class supports storing the
-     * authentication data in an HTTP Cookie.
-     */
-    private static class CookieStorage implements AuthenticationStorage {
-
-        /**
-         * The Set-Cookie header used to manage the login cookie.
-         *
-         * @see CookieStorage#setCookie(HttpServletRequest, 
HttpServletResponse,
-         *      String, String, int, String)
-         */
-        private static final String HEADER_SET_COOKIE = "Set-Cookie";
-
-        private final String cookieName;
-        private final String domainCookieName;
-        private final String defaultCookieDomain;
-
-        public CookieStorage(final String cookieName, final String 
defaultCookieDomain) {
-            this.cookieName = cookieName;
-            this.domainCookieName = cookieName + "." + COOKIE_DOMAIN;
-            this.defaultCookieDomain = defaultCookieDomain;
-        }
-
-        @Override
-        public String extractAuthenticationInfo(HttpServletRequest request) {
-            Cookie[] cookies = request.getCookies();
-            if (cookies != null) {
-                for (Cookie cookie : cookies) {
-                    if (this.cookieName.equals(cookie.getName())) {
-                        // found the cookie, so try to extract the credentials
-                        // from it and reverse the base64 encoding
-                        String value = cookie.getValue();
-                        if (value.length() > 0) {
-                            try {
-                                return new String(Base64.decodeBase64(value),
-                                    "UTF-8");
-                            } catch (UnsupportedEncodingException e1) {
-                                throw new RuntimeException(e1);
-                            }
-                        }
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        @Override
-        public void set(HttpServletRequest request,
-                HttpServletResponse response, String authData, 
AuthenticationInfo info) {
-            // base64 encode to handle any special characters
-            String cookieValue;
-            try {
-                cookieValue = 
Base64.encodeBase64URLSafeString(authData.getBytes("UTF-8"));
-            } catch (UnsupportedEncodingException e1) {
-                throw new RuntimeException(e1);
-            }
-
-            // send the cookie to the response
-            String cookieDomain = (String) info.get(COOKIE_DOMAIN);
-            if (cookieDomain == null || cookieDomain.length() == 0) {
-                cookieDomain = defaultCookieDomain;
-            }
-            setCookie(request, response, this.cookieName, cookieValue, -1,
-                cookieDomain);
-
-            // send the cookie domain cookie if domain is not null
-            if (cookieDomain != null) {
-                setCookie(request, response, this.domainCookieName,
-                    cookieDomain, -1, cookieDomain);
-            }
-        }
-
-        @Override
-        public void clear(HttpServletRequest request,
-                HttpServletResponse response) {
-            Cookie oldCookie = null;
-            String oldCookieDomain = null;
-            Cookie[] cookies = request.getCookies();
-            if (cookies != null) {
-                for (Cookie cookie : cookies) {
-                    if (this.cookieName.equals(cookie.getName())) {
-                        // found the cookie
-                        oldCookie = cookie;
-                    } else if (this.domainCookieName.equals(cookie.getName())) 
{
-                        oldCookieDomain = cookie.getValue();
-                    }
-                }
-            }
-
-            // remove the old cookie from the client
-            if (oldCookie != null) {
-                setCookie(request, response, this.cookieName, "", 0, 
oldCookieDomain);
-                if (oldCookieDomain != null && oldCookieDomain.length() > 0) {
-                    setCookie(request, response, this.domainCookieName, "", 0, 
oldCookieDomain);
-                }
-            }
-        }
-
-        private void setCookie(final HttpServletRequest request,
-                final HttpServletResponse response, final String name,
-                final String value, final int age, final String domain) {
-
-            final String ctxPath = request.getContextPath();
-            final String cookiePath = (ctxPath == null || ctxPath.length() == 
0)
-                    ? "/"
-                    : ctxPath;
-
-            /*
-             * The Servlet Spec 2.5 does not allow us to set the commonly used
-             * HttpOnly attribute on cookies (Servlet API 3.0 does) so we 
create
-             * the Set-Cookie header manually. See
-             * http://www.owasp.org/index.php/HttpOnly for information on what
-             * the HttpOnly attribute is used for.
-             */
-
-            final StringBuilder header = new StringBuilder();
-
-            // default setup with name, value, cookie path and HttpOnly
-            header.append(name).append("=").append(value);
-            header.append("; Path=").append(cookiePath);
-            header.append("; HttpOnly"); // don't allow JS access
-
-            // set the cookie domain if so configured
-            if (domain != null) {
-                header.append("; Domain=").append(domain);
-            }
-
-            // Only set the Max-Age attribute to remove the cookie
-            if (age >= 0) {
-                header.append("; Max-Age=").append(age);
-            }
-
-            // ensure the cookie is secured if this is an https request
-            if (request.isSecure()) {
-                header.append("; Secure");
-            }
-
-            response.addHeader(HEADER_SET_COOKIE, header.toString());
-        }
-    }
-
-    /**
-     * The <code>SessionStorage</code> class provides support to store the
-     * authentication data in an HTTP Session.
-     */
-    private static class SessionStorage implements AuthenticationStorage {
-        private final String sessionAttributeName;
-
-        SessionStorage(final String sessionAttributeName) {
-            this.sessionAttributeName = sessionAttributeName;
-        }
-
-        @Override
-        public String extractAuthenticationInfo(HttpServletRequest request) {
-            HttpSession session = request.getSession(false);
-            if (session != null) {
-                Object attribute = session.getAttribute(sessionAttributeName);
-                if (attribute instanceof String) {
-                    return (String) attribute;
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public void set(HttpServletRequest request,
-                HttpServletResponse response, String authData, 
AuthenticationInfo info) {
-            // store the auth hash as a session attribute
-            HttpSession session = request.getSession();
-            session.setAttribute(sessionAttributeName, authData);
-        }
-
-        @Override
-        public void clear(HttpServletRequest request,
-                HttpServletResponse response) {
-            HttpSession session = request.getSession(false);
-            if (session != null) {
-                session.removeAttribute(sessionAttributeName);
-            }
-        }
-
-    }
+       /**
+        * The request method required for user name and password submission by 
the form
+        * (value is "POST").
+        */
+       private static final String REQUEST_METHOD = "POST";
+
+       /**
+        * The last segment of the request URL for the user name and password 
submission
+        * by the form (value is "/j_security_check").
+        * <p>
+        * This name is derived from the prescription in the Servlet API 2.4
+        * Specification, Section SRV.12.5.3.1 Login Form Notes: <i>In order 
for the
+        * authentication to proceed appropriately, the action of the login 
form must
+        * always be set to <code>j_security_check</code>.</i>
+        */
+       private static final String REQUEST_URL_SUFFIX = "/j_security_check";
+
+       /**
+        * The name of the form submission parameter providing the name of the 
user to
+        * authenticate (value is "j_username").
+        * <p>
+        * This name is prescribed by the Servlet API 2.4 Specification, Section
+        * SRV.12.5.3 Form Based Authentication.
+        */
+       private static final String PAR_J_USERNAME = "j_username";
+
+       /**
+        * The name of the form submission parameter providing the password of 
the user
+        * to authenticate (value is "j_password").
+        * <p>
+        * This name is prescribed by the Servlet API 2.4 Specification, Section
+        * SRV.12.5.3 Form Based Authentication.
+        */
+       private static final String PAR_J_PASSWORD = "j_password";
+
+       /**
+        * Key in the AuthenticationInfo map which contains the domain on which 
the auth
+        * cookie should be set.
+        */
+       private static final String COOKIE_DOMAIN = "cookie.domain";
+
+       /**
+        * The factor to convert minute numbers into milliseconds used 
internally
+        */
+       private static final long MINUTES = 60L * 1000L;
+
+       /** default log */
+       private final Logger log = LoggerFactory.getLogger(getClass());
+
+       private AuthenticationStorage authStorage;
+
+       private String loginForm;
+
+       /**
+        * The timeout of a login session in milliseconds, converted from the
+        * configuration property {@link #PAR_AUTH_TIMEOUT} by multiplying with
+        * {@link #MINUTES}.
+        */
+       private long sessionTimeout;
+
+       /**
+        * The name of the credentials attribute which is set to the cookie 
data to
+        * validate.
+        */
+       private String attrCookieAuthData;
+
+       /**
+        * The {@link TokenStore} used to persist and check authentication data
+        */
+       private TokenStore tokenStore;
+
+       /**
+        * The {@link FormLoginModulePlugin} service registration created when 
this
+        * authentication handler is registered. If the login module plugin 
cannot be
+        * created this field is set to <code>null</code>.
+        */
+       private ServiceRegistration<?> loginModule;
+
+       /**
+        * If true, the handler will attempt to include the login form instead 
of doing
+        * a redirect.
+        */
+       private boolean includeLoginForm;
+
+       /**
+        * The resource resolver factory used to resolve the login form as a 
resource
+        */
+       @Reference(policy = ReferencePolicy.DYNAMIC, cardinality = 
ReferenceCardinality.OPTIONAL)
+       private volatile ResourceResolverFactory resourceResolverFactory;
+
+       /**
+        * If true the login form will be presented when the token expires.
+        */
+       private boolean loginAfterExpire;
+
+       private JaasHelper jaasHelper;
+
+       /**
+        * Extracts cookie/session based credentials from the request. Returns
+        * <code>null</code> if the handler assumes HTTP Basic authentication 
would be
+        * more appropriate, if no form fields are present in the request and 
if the
+        * secure user data is not present either in the cookie or an HTTP 
Session.
+        */
+       @Override
+       public AuthenticationInfo extractCredentials(HttpServletRequest 
request, HttpServletResponse response) {
+
+               AuthenticationInfo info = null;
+
+               // 1. try credentials from POST'ed request parameters
+               info = this.extractRequestParameterAuthentication(request);
+
+               // 2. try credentials from the cookie or session
+               if (info == null) {
+                       String authData = 
authStorage.extractAuthenticationInfo(request);
+                       if (authData != null) {
+                               if (tokenStore.isValid(authData)) {
+                                       info = createAuthInfo(authData);
+                               } else {
+                                       // clear the cookie, its invalid and we 
should get rid of it
+                                       // so that the invalid cookie isn't 
present on the authN
+                                       // operation.
+                                       authStorage.clear(request, response);
+                                       if (this.loginAfterExpire || 
AuthUtil.isValidateRequest(request)) {
+                                               // signal the 
requestCredentials method a previous login
+                                               // failure
+                                               
request.setAttribute(FAILURE_REASON, FormReason.TIMEOUT);
+                                               info = 
AuthenticationInfo.FAIL_AUTH;
+                                       }
+                               }
+                       }
+               }
+
+               return info;
+       }
+
+       /**
+        * Unless the <code>sling:authRequestLogin</code> to anything other than
+        * <code>Form</code> this method either sends back a 403/FORBIDDEN 
response if
+        * the <code>j_verify</code> parameter is set to <code>true</code> or 
redirects
+        * to the login form to ask for credentials.
+        * <p>
+        * This method assumes the <code>j_verify</code> request parameter to 
only be
+        * set in the initial username/password submission through the login 
form. No
+        * further checks are applied, though, before sending back the 
403/FORBIDDEN
+        * response.
+        */
+       @Override
+       public boolean requestCredentials(HttpServletRequest request, 
HttpServletResponse response) throws IOException {
+
+               // 0. ignore this handler if an authentication handler is 
requested
+               if (ignoreRequestCredentials(request)) {
+                       // consider this handler is not used
+                       return false;
+               }
+
+               // check the referrer to see if the request is for this handler
+               if (!AuthUtil.checkReferer(request, loginForm)) {
+                       // not for this handler, so return
+                       return false;
+               }
+
+               final String resource = 
AuthUtil.setLoginResourceAttribute(request, request.getRequestURI());
+
+               if (includeLoginForm && (resourceResolverFactory != null)) {
+                       ResourceResolver resourceResolver = null;
+                       try {
+                               resourceResolver = 
resourceResolverFactory.getAdministrativeResourceResolver(null);
+                               Resource loginFormResource = 
resourceResolver.resolve(loginForm);
+                               Servlet loginFormServlet = 
loginFormResource.adaptTo(Servlet.class);
+                               if (loginFormServlet != null) {
+                                       try {
+                                               
loginFormServlet.service(request, response);
+                                               return true;
+                                       } catch (ServletException e) {
+                                               log.error("Failed to include 
the form: " + loginForm, e);
+                                       }
+                               }
+                       } catch (LoginException e) {
+                               log.error(
+                                               "Unable to get a resource 
resolver to include for the login resource. Will redirect instead.");
+                       } finally {
+                               if (resourceResolver != null) {
+                                       resourceResolver.close();
+                               }
+                       }
+               }
+
+               HashMap<String, String> params = new HashMap<String, String>();
+               params.put(Authenticator.LOGIN_RESOURCE, resource);
+
+               // append indication of previous login failure
+               if (request.getAttribute(FAILURE_REASON) != null) {
+                       final Object jReason = 
request.getAttribute(FAILURE_REASON);
+                       @SuppressWarnings("rawtypes")
+                       final String reason = (jReason instanceof Enum) ? 
((Enum) jReason).name() : jReason.toString();
+                       params.put(FAILURE_REASON, reason);
+               }
+
+               try {
+                       AuthUtil.sendRedirect(request, response, 
request.getContextPath() + loginForm, params);
+               } catch (IOException e) {
+                       log.error("Failed to redirect to the login form " + 
loginForm, e);
+               }
+
+               return true;
+       }
+
+       /**
+        * Clears all authentication state which might have been prepared by 
this
+        * authentication handler.
+        */
+       @Override
+       public void dropCredentials(HttpServletRequest request, 
HttpServletResponse response) {
+               authStorage.clear(request, response);
+       }
+
+       // ---------- AuthenticationFeedbackHandler
+
+       /**
+        * Called after an unsuccessful login attempt. This implementation 
makes sure
+        * the authentication data is removed either by removing the cookie or 
by remove
+        * the HTTP Session attribute.
+        */
+       @Override
+       public void authenticationFailed(HttpServletRequest request, 
HttpServletResponse response,
+                       AuthenticationInfo authInfo) {
+
+               /*
+                * Note: This method is called if this handler provided 
credentials which cause
+                * a login failure
+                */
+
+               // clear authentication data from Cookie or Http Session
+               authStorage.clear(request, response);
+
+               // signal the reason for login failure
+               request.setAttribute(FAILURE_REASON, 
FormReason.INVALID_CREDENTIALS);
+       }
+
+       /**
+        * Called after successful login with the given authentication info. 
This
+        * implementation ensures the authentication data is set in either the 
cookie or
+        * the HTTP session with the correct security tokens.
+        * <p>
+        * If no authentication data already exists, it is created. Otherwise 
if the
+        * data has expired the data is updated with a new security token and a 
new
+        * expiry time.
+        * <p>
+        * If creating or updating the authentication data fails, it is 
actually removed
+        * from the cookie or the HTTP session and future requests will not be
+        * authenticated any longer.
+        */
+       @Override
+       public boolean authenticationSucceeded(HttpServletRequest request, 
HttpServletResponse response,
+                       AuthenticationInfo authInfo) {
+
+               /*
+                * Note: This method is called if this handler provided 
credentials which
+                * succeeded login into the repository
+                */
+
+               // ensure fresh authentication data
+               refreshAuthData(request, response, authInfo);
+
+               final boolean result;
+               // SLING-1847: only consider a resource redirect if this is a 
POST request
+               // to the j_security_check URL
+               if (REQUEST_METHOD.equals(request.getMethod()) && 
request.getRequestURI().endsWith(REQUEST_URL_SUFFIX)) {
+
+                       if 
(DefaultAuthenticationFeedbackHandler.handleRedirect(request, response)) {
+                               // terminate request, all done in the default 
handler
+                               result = false;
+                       } else {
+                               // check whether redirect is requested by the 
resource parameter
+                               final String targetResource = 
AuthUtil.getLoginResource(request, null);
+                               if (targetResource != null) {
+                                       try {
+                                               if (response.isCommitted()) {
+                                                       throw new 
IllegalStateException("Response is already committed");
+                                               }
+                                               response.resetBuffer();
+
+                                               StringBuilder b = new 
StringBuilder();
+                                               if 
(AuthUtil.isRedirectValid(request, targetResource)) {
+                                                       
b.append(targetResource);
+                                               } else if 
(request.getContextPath().length() == 0) {
+                                                       b.append("/");
+                                               } else {
+                                                       
b.append(request.getContextPath());
+                                               }
+                                               
response.sendRedirect(b.toString());
+                                       } catch (IOException ioe) {
+                                               log.error("Failed to send 
redirect to: " + targetResource, ioe);
+                                       }
+
+                                       // terminate request, all done
+                                       result = true;
+                               } else {
+                                       // no redirect, hence continue 
processing
+                                       result = false;
+                               }
+                       }
+               } else {
+                       // no redirect, hence continue processing
+                       result = false;
+               }
+
+               // no redirect
+               return result;
+       }
+
+       @Override
+       public String toString() {
+               return "Form Based Authentication Handler";
+       }
+
+       // --------- Force HTTP Basic Auth ---------
+
+       /**
+        * Returns <code>true</code> if this authentication handler should 
ignore the
+        * call to {@link #requestCredentials(HttpServletRequest, 
HttpServletResponse)}.
+        * <p>
+        * This method returns <code>true</code> if the {@link 
#REQUEST_LOGIN_PARAMETER}
+        * is set to any value other than "Form" (HttpServletRequest.FORM_AUTH).
+        */
+       private boolean ignoreRequestCredentials(final HttpServletRequest 
request) {
+               final String requestLogin = 
request.getParameter(REQUEST_LOGIN_PARAMETER);
+               return requestLogin != null && 
!HttpServletRequest.FORM_AUTH.equals(requestLogin);
+       }
+
+       /**
+        * Ensures the authentication data is set (if not set yet) and the 
expiry time
+        * is prolonged (if auth data already existed).
+        * <p>
+        * This method is intended to be called in case authentication 
succeeded.
+        *
+        * @param request
+        *            The current request
+        * @param response
+        *            The current response
+        * @param authInfo
+        *            The authentication info used to successful log in
+        */
+       private void refreshAuthData(final HttpServletRequest request, final 
HttpServletResponse response,
+                       final AuthenticationInfo authInfo) {
+
+               // get current authentication data, may be missing after first 
login
+               String authData = getCookieAuthData(authInfo);
+
+               // check whether we have to "store" or create the data
+               final boolean refreshCookie = needsRefresh(authData, 
this.sessionTimeout);
+
+               // add or refresh the stored auth hash
+               if (refreshCookie) {
+                       long expires = System.currentTimeMillis() + 
this.sessionTimeout;
+                       try {
+                               authData = null;
+                               authData = tokenStore.encode(expires, 
authInfo.getUser());
+                       } catch (InvalidKeyException e) {
+                               log.error(e.getMessage(), e);
+                       } catch (IllegalStateException e) {
+                               log.error(e.getMessage(), e);
+                       } catch (UnsupportedEncodingException e) {
+                               log.error(e.getMessage(), e);
+                       } catch (NoSuchAlgorithmException e) {
+                               log.error(e.getMessage(), e);
+                       }
+
+                       if (authData != null) {
+                               authStorage.set(request, response, authData, 
authInfo);
+                       } else {
+                               authStorage.clear(request, response);
+                       }
+               }
+       }
+
+       // --------- Request Parameter Auth ---------
+
+       private AuthenticationInfo 
extractRequestParameterAuthentication(HttpServletRequest request) {
+               AuthenticationInfo info = null;
+
+               // only consider login form parameters if this is a POST request
+               // to the j_security_check URL
+               if (REQUEST_METHOD.equals(request.getMethod()) && 
request.getRequestURI().endsWith(REQUEST_URL_SUFFIX)) {
+
+                       String user = request.getParameter(PAR_J_USERNAME);
+                       String pwd = request.getParameter(PAR_J_PASSWORD);
+
+                       if (user != null && pwd != null) {
+                               info = new 
AuthenticationInfo(HttpServletRequest.FORM_AUTH, user, pwd.toCharArray());
+                               info.put(AuthConstants.AUTH_INFO_LOGIN, new 
Object());
+
+                               // if this request is providing form 
credentials, we have to
+                               // make sure, that the request is redirected 
after successful
+                               // authentication, otherwise the request may be 
processed
+                               // as a POST request to the j_security_check 
page (unless
+                               // the j_validate parameter is set); but only 
if this is not
+                               // a validation request
+                               if (!AuthUtil.isValidateRequest(request)) {
+                                       
AuthUtil.setLoginResourceAttribute(request, request.getContextPath());
+                               }
+                       }
+               }
+
+               return info;
+       }
+
+       private AuthenticationInfo createAuthInfo(final String authData) {
+               final String userId = getUserId(authData);
+               if (userId == null) {
+                       return null;
+               }
+
+               final AuthenticationInfo info = new 
AuthenticationInfo(HttpServletRequest.FORM_AUTH, userId);
+
+               if (jaasHelper.enabled()) {
+                       // JcrResourceConstants.AUTHENTICATION_INFO_CREDENTIALS
+                       info.put("user.jcr.credentials", new 
FormCredentials(userId, authData));
+               } else {
+                       info.put(attrCookieAuthData, authData);
+               }
+
+               return info;
+       }
+
+       private String getCookieAuthData(final AuthenticationInfo info) {
+               Object data = info.get(attrCookieAuthData);
+               if (data instanceof String) {
+                       return (String) data;
+               }
+               return null;
+       }
+
+       // ---------- LoginModulePlugin support
+
+       private String getCookieAuthData(final Credentials credentials) {
+               if (credentials instanceof SimpleCredentials) {
+                       Object data = ((SimpleCredentials) 
credentials).getAttribute(attrCookieAuthData);
+                       if (data instanceof String) {
+                               return (String) data;
+                       }
+               } else if (credentials instanceof FormCredentials) {
+                       return ((FormCredentials) credentials).getAuthData();
+               }
+
+               // no SimpleCredentials or no valid attribute
+               return null;
+       }
+
+       boolean hasAuthData(final Credentials credentials) {
+               return getCookieAuthData(credentials) != null;
+       }
+
+       public boolean isValid(final Credentials credentials) {
+               String authData = getCookieAuthData(credentials);
+               if (authData != null) {
+                       return tokenStore.isValid(authData);
+               }
+
+               // no authdata, not valid
+               return false;
+       }
+
+       // ---------- SCR Integration 
----------------------------------------------
+
+       /**
+        * Called by SCR to activate the authentication handler.
+        *
+        * @throws InvalidKeyException
+        * @throws NoSuchAlgorithmException
+        * @throws IllegalStateException
+        * @throws UnsupportedEncodingException
+        */
+       protected void activate(FormAuthenticationHandlerConfig config, 
ComponentContext componentContext)
+                       throws InvalidKeyException, NoSuchAlgorithmException, 
IllegalStateException, UnsupportedEncodingException {
+
+               this.jaasHelper = new JaasHelper(this, 
componentContext.getBundleContext(), config);
+               this.loginForm = config.form_login_form();
+               log.info("Login Form URL {}", loginForm);
+
+               final String authName = config.form_auth_name();
+
+               String defaultCookieDomain = 
config.form_default_cookie_domain();
+               if (defaultCookieDomain.length() == 0) {
+                       defaultCookieDomain = null;
+               }
+
+               final String authStorage = config.form_auth_storage();
+               if 
(FormAuthenticationHandlerConfig.AUTH_STORAGE_SESSION_ATTRIBUTE.equals(authStorage))
 {
+                       this.authStorage = new SessionStorage(authName);
+                       log.info("Using HTTP Session store with attribute name 
{}", authName);
+               } else {
+                       this.authStorage = new CookieStorage(authName, 
defaultCookieDomain);
+                       log.info("Using Cookie store with name {}", authName);
+               }
+
+               this.attrCookieAuthData = config.form_credentials_name();
+               log.info("Setting Auth Data attribute name {}", 
attrCookieAuthData);
+
+               int timeoutMinutes = config.form_auth_timeout();
+               if (timeoutMinutes < 1) {
+                       timeoutMinutes = 
FormAuthenticationHandlerConfig.DEFAULT_AUTH_TIMEOUT;
+               }
+               log.info("Setting session timeout {} minutes", timeoutMinutes);
+               this.sessionTimeout = MINUTES * timeoutMinutes;
+
+               final String tokenFileName = config.form_token_file();
+               final File tokenFile = getTokenFile(tokenFileName, 
componentContext.getBundleContext());
+               final boolean fastSeed = config.form_token_fastseed();
+               log.info("Storing tokens in {}", tokenFile.getAbsolutePath());
+               this.tokenStore = new TokenStore(tokenFile, sessionTimeout, 
fastSeed);
+
+               this.loginModule = null;
+               if (!jaasHelper.enabled()) {
+                       try {
+                               this.loginModule = 
FormLoginModulePlugin.register(this, componentContext.getBundleContext());
+                       } catch (Throwable t) {
+                               log.info(
+                                               "Cannot register 
FormLoginModulePlugin. This is expected if Sling LoginModulePlugin services are 
not supported");
+                               log.debug("dump", t);
+                       }
+               }
+
+               this.includeLoginForm = config.useInclude();
+
+               this.loginAfterExpire = config.form_onexpire_login();
+       }
+
+       @Deactivate
+       protected void deactivate() {
+               if (jaasHelper != null) {
+                       jaasHelper.close();
+                       jaasHelper = null;
+               }
+
+               if (loginModule != null) {
+                       loginModule.unregister();
+                       loginModule = null;
+               }
+       }
+
+       /**
+        * Returns an absolute file indicating the file to use to persist the 
security
+        * tokens.
+        * <p>
+        * This method is not part of the API of this class and is package 
private to
+        * enable unit tests.
+        *
+        * @param tokenFileName
+        *            The configured file name, must not be null
+        * @param bundleContext
+        *            The BundleContext to use to make an relative file absolute
+        * @return The absolute file
+        */
+       File getTokenFile(final String tokenFileName, final BundleContext 
bundleContext) {
+               File tokenFile = new File(tokenFileName);
+               if (tokenFile.isAbsolute()) {
+                       return tokenFile;
+               }
+
+               tokenFile = bundleContext.getDataFile(tokenFileName);
+               if (tokenFile == null) {
+                       final String slingHome = 
bundleContext.getProperty("sling.home");
+                       if (slingHome != null) {
+                               tokenFile = new File(slingHome, tokenFileName);
+                       } else {
+                               tokenFile = new File(tokenFileName);
+                       }
+               }
+
+               return tokenFile.getAbsoluteFile();
+       }
+
+       /**
+        * Returns the user id from the authentication data. If the 
authentication data
+        * is a non-<code>null</code> value with 3 fields separated by an @ 
sign, the
+        * value of the third field is returned. Otherwise <code>null</code> is
+        * returned.
+        * <p>
+        * This method is not part of the API of this class and is package 
private to
+        * enable unit tests.
+        *
+        * @param authData
+        * @return
+        */
+       String getUserId(final String authData) {
+               if (authData != null) {
+                       String[] parts = TokenStore.split(authData);
+                       if (parts != null) {
+                               return parts[2];
+                       }
+               }
+               return null;
+       }
+
+       /**
+        * Refresh the cookie periodically.
+        *
+        * @param sessionTimeout
+        *            time to live for the session
+        * @return true or false
+        */
+       private boolean needsRefresh(final String authData, final long 
sessionTimeout) {
+               boolean updateCookie = false;
+               if (authData == null) {
+                       updateCookie = true;
+               } else {
+                       String[] parts = TokenStore.split(authData);
+                       if (parts != null && parts.length == 3) {
+                               long cookieTime = 
Long.parseLong(parts[1].substring(1));
+                               if (System.currentTimeMillis() + 
(sessionTimeout / 2) > cookieTime) {
+                                       updateCookie = true;
+                               }
+                       }
+               }
+               return updateCookie;
+       }
+
+       /**
+        * The <code>AuthenticationStorage</code> interface abstracts the API 
required
+        * to store the authentication data in an HTTP cookie or in an HTTP 
Session. The
+        * concrete class -- {@link CookieStorage} or {@link SessionStorage} -- 
is
+        * selected using the {@link FormAuthenticationHandler#PAR_AUTH_STORAGE}
+        * configuration parameter, {@link CookieStorage} by default.
+        */
+       private static interface AuthenticationStorage {
+               String extractAuthenticationInfo(HttpServletRequest request);
+
+               void set(HttpServletRequest request, HttpServletResponse 
response, String authData, AuthenticationInfo info);
+
+               void clear(HttpServletRequest request, HttpServletResponse 
response);
+       }
+
+       /**
+        * The <code>CookieStorage</code> class supports storing the 
authentication data
+        * in an HTTP Cookie.
+        */
+       private static class CookieStorage implements AuthenticationStorage {
+
+               /**
+                * The Set-Cookie header used to manage the login cookie.
+                *
+                * @see CookieStorage#setCookie(HttpServletRequest, 
HttpServletResponse, String,
+                *      String, int, String)
+                */
+               private static final String HEADER_SET_COOKIE = "Set-Cookie";
+
+               private final String cookieName;
+               private final String domainCookieName;
+               private final String defaultCookieDomain;
+
+               public CookieStorage(final String cookieName, final String 
defaultCookieDomain) {
+                       this.cookieName = cookieName;
+                       this.domainCookieName = cookieName + "." + 
COOKIE_DOMAIN;
+                       this.defaultCookieDomain = defaultCookieDomain;
+               }
+
+               @Override
+               public String extractAuthenticationInfo(HttpServletRequest 
request) {
+                       Cookie[] cookies = request.getCookies();
+                       if (cookies != null) {
+                               for (Cookie cookie : cookies) {
+                                       if 
(this.cookieName.equals(cookie.getName())) {
+                                               // found the cookie, so try to 
extract the credentials
+                                               // from it and reverse the 
base64 encoding
+                                               String value = 
cookie.getValue();
+                                               if (value.length() > 0) {
+                                                       try {
+                                                               return new 
String(Base64.decodeBase64(value), "UTF-8");
+                                                       } catch 
(UnsupportedEncodingException e1) {
+                                                               throw new 
RuntimeException(e1);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+
+                       return null;
+               }
+
+               @Override
+               public void set(HttpServletRequest request, HttpServletResponse 
response, String authData,
+                               AuthenticationInfo info) {
+                       // base64 encode to handle any special characters
+                       String cookieValue;
+                       try {
+                               cookieValue = 
Base64.encodeBase64URLSafeString(authData.getBytes("UTF-8"));
+                       } catch (UnsupportedEncodingException e1) {
+                               throw new RuntimeException(e1);
+                       }
+
+                       // send the cookie to the response
+                       String cookieDomain = (String) info.get(COOKIE_DOMAIN);
+                       if (cookieDomain == null || cookieDomain.length() == 0) 
{
+                               cookieDomain = defaultCookieDomain;
+                       }
+                       setCookie(request, response, this.cookieName, 
cookieValue, -1, cookieDomain);
+
+                       // send the cookie domain cookie if domain is not null
+                       if (cookieDomain != null) {
+                               setCookie(request, response, 
this.domainCookieName, cookieDomain, -1, cookieDomain);
+                       }
+               }
+
+               @Override
+               public void clear(HttpServletRequest request, 
HttpServletResponse response) {
+                       Cookie oldCookie = null;
+                       String oldCookieDomain = null;
+                       Cookie[] cookies = request.getCookies();
+                       if (cookies != null) {
+                               for (Cookie cookie : cookies) {
+                                       if 
(this.cookieName.equals(cookie.getName())) {
+                                               // found the cookie
+                                               oldCookie = cookie;
+                                       } else if 
(this.domainCookieName.equals(cookie.getName())) {
+                                               oldCookieDomain = 
cookie.getValue();
+                                       }
+                               }
+                       }
+
+                       // remove the old cookie from the client
+                       if (oldCookie != null) {
+                               setCookie(request, response, this.cookieName, 
"", 0, oldCookieDomain);
+                               if (oldCookieDomain != null && 
oldCookieDomain.length() > 0) {
+                                       setCookie(request, response, 
this.domainCookieName, "", 0, oldCookieDomain);
+                               }
+                       }
+               }
+
+               private void setCookie(final HttpServletRequest request, final 
HttpServletResponse response, final String name,
+                               final String value, final int age, final String 
domain) {
+
+                       final String ctxPath = request.getContextPath();
+                       final String cookiePath = (ctxPath == null || 
ctxPath.length() == 0) ? "/" : ctxPath;
+
+                       /*
+                        * The Servlet Spec 2.5 does not allow us to set the 
commonly used HttpOnly
+                        * attribute on cookies (Servlet API 3.0 does) so we 
create the Set-Cookie
+                        * header manually. See 
http://www.owasp.org/index.php/HttpOnly for information
+                        * on what the HttpOnly attribute is used for.
+                        */
+
+                       final StringBuilder header = new StringBuilder();
+
+                       // default setup with name, value, cookie path and 
HttpOnly
+                       header.append(name).append("=").append(value);
+                       header.append("; Path=").append(cookiePath);
+                       header.append("; HttpOnly"); // don't allow JS access
+
+                       // set the cookie domain if so configured
+                       if (domain != null) {
+                               header.append("; Domain=").append(domain);
+                       }
+
+                       // Only set the Max-Age attribute to remove the cookie
+                       if (age >= 0) {
+                               header.append("; Max-Age=").append(age);
+                       }
+
+                       // ensure the cookie is secured if this is an https 
request
+                       if (request.isSecure()) {
+                               header.append("; Secure");
+                       }
+
+                       response.addHeader(HEADER_SET_COOKIE, 
header.toString());
+               }
+       }
+
+       /**
+        * The <code>SessionStorage</code> class provides support to store the
+        * authentication data in an HTTP Session.
+        */
+       private static class SessionStorage implements AuthenticationStorage {
+               private final String sessionAttributeName;
+
+               SessionStorage(final String sessionAttributeName) {
+                       this.sessionAttributeName = sessionAttributeName;
+               }
+
+               @Override
+               public String extractAuthenticationInfo(HttpServletRequest 
request) {
+                       HttpSession session = request.getSession(false);
+                       if (session != null) {
+                               Object attribute = 
session.getAttribute(sessionAttributeName);
+                               if (attribute instanceof String) {
+                                       return (String) attribute;
+                               }
+                       }
+                       return null;
+               }
+
+               @Override
+               public void set(HttpServletRequest request, HttpServletResponse 
response, String authData,
+                               AuthenticationInfo info) {
+                       // store the auth hash as a session attribute
+                       HttpSession session = request.getSession();
+                       session.setAttribute(sessionAttributeName, authData);
+               }
+
+               @Override
+               public void clear(HttpServletRequest request, 
HttpServletResponse response) {
+                       HttpSession session = request.getSession(false);
+                       if (session != null) {
+                               session.removeAttribute(sessionAttributeName);
+                       }
+               }
+
+       }
 }
\ No newline at end of file
diff --git 
a/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerConfig.java
 
b/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerConfig.java
new file mode 100644
index 0000000..cbc0d86
--- /dev/null
+++ 
b/src/main/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerConfig.java
@@ -0,0 +1,86 @@
+/*
+ * 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.sling.auth.form.impl;
+
+import org.osgi.service.metatype.annotations.AttributeDefinition;
+import org.osgi.service.metatype.annotations.AttributeType;
+import org.osgi.service.metatype.annotations.ObjectClassDefinition;
+import org.osgi.service.metatype.annotations.Option;
+
+/**
+ * The configuration for the <code>FormAuthenticationHandler</code>
+ * 
+ * @see org.apache.sling.auth.form.impl.FormAuthenticationHandler
+ */
+@ObjectClassDefinition(name = "%auth.form.name", description = 
"%auth.form.description")
+public @interface FormAuthenticationHandlerConfig {
+
+       public static final String AUTH_STORAGE_SESSION_ATTRIBUTE = "session";
+       public static final int DEFAULT_AUTH_TIMEOUT = 30;
+
+       @AttributeDefinition(defaultValue = "sling.formauth", name = 
"%authName.name", description = "%authName.description")
+       String form_auth_name();
+
+       @AttributeDefinition(defaultValue = "cookie", options = { @Option(label 
= "Cookie", value = "cookie"),
+                       @Option(label = "Session Attribute", value = 
AUTH_STORAGE_SESSION_ATTRIBUTE) }, name = "%authStorage.name", description = 
"%authStorage.description")
+       String form_auth_storage();
+
+       @AttributeDefinition(defaultValue = "30", type = AttributeType.INTEGER, 
name = "%authTimeout.name", description = "%authTimeout.description")
+       int form_auth_timeout();
+
+       @AttributeDefinition(defaultValue = "sling.formauth", name = 
"%credentialsName.name", description = "%credentialsName.description")
+       String form_credentials_name();
+
+       @AttributeDefinition(name = "%defaultCookieDomain.name", description = 
"%defaultCookieDomain.description")
+       String form_default_cookie_domain();
+
+       @AttributeDefinition(defaultValue = 
AuthenticationFormServlet.SERVLET_PATH, name = "%loginForm.name", description = 
"%loginForm.description")
+       String form_login_form();
+
+       @AttributeDefinition(defaultValue = "false", type = 
AttributeType.BOOLEAN, name = "%onexpireLogin.name", description = 
"%onexpireLogin.description")
+       boolean form_onexpire_login();
+
+       @AttributeDefinition(defaultValue = "false", type = 
AttributeType.BOOLEAN, name = "%tokenFileFastseed.name", description = 
"%tokenFileFastseed.description")
+       boolean form_token_fastseed();
+
+       @AttributeDefinition(defaultValue = "cookie-tokens.bin", name = 
"%tokenFile.name", description = "%tokenFile.description")
+       String form_token_file();
+
+       @AttributeDefinition(defaultValue = "sufficient", options = { 
@Option(label = "Optional", value = "optional"),
+                       @Option(label = "Required", value = "required"), 
@Option(label = "Requisite", value = "requisite"),
+                       @Option(label = "Sufficient", value = "sufficient") }, 
name = "%jaasControlFlag.name", description = "%jaasControlFlag.description")
+       String jaas_controlFlag();
+
+       @AttributeDefinition(defaultValue = "1000", type = 
AttributeType.INTEGER, name = "%jaasRanking.name", description = 
"%jaasRanking.description")
+       int jaas_ranking();
+
+       @AttributeDefinition(defaultValue = "jackrabbit.oak", name = 
"%jaasRealm.name", description = "%jaasRealm.description")
+       String jaas_realmName();
+
+       @AttributeDefinition(defaultValue = {
+                       "/" }, cardinality = Integer.MAX_VALUE, name = 
"%path.name", description = "%path.description")
+       String[] path();
+
+       @AttributeDefinition(defaultValue = "0", type = AttributeType.INTEGER, 
name = "%service.ranking.name", description = "%service.ranking.description")
+       int service_ranking();
+
+       @AttributeDefinition(defaultValue = "false", type = 
AttributeType.BOOLEAN, name = "%useInclude.name", description = 
"%useInclude.description")
+       boolean useInclude();
+
+}
diff --git a/src/main/java/org/apache/sling/auth/form/impl/jaas/JaasHelper.java 
b/src/main/java/org/apache/sling/auth/form/impl/jaas/JaasHelper.java
index bb5a1b5..9b619c1 100644
--- a/src/main/java/org/apache/sling/auth/form/impl/jaas/JaasHelper.java
+++ b/src/main/java/org/apache/sling/auth/form/impl/jaas/JaasHelper.java
@@ -20,11 +20,13 @@
 package org.apache.sling.auth.form.impl.jaas;
 
 import java.util.Dictionary;
+import java.util.Hashtable;
 
 import javax.security.auth.spi.LoginModule;
 
 import org.apache.felix.jaas.LoginModuleFactory;
 import org.apache.sling.auth.form.impl.FormAuthenticationHandler;
+import org.apache.sling.auth.form.impl.FormAuthenticationHandlerConfig;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceRegistration;
@@ -40,19 +42,19 @@ public class JaasHelper {
     /**
      * login module service registration
      */
-    private final ServiceRegistration factoryRegistration;
+    private final ServiceRegistration<?> factoryRegistration;
 
     /**
      * Opens/Initializes the helper and registers the login module factory 
(LMF) service if possible.
      *
      * @param ctx        the bundle context
-     * @param properties properties that contain the jaas related LMF service 
properties.
+     * @param config properties that contain the jaas related LMF service 
properties.
      */
-    public JaasHelper(FormAuthenticationHandler authHandler, BundleContext 
ctx, Dictionary properties) {
+    public JaasHelper(FormAuthenticationHandler authHandler, BundleContext 
ctx, FormAuthenticationHandlerConfig config) {
         this.authHandler = authHandler;
         // we dynamically register the LoginModuleFactory for the case we 
detect a login module.
         if (hasSSOLoginModule(ctx)) {
-            factoryRegistration = registerLoginModuleFactory(ctx, properties);
+            factoryRegistration = registerLoginModuleFactory(ctx, config);
         } else {
             factoryRegistration = null;
         }
@@ -77,17 +79,17 @@ public class JaasHelper {
         }
     }
 
-    private ServiceRegistration registerLoginModuleFactory(BundleContext ctx, 
Dictionary properties) {
-        ServiceRegistration reg = null;
+    private ServiceRegistration<?> registerLoginModuleFactory(BundleContext 
ctx, FormAuthenticationHandlerConfig config) {
+        ServiceRegistration<?> reg = null;
         try {
-            java.util.Properties props = new java.util.Properties();
+            Dictionary<String, Object> props = new Hashtable<String,Object>();
             final String desc = "LoginModule Support for 
FormAuthenticationHandler";
             props.put(Constants.SERVICE_DESCRIPTION, desc);
             props.put(Constants.SERVICE_VENDOR, 
ctx.getBundle().getHeaders().get(Constants.BUNDLE_VENDOR));
 
-            props.put(LoginModuleFactory.JAAS_RANKING, 
properties.get(LoginModuleFactory.JAAS_RANKING));
-            props.put(LoginModuleFactory.JAAS_CONTROL_FLAG, 
properties.get(LoginModuleFactory.JAAS_CONTROL_FLAG));
-            props.put(LoginModuleFactory.JAAS_REALM_NAME, 
properties.get(LoginModuleFactory.JAAS_REALM_NAME));
+            props.put(LoginModuleFactory.JAAS_RANKING, config.jaas_ranking());
+            props.put(LoginModuleFactory.JAAS_CONTROL_FLAG, 
config.jaas_controlFlag());
+            props.put(LoginModuleFactory.JAAS_REALM_NAME, 
config.jaas_realmName());
             reg = ctx.registerService(LoginModuleFactory.class.getName(),
                     new LoginModuleFactory() {
                         public LoginModule createLoginModule() {
diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties 
b/src/main/resources/OSGI-INF/l10n/org.apache.sling.auth.form.impl.FormAuthenticationHandlerConfig.properties
similarity index 68%
rename from src/main/resources/OSGI-INF/metatype/metatype.properties
rename to 
src/main/resources/OSGI-INF/l10n/org.apache.sling.auth.form.impl.FormAuthenticationHandlerConfig.properties
index 7070cdb..7143726 100644
--- a/src/main/resources/OSGI-INF/metatype/metatype.properties
+++ 
b/src/main/resources/OSGI-INF/l10n/org.apache.sling.auth.form.impl.FormAuthenticationHandlerConfig.properties
@@ -31,34 +31,34 @@ path.description = Repository path for which this 
authentication handler \
  should be used by Sling. If this is empty, the authentication handler will \
  be disabled.
 
-form.login.form.name = Login Form
-form.login.form.description = The URL (without any context path prefix) to \
+loginForm.name = Login Form
+loginForm.description = The URL (without any context path prefix) to \
  redirect the client to to present the login form. The default value is \
  "/system/sling/form/login".
 
-form.auth.storage.name = Hash Storage
-form.auth.storage.description = The type of storage used to provide the \
+authStorage.name = Hash Storage
+authStorage.description = The type of storage used to provide the \
  authentication state. Valid values are cookie and session. The default value \
  (cookie) also applies if any setting other than the supported values is \
  configured.
 
-form.auth.name.name = Cookie/Attribute Name
-form.auth.name.description = The name of the Cookie or HTTP Session attribute \
+authName.name = Cookie/Attribute Name
+authName.description = The name of the Cookie or HTTP Session attribute \
  providing the authentication state. The default value is "sling.formauth".
 
-form.credentials.name.name = Credentials Attribute
-form.credentials.name.description = The name of the SimpleCredentials \
+credentialsName.name = Credentials Attribute
+credentialsName.description = The name of the SimpleCredentials \
  attribute used  to provide the authentication data to the LoginModulePlugin. \
  The default value is "sling.formauth".
 
-form.auth.timeout.name = Timeout
-form.auth.timeout.description = The number of minutes after which a login \
+authTimeout.name = Timeout
+authTimeout.description = The number of minutes after which a login \
  session times out. This value is used as the expiry time set in the \
  authentication data. The default value is 30 minutes. If the value is set \
  a value less than 1, the default value is used instead.
 
-form.token.file.name = Security Token File
-form.token.file.description = The name of the file used to persist the \
+tokenFile.name = Security Token File
+tokenFile.description = The name of the file used to persist the \
  security tokens. The default value is cookie-tokens.bin. This property \
  currently refers to a file stored in the file system. If the path is a \
  relative path, the file is either stored in the Authentication Handler bundle 
\
@@ -67,8 +67,8 @@ form.token.file.description = The name of the file used to 
persist the \
  working directory. In the future this file may be store in the JCR Repository 
\
  to support clustering scenarios.
 
-form.token.fastseed.name = Fast Seed Generator
-form.token.fastseed.description = Defines whether the random number generator \
+tokenFileFastseed.name = Fast Seed Generator
+tokenFileFastseed.description = Defines whether the random number generator \
  should be seeded with a fast but less secure method. If this property is not \
  set or is set to "false" the seed generator of the Java platform will be \
  used. By default the secure seed generator is used, which may block startup \
@@ -77,33 +77,33 @@ form.token.fastseed.description = Defines whether the 
random number generator \
 service.ranking.name = Ranking
 service.ranking.description = The relative ranking of this service.
 
-form.use.include.name = Include Form
-form.use.include.description = If true, this authentication handler will 
attempt \
+useInclude.name = Include Form
+useInclude.description = If true, this authentication handler will attempt \
  to include a Servlet resource at the login form path. If false, a redirect 
will \
  be used instead.
 
-form.onexpire.login.name = On Login Expire, Re-login
-form.onexpire.login.description = If true, when the form login expires the 
user \
+onexpireLogin.name = On Login Expire, Re-login
+onexpireLogin.description = If true, when the form login expires the user \
  will be prompted to re-login. If false they become an anonymous user. The 
default \
  is false.
  
-form.default.cookie.domain.name = Default Cookie Domain
-form.default.cookie.domain.description = The domain on which authentication 
cookies will \
+defaultCookieDomain.name = Default Cookie Domain
+defaultCookieDomain.description = The domain on which authentication cookies 
will \
  be set, unless overridden in the AuthenticationInfo object. The default is 
null \
  which means to set the cookie on the request domain.
 
-jaas.controlFlag.name = JAAS Control Flag
-jaas.controlFlag.description = Property name specifying whether or not a 
LoginModule is REQUIRED, REQUISITE, SUFFICIENT \
+jaasControlFlag.name = JAAS Control Flag
+jaasControlFlag.description = Property name specifying whether or not a 
LoginModule is REQUIRED, REQUISITE, SUFFICIENT \
   or OPTIONAL. Refer to the JAAS configuration documentation for more details 
around the meaning of these flags. \
   Jackrabbit Oak only.
 
-jaas.realmName.name = JAAS Realm
-jaas.realmName.description = Property name specifying the realm name (or 
application name) against which the LoginModule \
+jaasRealm.name = JAAS Realm
+jaasRealm.description = Property name specifying the realm name (or 
application name) against which the LoginModule \
   is be registered. If no realm name is provided then LoginModule is 
registered with a default realm as configured in \
   the Felix JAAS configuration. \
   Jackrabbit Oak only.
 
-jaas.ranking.name = JAAS Ranking
-jaas.ranking.description = Property name specifying the ranking (i.e. sort 
order) of the configured login module \
+jaasRanking.name = JAAS Ranking
+jaasRanking.description = Property name specifying the ranking (i.e. sort 
order) of the configured login module \
   entries. The entries are sorted in a descending order (i.e. higher value 
ranked configurations come first). \
   Jackrabbit Oak only.
diff --git 
a/src/test/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerTest.java
 
b/src/test/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerTest.java
index 2dfe487..7457cfc 100644
--- 
a/src/test/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerTest.java
+++ 
b/src/test/java/org/apache/sling/auth/form/impl/FormAuthenticationHandlerTest.java
@@ -36,7 +36,7 @@ import org.apache.sling.api.auth.Authenticator;
 import org.apache.sling.auth.core.spi.AuthenticationInfo;
 import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler;
 import org.hamcrest.Description;
-import org.hamcrest.text.StringStartsWith;
+import org.hamcrest.core.StringStartsWith;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.jmock.api.Action;

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to