soteria icon indicating copy to clipboard operation
soteria copied to clipboard

App-mem-custom-form securityContext looping

Open glassfishrobot opened this issue 7 years ago • 7 comments

I am trying to implement the loginbacking according to the App-mem-custom-form and when I run:

   @Inject
   SecurityContext securityContext;

   FacesContext context = FacesContext.getCurrentInstance();
   Credential credential = new UsernamePasswordCredential(username, new Password(password));

   AuthenticationStatus status = securityContext.authenticate(
               getRequest(context),
               getResponse(context),
               withParams()
                       .credential(credential));

   private static HttpServletResponse getResponse(FacesContext context) {
       return (HttpServletResponse) context
               .getExternalContext()
               .getResponse();
   }

   private static HttpServletRequest getRequest(FacesContext context) {
       return (HttpServletRequest) context
               .getExternalContext()
               .getRequest();
   }

Instead of returning status(NOT_DONE, SEND_CONTINUE, SUCCESS, or SEND_FAILURE) it loops back and runs securityContext.authenticate infinitely. I have tried with both:

    import javax.security.enterprise.SecurityContext;
    import org.glassfish.soteria.SecurityContextImpl;

and I get the same looping issue with both. Hopefully just a maven dependancy issue on my part but I thought i'd check if anyone else was having this issue.

pom.txt

glassfishrobot avatar Dec 22 '17 16:12 glassfishrobot

  • Issue Imported From: https://github.com/javaee/security-soteria/issues/202
  • Original Issue Raised By:@VincentMystery
  • Original Issue Assigned To: Unassigned

glassfishrobot avatar May 25 '18 05:05 glassfishrobot

@VincentMystery Commented (P.S. I am running a wildfly 11.0.0 server, and here is the log output when it loops:

soteria.SecurityContextImpl.authenticate(SecurityContextImpl.java:106)
at configuration.LoginBacking.login(LoginBacking.java:75)
	at sun.reflect.GeneratedMethodAccessor41.invoke(ReflectionUtil.java:181)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.sun.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:181)
	at com.sun.el.parser.AstValue.invoke(AstValue.java:289)
	at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:304)
	at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
	at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
	at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:40)
	at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:50)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:87)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:790)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1282)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
	at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
	at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
	at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:274)
	at io.undertow.servlet.handlers.ServletInitialHandler.dispatchToPath(ServletInitialHandler.java:209)
	at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImpl(RequestDispatcherImpl.java:221)
	at io.undertow.servlet.spec.RequestDispatcherImpl.forwardImplSetup(RequestDispatcherImpl.java:147)
	at io.undertow.servlet.spec.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:111)
	at io.undertow.servlet.handlers.security.ServletFormAuthenticationMechanism.servePage(ServletFormAuthenticationMechanism.java:145)
	at io.undertow.security.impl.FormAuthenticationMechanism.sendChallenge(FormAuthenticationMechanism.java:176)
	at io.undertow.security.impl.SecurityContextImpl$ChallengeSender.transition(SecurityContextImpl.java:296)
	at io.undertow.security.impl.SecurityContextImpl$ChallengeSender.transition(SecurityContextImpl.java:314)
	at io.undertow.security.impl.SecurityContextImpl$ChallengeSender.access$300(SecurityContextImpl.java:279)
	at io.undertow.security.impl.SecurityContextImpl.sendChallenges(SecurityContextImpl.java:130)
	at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:102)
	at io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:107)
	at io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:92)
	at io.undertow.servlet.spec.HttpServletRequestImpl.authenticate(HttpServletRequestImpl.java:416)
	at org.glassfish.soteria.mechanisms.jaspic.Jaspic.authenticate(Jaspic.java:112)
	at org.glassfish.soteria.SecurityContextImpl.authenticate(SecurityContextImpl.java:106)
at configuration.LoginBacking.login(LoginBacking.java:75)
	at sun.reflect.GeneratedMethodAccessor41.invoke(ReflectionUtil.java:181)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at com.sun.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:181)

glassfishrobot avatar Dec 22 '17 16:12 glassfishrobot

@arjantijms Commented From the stack it's clear that an Undertow native authentication mechanism is being installed (or defaulted to):

at io.undertow.security.impl.FormAuthenticationMechanism.sendChallenge(FormAuthenticationMechanism.java:176)

This particular authentication mechanism happens to forward to the same view from which you call securityContext.authenticate which (I think) makes use of the same request/post data and thus invokes the login method again, hence the loop.

Did you install a Java EE Security authentication mechanism?

glassfishrobot avatar Dec 22 '17 18:12 glassfishrobot

@VincentMystery Commented Thank you for your help, I don't believe I installed two authentication mechanisms. I was trying to implement form biased authentication:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>Solid Building Solutions Application</display-name>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>
    
    <welcome-file-list>
        <welcome-file>/index.xhtml</welcome-file>
    </welcome-file-list>

    <context-param>
        <param-name>primefaces.FONT_AWESOME</param-name>
        <param-value>true</param-value>
    </context-param>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>user</web-resource-name>
            <url-pattern>/user/*</url-pattern>
            <http-method>GET</http-method>
        </web-resource-collection>

        <auth-constraint>
            <role-name>EMPLOYEE</role-name>
            <role-name>ADMIN</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>admin</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
            <http-method>PUT</http-method>
            <http-method>DELETE</http-method>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>EMPLOYEE</role-name>
            <role-name>ADMIN</role-name>
        </auth-constraint>
    </security-constraint>

    <security-role>
        <role-name>EMPLOYEE</role-name>
    </security-role>
    <security-role>
        <role-name>ADMIN</role-name>
    </security-role>

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login.xhtml</form-login-page>
            <form-error-page>/error.xhtml</form-error-page>
        </form-login-config>
    </login-config>

    <!--<servlet>-->
        <!--<servlet-name>RFIDResource</servlet-name>-->
        <!--<servlet-class>Servlets.RFIDResource</servlet-class>-->
    <!--</servlet>-->
        <!---->
    <!--<servlet-mapping>-->
        <!--<servlet-name>RFIDResource</servlet-name>-->
        <!--<url-pattern>/RFIDResource</url-pattern>-->
    <!--</servlet-mapping>-->

</web-app>

And then I am using javax.security.enterprise and Sorteria as per the example projects.

glassfishrobot avatar Dec 27 '17 16:12 glassfishrobot

@arjantijms Commented

<login-config>
        <auth-method>FORM</auth-method>

This will cause io.undertow.security.impl.FormAuthenticationMechanism to be installed, which causes the looping here.

The idea is to have an authentication mechanism installed that's Java EE Security aware. I.e. using:

@FormAuthenticationMechanismDefinition(
    loginToContinue = @LoginToContinue(
        loginPage="/login-servlet",
        errorPage="/login-error-servlet"
    )

See: https://github.com/javaee/security-soteria/blob/master/test/app-mem-form/src/main/java/org/glassfish/soteria/test/ApplicationConfig.java#L47

glassfishrobot avatar Dec 27 '17 17:12 glassfishrobot

@VincentMystery Commented Thank you very much for your help. Your suggestion worked and fixed the looping issue. Now I just get a blank page that says "forbidden" when I try to go to a restricted page instead of the login form. This is most likely an issue with my setup and not the JSR.

glassfishrobot avatar Jan 03 '18 17:01 glassfishrobot

@VincentMystery do you need any more help? Can we safely closed this issue?

ggam avatar May 25 '18 18:05 ggam