Custom AuthenticationHandler and LoginModule on AEM6

Avatar

Avatar

boser87

Avatar

boser87

boser87

15-10-2015

Hi,

I'm trying to implement a custom AuthenticationHandler (http://sling.apache.org/documentation/the-sling-engine/authentication/authentication-authenticationh...) that extracts credentials from the request and authenticates them against an external service (let's say a REST API). I have implemented the AuthenticationHandler interface following this guide http://www.wemblog.com/2013/03/how-to-create-custom-authentication.html and the LoginModulePlugin interface (https://sling.apache.org/apidocs/sling6/org/apache/sling/jcr/jackrabbit/server/security/LoginModuleP...). When I call the path uder authentication my AuthenticationHandler is correctly called (extractCredentials). My problem is that the LoginModule's AuthenticationPlugin is not fired when the AuthenticationInfo is returned by extractCredentials. Any why I get this wrong behavior? I'm appending below the code for reference.


Thank you!

AuthenticationHandler

import java.io.IOException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.ComponentContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.felix.scr.annotations.Activate; 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.AuthenticationFeedbackHandler; import org.apache.sling.auth.core.spi.AuthenticationHandler; import org.apache.sling.auth.core.spi.AuthenticationInfo; import org.apache.sling.auth.core.spi.DefaultAuthenticationFeedbackHandler; @Component(metatype = true, immediate = true, label = "Custom Auth Handler", description="Authenticates User Against a REST Service") @Service @Properties({ @Property(name = AuthenticationHandler.PATH_PROPERTY, value = "/content/custom-commerce-it/it/j_custom_security_check"), @Property(name = AuthenticationHandler.TYPE_PROPERTY, value = CustomAuthenticationHandler.AUTH_TYPE, propertyPrivate = true), @Property(name = Constants.SERVICE_VENDOR, value = "Custom"), @Property(name = Constants.SERVICE_DESCRIPTION, value = "Custom Auth Handler") }) public class CustomAuthenticationHandler extends DefaultAuthenticationFeedbackHandler implements AuthenticationHandler, AuthenticationFeedbackHandler { private final Logger log = LoggerFactory.getLogger(this.getClass()); protected static final String AUTH_TYPE = "CUSTOM_AUTH"; private ServiceRegistration loginModule; @Activate protected void activate(ComponentContext componentContext) { log.debug("*** CustomAuthenticationHandler activate ***"); try { this.loginModule = CustomLoginModule.register(this, componentContext.getBundleContext()); } catch (Throwable t) { log.error("Error while activating CustomAuthenticationHandler!!!", t); } } @Override public void dropCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException { log.debug("*** CustomAuthenticationHandler dropCredentials ***"); } @Override public AuthenticationInfo extractCredentials(HttpServletRequest request, HttpServletResponse response) { log.debug("*** CustomAuthenticationHandler extractCredentials ***"); AuthenticationInfo authInfo = new AuthenticationInfo(CustomAuthenticationHandler.AUTH_TYPE, "userId", "pwd".toCharArray()); return authInfo; } @Override public boolean requestCredentials(HttpServletRequest request, HttpServletResponse response) throws IOException { log.debug("*** CustomAuthenticationHandler requestCredentials ***"); response.sendRedirect("/"); return true; } @Override public boolean authenticationSucceeded(HttpServletRequest request, HttpServletResponse response, AuthenticationInfo authInfo) { log.debug("*** CustomAuthenticationHandler authenticationSucceeded ***"); return super.authenticationSucceeded(request, response, authInfo); } @Override public void authenticationFailed(HttpServletRequest request, HttpServletResponse response, AuthenticationInfo authInfo) { log.debug("*** CustomAuthenticationHandler authenticationFailed ***"); super.authenticationFailed(request, response, authInfo); } }

LoginModulePlugin

import java.security.Principal; import java.util.Hashtable; import java.util.Map; import javax.jcr.Credentials; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.FailedLoginException; import javax.security.auth.login.LoginException; import org.apache.sling.jcr.jackrabbit.server.security.AuthenticationPlugin; import org.apache.sling.jcr.jackrabbit.server.security.LoginModulePlugin; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceRegistration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CustomLoginModule implements LoginModulePlugin { private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * The {@link CustomAuthenticationHandler} used to validate the credentials * and its contents. */ private final CustomAuthenticationHandler authHandler; /** * Creates an instance of this class and registers it as a * <code>LoginModulePlugin</code> service to handle login requests with * <code>SimpleCredentials</code> provided by the * {@link CustomAuthenticationHandler}. * * @param authHandler The {@link CustomAuthenticationHandler} providing *            support to validate the credentials * @param bundleContext The <code>BundleContext</code> to register the *            service * @return The <code>ServiceRegistration</code> of the registered service for *         the {@link CustomAuthenticationHandler} to unregister the service *         on shutdown. */ static ServiceRegistration register( final CustomAuthenticationHandler authHandler, final BundleContext bundleContext) { CustomLoginModule plugin = new CustomLoginModule(authHandler); Hashtable<String, Object> properties = new Hashtable<String, Object>(); properties.put(Constants.SERVICE_DESCRIPTION, "LoginModulePlugin Support for CustomAuthenticationHandler"); return bundleContext.registerService(LoginModulePlugin.class.getName(), plugin, properties); } /** * Private constructor called from * {@link #register(CustomAuthenticationHandler, BundleContext)} to create an * instance of this class. * * @param authHandler The {@link CustomAuthenticationHandler} used to validate *            the credentials attribute */ private CustomLoginModule(final CustomAuthenticationHandler authHandler) { this.authHandler = authHandler; } @Override public boolean canHandle(Credentials arg0) { log.debug("*** CustomLoginModule canHandle ***"); return true; } @Override public void doInit(CallbackHandler arg0, Session arg1, Map arg2) throws LoginException { log.debug("*** CustomLoginModule doInit ***"); } @Override public AuthenticationPlugin getAuthentication(Principal arg0, Credentials arg1) throws RepositoryException { log.debug("*** CustomLoginModule getAuthentication ***"); return new AuthenticationPlugin() { public boolean authenticate(Credentials credentials) throws RepositoryException { log.debug("*** CustomLoginModule authenticate ***"); return true; } }; } @Override public Principal getPrincipal(Credentials arg0) { log.debug("*** CustomLoginModule getPrincipal ***"); return null; } @Override public int impersonate(Principal arg0, Credentials arg1) throws RepositoryException, FailedLoginException { log.debug("*** CustomLoginModule impersonate ***"); return 0; } }
View Entire Topic

Avatar

Avatar

Anand_Bisht

Avatar

Anand_Bisht

Anand_Bisht

15-10-2015

Hi Stefano, are you able to to implement custom login successfully?