9 Replies Latest reply on Jan 20, 2014 5:04 AM by jansi senthil

    remote EJB caller principal name always "anonymous"

    Philippe Marschall Expert

      When doing EJBContext.getCallerPrincipal().getName() in an EJB that is called over EJB demoting we always seem to get "anonymous". This is done with EAP 6.1.0.Alpha1.

       

      This is the EJB:

       

      @Singleton
      @ConcurrencyManagement(ConcurrencyManagementType.BEAN)
      public class WhoBean implements WhoAmI {
      
                @Resource
                private EJBContext context;
      
                @Override
                public String whoAmI() {
                          return context.getCallerPrincipal().getName();
                }
      
      }
      

       

       

      Thie is the client:

       

      public class Client {
      
                static {
                          Security.addProvider(new JBossSaslProvider());
                }
      
                public void run() {
                          this.configureClientWithPassword();
      
                          WhoAmI secured = this.doLookup(WhoAmI.class);
                          System.out.println(secured.whoAmI());
                }
      
      
                <T> T doLookup(Class<T> intefaceClass) {
                          try {
                                    Properties jndiProps = new Properties();
                                    jndiProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
                                    Context context = new InitialContext(jndiProps);
                                    String lookupName = "ejb:" +  "acme-ear" + "/" + "acme-ejb" + "//" + "WhoBean" + "!" + intefaceClass.getName();
                                    Object object = context.lookup(lookupName);
                                    return intefaceClass.cast(object);
                          } catch (NamingException e) {
                                    throw new RuntimeException(e);
                          }
                }
      
                private void configureClientWithPassword() {
                          Properties invokeProperties = new Properties();
                          invokeProperties.put("endpoint.name", "client-endpoint");
                          invokeProperties.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
                          invokeProperties.put("remote.connections", "default");
                          invokeProperties.put("remote.connection.default.host", "localhost");
                          invokeProperties.put("remote.connection.default.port", "4447");
                          invokeProperties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "true");
                          invokeProperties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_DISALLOWED_MECHANISMS", "JBOSS-LOCAL-USER");
                          invokeProperties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
                          invokeProperties.put("remote.connection.default.username", "test");
                          invokeProperties.put("remote.connection.default.password", "test");
      
                          EJBClientConfiguration ejbcc = new PropertiesBasedEJBClientConfiguration(invokeProperties);
                          ContextSelector<EJBClientContext> ejbCtxSel = new ConfigBasedEJBClientContextSelector(ejbcc);
                          EJBClientContext.setSelector(ejbCtxSel);
                }
      
                public static void main(String[] args) {
                          new Client().run();
                }
      
      }
      

       

       

      And this is the configuration we add to standalone.xml

       

                  <security-realm name="acmeRealm">
                      <authentication>
                          <jaas name="acme"/>
                      </authentication>
                  </security-realm>
      
                      <security-domain name="acme" cache-type="default">
                          <authentication>
                              <login-module code="Remoting" flag="optional">
                                  <module-option name="password-stacking" value="useFirstPass"/>
                              </login-module>
                              <login-module code="Simple" flag="required">
                                  <module-option name="password-stacking" value="useFirstPass"/>
                                  <module-option name="unauthenticatedIdentity" value="guest"/>
                              </login-module>
                          </authentication>
                      </security-domain>
      
              <subsystem xmlns="urn:jboss:domain:remoting:1.1">
                  <connector name="remoting-connector" socket-binding="remoting" security-realm="acmeRealm"/>
              </subsystem>
      

       

       

      Attached you'll find a project to reproduce the issue.

        • 1. Re: remote EJB caller principal name always "anonymous"
          jaikiran pai Master

          Your bean needs to be marked as secured (using any of the spec provided ways for the security related interceptors to play a role).

           

          As a first step, you could do something like:

           

          @Override

          @PermitAll
          public String whoAmI() {
             return context.getCallerPrincipal().getName();
          }

           

          That's just an example where you allow all roles to access that method. The presence of that @PermitAll security annotation will instruct the EJB container to bring into picture the EJB security interceptors. Take a look at this documentation for further details
          https://docs.jboss.org/author/display/AS72/Securing+EJBs

          • 2. Re: remote EJB caller principal name always "anonymous"
            jaikiran pai Master

            By the way:

            static {
                                Security.addProvider(new JBossSaslProvider());
                      }

            You don't need that anymore. You can remove it from your code.

            • 3. Re: remote EJB caller principal name always "anonymous"
              jaikiran pai Master

              jaikiran pai wrote:

               

              Your bean needs to be marked as secured (using any of the spec provided ways for the security related interceptors to play a role).

               

              As a first step, you could do something like:

              ...

              Then as a second step, you'll have to tell the container which security domain to use. If you don't specify one, it will use the "other" security domain. Looking at your code, you have your own security domain configured by the name of "acme". So your bean should now point the container to it using the @org.jboss.ejb3.annotation.SecurityDomain. Here's what the bean would look like:

               

              @Singleton
              @ConcurrencyManagement(ConcurrencyManagementType.BEAN)
              @org.jboss.ejb3.annotation.SecurityDomain("acme") // the one we have configured in the security subsystem
              public class WhoBean implements WhoAmI {
               
                        @Resource
                        private EJBContext context;
               
                        @Override
                        @PermitAll // just an example
                        public String whoAmI() {
                                  return context.getCallerPrincipal().getName();
                        }
               
              }
              
              2 of 2 people found this helpful
              • 4. Re: remote EJB caller principal name always "anonymous"
                Philippe Marschall Expert

                jaikiran pai wrote:

                ...

                 

                Thanks this fixes the problem. The reason our code was like this is because it worked like this in JBoss AS 5.1 / EAP 5. You didn't have to have @PermitAll having @SecurityDomain was enough. I'm a bit confused when it comes to realms vs domains. If I have the domain on the EJB why do I have to have a realm in the remoting connector that points to the domain? And if I have a realm in the remoting connector that points to the domain why do I have to have the domain on the EJB again?

                 

                What we actually need is a bit different. We need to have one of our EJBs not secured (used for creating the login screen) and the rest secured. What we would do in AS 5.1 / EAP 5 is leave out @SecurityDomain on the secured one and add it on the other. However my userstanding is that with AS 7.x / EAP 6.x we can't do this because if we want to have EJBs secured we need to have a realm in the remoting connector and if we don't want to have them secured we must not have a realm in the remoting connector. Am I wrong?

                • 5. Re: remote EJB caller principal name always "anonymous"
                  Kirill Lyzo Newbie

                  Phillippe, have you found confirmation for your question? We'd like to implement the same idea - one bean is unsecured while all the rest are secured. And we observe the same issue. If remoting subsystem doesn't have realm - all the EJBs are unsecured disregards what we have in ejb-jar.xml and jboss-ejb3.xml. And if realm is set for remoting - then even if mean of the bean marked as "for all" - you can't actually lookup bean itself without credentials. So is there a way to configure one bean unsecured (no credentials for both lookup and execute) and all the others secured?

                  • 6. Re: remote EJB caller principal name always "anonymous"
                    Philippe Marschall Expert

                    Kirill Lyzo wrote:

                     

                    Phillippe, have you found confirmation for your question? We'd like to implement the same idea - one bean is unsecured while all the rest are secured. And we observe the same issue. If remoting subsystem doesn't have realm - all the EJBs are unsecured disregards what we have in ejb-jar.xml and jboss-ejb3.xml. And if realm is set for remoting - then even if mean of the bean marked as "for all" - you can't actually lookup bean itself without credentials. So is there a way to configure one bean unsecured (no credentials for both lookup and execute) and all the others secured?

                    No, I haven't. We decided to change to application and remove the features that require unauthenticated calls. This is suboptimal but our options are quite limited.

                    • 7. Re: remote EJB caller principal name always "anonymous"
                      jaikiran pai Master

                      Kirill, welcome to the forums!

                      Kirill Lyzo wrote:

                       

                      Phillippe, have you found confirmation for your question? We'd like to implement the same idea - one bean is unsecured while all the rest are secured. And we observe the same issue. If remoting subsystem doesn't have realm - all the EJBs are unsecured disregards what we have in ejb-jar.xml and jboss-ejb3.xml. And if realm is set for remoting - then even if mean of the bean marked as "for all" - you can't actually lookup bean itself without credentials. So is there a way to configure one bean unsecured (no credentials for both lookup and execute) and all the others secured?

                      I think there's some confusion on what the authentication on the remoting-connector stands for.

                       

                      Starting AS7, every remote client interaction to the server requires an authentication/authorization. It doesn't have anything to do with EJBs (secured or not). The remoting connector that you see in the remoting subsystem (the one which use the ApplicationRealm) is what is used for the communication between the client and the server. Now when you are doing an invocation on a EJB hosted on the server, you are first trying to get access to the server itself (no EJB in the picture yet). This effectively requires that you pass along the relevant user credentials to get access to the server for communication.

                       

                      Now once you have successfully connected to the server, the EJB invocation comes into picture. The invocation on the EJB can either be secured (in which case the already established credentials are used) or can be unsecure (in which case no credentials are required). So you can selectively have certain EJBs to be secure and some other to be unsecure. We don't stop that.

                       

                      However, by default, we do stop unauthenticated/unauthorized access to the server itself, which is why you need the credentials to be passed along.

                      • 8. Re: remote EJB caller principal name always "anonymous"
                        Kirill Lyzo Newbie

                        Jaikaran, thank you for explanation. We are trying to implement the same idea described by Philippe. One EJB is fully accessible without any credentials at all - used for authentication. If user is authenticated - we provide him credentials to access other EJBs. This logic was implemented for Weblogic and now we are trying to migrate it to JBoss. So considering your explanation we want to disable authentication for remoting connector but still have secured EJBs. Is that possible?

                        • 9. Re: remote EJB caller principal name always "anonymous"
                          jansi senthil Newbie

                          Hi Jaikiran,

                           

                          I went through your comments. I am getting the same issue. A simple web application invoking an local EJB. Using JAAS security.

                          But in the EJB sessionCOntext, i am getting the name as anonymous.

                           

                          My Satndalone-xml

                          <subsystem xmlns="urn:jboss:domain:security:1.1">

                                      <security-domains>

                                          <security-domain name="other" cache-type="default">

                                              <authentication>

                                                  <login-module code="Remoting" flag="optional">

                                                      <module-option name="password-stacking" value="useFirstPass"/>

                                                  </login-module>

                                                  <login-module code="RealmUsersRoles" flag="required">

                                                      <module-option name="usersProperties" value="${jboss.server.config.dir}/application-users.properties"/>

                                                      <module-option name="rolesProperties" value="${jboss.server.config.dir}/application-roles.properties"/>

                                                      <module-option name="realm" value="ApplicationRealm"/>

                                                      <module-option name="password-stacking" value="useFirstPass"/>

                                                  </login-module>

                                              </authentication>

                                          </security-domain>

                           

                          I am invoking only local EJB. Kindly advice.