7 Replies Latest reply on Apr 16, 2012 2:42 AM by ropalka

    JBoss not honoring @PermitAll on EJB3 Endpoint

    abhi0123

      I have an EJB3 WebService Endpoint secured using @DeclareRoles and @RolesAllowed. It is packaged as an war, with deployment descriptors jboss-ejb3.xml and jboss-webservices.xml. When I invoke a method marked @PermitAll from the standalone client, it fails with 401 response. The method invocation is successful when credentials are provided. Problem is, credentials should not be required for a method marked @PermitAll.

       

      I have intentionally omitted the handler code for brevity. If someone wants to see, I'll provide in a follow up post.

       

      TimeService.java


      {code}

      @Stateless

      @WebService(name = "Time", serviceName = "TimeService", portName = "TimeServicePort")

      @HandlerChain(file = "handler-chain.xml")

      @DeclareRoles({ "AppUser" })

      public class TimeService {

       

        @WebMethod

        @PermitAll

                public Time getCurrentTime() {

                          return new Time();

                }

       

        /* HttpBasicAuthenticationHandler authenticates this request */

        @WebMethod

                public Time getCurrentTimeAfterHttpBasicAuthentication() {

                          return getCurrentTime();

                }

       

        @WebMethod

        @RolesAllowed("AppUser")

                public Time getCurrentTimeAfterDeclarativeRoleBasedAuthorization() {

                          return getCurrentTime();

                }

      }

      {code}

       

       

      handler-chain.xml (located in the same directory as the WebService Endpoint above)

       

      {code:xml}

      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

      <javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"

        xmlns:xsd="http://www.w3.org/2001/XMLSchema">

        <javaee:handler-chain>

        <javaee:handler>

                                    <javaee:handler-class>edu.certification.abhijitsarkar.ocewsd.jaxws.utility.handler.SOAPRequestHandler

        </javaee:handler-class>

        </javaee:handler>

        <javaee:handler>

                                    <javaee:handler-class>edu.certification.abhijitsarkar.ocewsd.jaxws.ejb.webservice.handler.HttpBasicAuthenticationHandler

        </javaee:handler-class>

        </javaee:handler>

        <javaee:handler>

                                    <javaee:handler-class>edu.certification.abhijitsarkar.ocewsd.jaxws.ejb.webservice.handler.ProgrammaticAuthenticationHandler

        </javaee:handler-class>

        </javaee:handler>

        </javaee:handler-chain>

      </javaee:handler-chains>

      {code}

       

      jboss-ejb3.xml

       

      {code:xml}

      <?xml version="1.1" encoding="UTF-8"?>

      <jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"

        xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xmlns:c="urn:clustering:1.0"

        xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-ejb3-2_0.xsd http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd"

        version="3.1" impl-version="2.0">

        <assembly-descriptor xmlns="http://java.sun.com/xml/ns/javaee">

        <security:security xmlns:security="urn:security">

        <!-- domain name set up in JBoss $JBOSS_HOME/standalone/configuration/standalone.xml -->

        <security:security-domain>other</security:security-domain>

        <ejb-name>TimeService</ejb-name>

        </security:security>

        </assembly-descriptor>

      </jboss:ejb-jar>

      {code}

       

      jboss-webservices.xml

       

      {code:xml}

      <webservices xmlns="http://www.jboss.com/xml/ns/javaee"

        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"

        xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss_webservices_1_0.xsd">

        <context-root>/jaxws-ejb-1.0</context-root>

        <port-component>

        <ejb-name>TimeService</ejb-name>

        <port-component-uri>/TimeService</port-component-uri>

        <auth-method>BASIC</auth-method>

        <transport-guarantee>NONE</transport-guarantee>

        <secure-wsdl-access>false</secure-wsdl-access>

        </port-component>

      </webservices>

      {code}

       

      Client.java

       

      {code}

      public class Client {

       

                public Time_Type getCurrentTime(String soapAction) {

                          Time time = getPort();

                          BindingProvider bp = (BindingProvider) time;

                          // commenting out the credentials throws following error

                              // bp.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "user");

                          // bp.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");

                          setSoapAction(soapAction, bp);

                          return time.getCurrentTime();

                }

      }

      {code}

       

      Stacktrace

       

      {code}

      com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized

                at com.sun.xml.ws.transport.http.client.HttpTransportPipe.checkStatusCode(HttpTransportPipe.java:321)

                at com.sun.xml.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:270)

                at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:228)

                at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:143)

                at com.sun.xml.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:110)

                at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961)

                at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910)

                at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873)

                at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775)

                at com.sun.xml.ws.client.Stub.process(Stub.java:429)

                at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:168)

                at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:119)

                at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:102)

                at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:151)

                at $Proxy30.getCurrentTime(Unknown Source)

                at edu.certification.abhijitsarkar.ocewsd.jaxws.ejb.webservice.client.Client.getCurrentTime(Client.java:29)

                at edu.certification.abhijitsarkar.ocewsd.jaxws.ejb.webservice.client.ClientTest.testGetCurrentTime(ClientTest.java:17)

                at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

                at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

                at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

                at java.lang.reflect.Method.invoke(Method.java:597)

                at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)

                at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)

                at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)

                at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)

                at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263)

                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68)

                at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)

                at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)

                at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)

                at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)

                at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)

                at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)

                at org.junit.runners.ParentRunner.run(ParentRunner.java:300)

                at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)

                at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)

                at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

      {code}

       

      application-users.properties

       

      Abhijit$ tail -5 application-users.properties

      # is for illustration only and does not correspond to a usable password.

      #

      #admin=2a0923285184943425d1f53ddd58ec7a

      user=8544a03c79aee5b1c99458d83ee0f9e0

      guest=1bb6b7c18b5c1dab17f5141fa398905a

       

       

      application-roles.properties

       

      Abhijit$ tail -5 application-roles.properties

      #

      #admin=PowerUser,BillingAdmin,

      #guest=guest

      user=AppUser

      guest=AppGuest

       

        • 1. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
          ropalka

          Have a look to the followin tests:

           

          jboss-as/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/ws/authentication

           

          The Git repo is: http://github.com/jbossas/jboss-as

          • 2. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
            abhi0123

            Richard Opalka wrote:

             

            Have a look to the followin tests:

             

            jboss-as/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/ws/authentication

             

            The Git repo is: http://github.com/jbossas/jboss-as

            I did and the commit demonstrates the exact same problem I pointed out. The test case is passing security credentials even for a @PermitAll method and you shouldn't need any.

             

             

            {code}

            public class EJBEndpoint implements EJBEndpointIface {

             

                public String hello(String input) {

                    return "Hello " + input + "!";

                }

               

                @PermitAll

                public String helloForAll(String input) {

                    return "Hello " + input + "!";

                }

            }

            {code}

             

             

            {code}

            @Test

                public void accessHelloForAllWithValidRole1() throws Exception {

                    URL wsdlURL = new URL(baseUrl, "/jaxws-authentication-ejb3/EJB3AuthService?wsdl");

             

                    Service service = Service.create(wsdlURL, serviceName);

                    EJBEndpointIface proxy = service.getPort(EJBEndpointIface.class);

             

                    Map<String, Object> reqContext = ((BindingProvider) proxy).getRequestContext();

                    reqContext.put(BindingProvider.USERNAME_PROPERTY, "user1");

                    reqContext.put(BindingProvider.PASSWORD_PROPERTY, "password1");

             

                    final String result = proxy.helloForAll("World");

                    Assert.assertEquals("Hello World!", result);

                }

            {code}

            • 3. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
              abhi0123

              I was slightly wrong. Apparently @PermitAll means all unauthorized, not all unauthenticated. It'd require a valid user but would accept any role. On the other hand, an unannotated method should allow unauthenticated access which isn't happening. Attached is a test project that demonstrates the problem. It depends on a remote JBoss AS 7 instance with the following users-*.properties files:

               

              I will create a JIRA.

               

              {code}

              Abhijit$ tail -5 application-users.properties

              # is for illustration only and does not correspond to a usable password.

              #

              #admin=2a0923285184943425d1f53ddd58ec7a

              user=8544a03c79aee5b1c99458d83ee0f9e0

              guest=1bb6b7c18b5c1dab17f5141fa398905a

              {code}

               

               

              {code}

              Abhijit$ tail -5 application-roles.properties

              #

              #admin=PowerUser,BillingAdmin,

              #guest=guest

              user=AppUser

              guest=AppGuest

              {code}

              • 4. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
                abhi0123
                • 5. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
                  ropalka

                  The issue have been rejected.

                  See comment on the JIRA.

                  Useful article can be found here:

                   

                  http://java.dzone.com/articles/understanding-web-security

                  • 6. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
                    abhi0123

                    Richard Opalka wrote:

                     

                    The issue have been rejected.

                    See comment on the JIRA.

                    Useful article can be found here:

                     

                    http://java.dzone.com/articles/understanding-web-security

                    The web.xml certainly helped. I've 2 questions:

                    1. Is there a way I can view the generated web.xml?
                    2. How is the realm managed? Is it created and destroyed along with the application? I certainly did not create a realm by that name.
                    • 7. Re: JBoss not honoring @PermitAll on EJB3 Endpoint
                      ropalka

                      1) There's no way to see generated web.xml ATM

                      2) The 'EJBWebServiceEndpointServlet Realm' is automagically generated and yes,

                      it's created & destroyed along with the application.