You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomee.apache.org by Zachary Bedell <zb...@nycourts.gov> on 2016/10/04 16:26:08 UTC

EJB via ServerServlet, JAASRealm name must match WAR name or in server.xml

I've found what looks to be a mis-feature with JAAS authentication for EJB's.  I'm using the ServerServlet to call EJB's over http/s.  It looks like in order to work, the JAAS realm that authenticates the EJB user must either be named the same as the WAR that contains ServerServlet OR it must be defined globally in Tomcat's server.xml.  

Defining the JAAS realm in ServerServlet's WAR with any name other than the WAR's name fails with a strange, "java.rmi.RemoteException: Received invalid response code from server: 3".  Best I can tell, the '3' corresponds to org.apache.openejb.client.ResponseCodes.AUTH_DENIED, which for some reason gets marshalled back under a "javax.ejb.EJBException: Unknown Container Exception" with a cause of that RemoteException.  Possibly there's another problem here with marshalling back the error condition from an AUTH_DENIED, but I haven't dug into that.

The closest thing to a root cause I can find is the behavior in org.apache.tomee.catalina.TomcatSecurityService::findRealm which is called by login, ultimate called by org.apache.openejb.server.ejbd.EjbRequestHandler processRequest method (securityToken = securityService.login(authentication.getRealm(), authentication.getUser(), new String(authentication.getPassword())); // Line 171)

The findRealm method searches a Map from TomcatWebAppBuilder which appears to contain keys of the various archive names to their defined realms.  

The two ways that this works successfully are:

1) If the Realm that should be securing your EJB's is in the default conf/server.xml, the fallthrough that returns defaultRealm works.

2) If the Realm is named the same as the WAR's URI, then it'll be found in the Map within TomcatWebAppBuilder.


My (failing) environment looked like this:

ejb.war!META-INF/context.xml:

<Context>
  <Realm 
    className="org.apache.catalina.realm.JAASRealm" 
    appName="ucs_security"
    userClassNames="ucs.common.tomee.UcsUser"
    roleClassNames="ucs.common.tomee.UcsRole"
  />
</Context>


ejb.war!WEB-INF/web.xml:

<web-app version="3.1"
  xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    
    <servlet>
        <servlet-name>ServerServlet</servlet-name>
        <servlet-class>org.apache.openejb.server.httpd.ServerServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>ServerServlet</servlet-name>
        <url-pattern>/invoke/*</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>ejb</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>ejb-user</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <security-role>
        <role-name>ejb-user</role-name>
    </security-role>

    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>ucs_security</realm-name>
    </login-config>
</web-app>

And the client-side JAAS configuration also uses "ucs_security" as its realm name.

If I moved the <Realm/> tag from the WAR's context.xml into server.xml, EJB calls authenticated successfully as it become the defaultRealm.  That bound the entire server to that authentication realm which isn't desired.  If I rename all the "ucs_security" references to "ejb" (or presumably renamed the WAR itself to "ucs_security" though I didn't test that), then it finds the right realm & authenticates.

It seems like incorrect behavior to force the name of the authentication realm to be the name of the EAR with all of the other various parts of JAAS able to specify an arbitrary realm name.

Is this expected behavior, or have I done something silly I'm not seeing?  This is all with TomEE 7.0.1.

Thanks in advance,
Zac Bedell

Re: EJB via ServerServlet, JAASRealm name must match WAR name or in server.xml

Posted by Romain Manni-Bucau <rm...@gmail.com>.
Hi Zac,

this is true for EJB but not for the webapp security. Means that is you put
in login-config:realm-name "foo" and login using the http request then foo
will be in use.


Romain Manni-Bucau
@rmannibucau <https://twitter.com/rmannibucau> |  Blog
<https://blog-rmannibucau.rhcloud.com> | Old Wordpress Blog
<http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber
<http://www.tomitribe.com> | JavaEE Factory
<https://javaeefactory-rmannibucau.rhcloud.com>

2016-10-04 18:26 GMT+02:00 Zachary Bedell <zb...@nycourts.gov>:

> I've found what looks to be a mis-feature with JAAS authentication for
> EJB's.  I'm using the ServerServlet to call EJB's over http/s.  It looks
> like in order to work, the JAAS realm that authenticates the EJB user must
> either be named the same as the WAR that contains ServerServlet OR it must
> be defined globally in Tomcat's server.xml.
>
> Defining the JAAS realm in ServerServlet's WAR with any name other than
> the WAR's name fails with a strange, "java.rmi.RemoteException: Received
> invalid response code from server: 3".  Best I can tell, the '3'
> corresponds to org.apache.openejb.client.ResponseCodes.AUTH_DENIED, which
> for some reason gets marshalled back under a "javax.ejb.EJBException:
> Unknown Container Exception" with a cause of that RemoteException.
> Possibly there's another problem here with marshalling back the error
> condition from an AUTH_DENIED, but I haven't dug into that.
>
> The closest thing to a root cause I can find is the behavior in
> org.apache.tomee.catalina.TomcatSecurityService::findRealm which is
> called by login, ultimate called by org.apache.openejb.server.ejbd.EjbRequestHandler
> processRequest method (securityToken = securityService.login(authentication.getRealm(),
> authentication.getUser(), new String(authentication.getPassword())); //
> Line 171)
>
> The findRealm method searches a Map from TomcatWebAppBuilder which appears
> to contain keys of the various archive names to their defined realms.
>
> The two ways that this works successfully are:
>
> 1) If the Realm that should be securing your EJB's is in the default
> conf/server.xml, the fallthrough that returns defaultRealm works.
>
> 2) If the Realm is named the same as the WAR's URI, then it'll be found in
> the Map within TomcatWebAppBuilder.
>
>
> My (failing) environment looked like this:
>
> ejb.war!META-INF/context.xml:
>
> <Context>
>   <Realm
>     className="org.apache.catalina.realm.JAASRealm"
>     appName="ucs_security"
>     userClassNames="ucs.common.tomee.UcsUser"
>     roleClassNames="ucs.common.tomee.UcsRole"
>   />
> </Context>
>
>
> ejb.war!WEB-INF/web.xml:
>
> <web-app version="3.1"
>   xmlns="http://xmlns.jcp.org/xml/ns/javaee"
>   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
> http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
>
>     <servlet>
>         <servlet-name>ServerServlet</servlet-name>
>         <servlet-class>org.apache.openejb.server.httpd.
> ServerServlet</servlet-class>
>     </servlet>
>
>     <servlet-mapping>
>         <servlet-name>ServerServlet</servlet-name>
>         <url-pattern>/invoke/*</url-pattern>
>     </servlet-mapping>
>
>     <security-constraint>
>         <web-resource-collection>
>             <web-resource-name>ejb</web-resource-name>
>             <url-pattern>/*</url-pattern>
>         </web-resource-collection>
>         <auth-constraint>
>             <role-name>ejb-user</role-name>
>         </auth-constraint>
>         <user-data-constraint>
>             <transport-guarantee>CONFIDENTIAL</transport-guarantee>
>         </user-data-constraint>
>     </security-constraint>
>
>     <security-role>
>         <role-name>ejb-user</role-name>
>     </security-role>
>
>     <login-config>
>         <auth-method>BASIC</auth-method>
>         <realm-name>ucs_security</realm-name>
>     </login-config>
> </web-app>
>
> And the client-side JAAS configuration also uses "ucs_security" as its
> realm name.
>
> If I moved the <Realm/> tag from the WAR's context.xml into server.xml,
> EJB calls authenticated successfully as it become the defaultRealm.  That
> bound the entire server to that authentication realm which isn't desired.
> If I rename all the "ucs_security" references to "ejb" (or presumably
> renamed the WAR itself to "ucs_security" though I didn't test that), then
> it finds the right realm & authenticates.
>
> It seems like incorrect behavior to force the name of the authentication
> realm to be the name of the EAR with all of the other various parts of JAAS
> able to specify an arbitrary realm name.
>
> Is this expected behavior, or have I done something silly I'm not seeing?
> This is all with TomEE 7.0.1.
>
> Thanks in advance,
> Zac Bedell