Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spanning user information across multiple EJBs

With javax.security.Principal you can retrieve the user information at any point by injecting the EJBContext with @Resource.

What I am trying to do is add extra information which would be specific to my application and to my users as part of the Principal. I also tried to include this information in the contextData() of the EJBContext, but this only lasts for the EJB lifecycle rather than in multiple EJB calls.

Is there any way of extending the Principal to add any extra information? I would prefer not to use ThreadLocal or modify all my EJBs signature to pass this information.

like image 661
Gonzalo Garcia Lasurtegui Avatar asked Nov 14 '22 13:11

Gonzalo Garcia Lasurtegui


1 Answers

Finally worked around this one. Custom Principals can be created in JBoss AS. It is enough with creating a class that implements java.security.Principal and add custom attributes and getters/setters.

Then, when configuring the login module (e.g. DatabaseServerLoginModule) a module-option in the login-config.xml file just add a principalClass option:

<application-policy name="my-security-domain">
     <authentication>
     <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required">
          <module-option name="principalClass">com.custom.security.MyCustomPrincipal</module-option>
...

Now the problem is that due to an existing bug in JBoss, a call to an injected EJBContext.getCallerPrincipal() will not return the custom Principal but a plain instance of SimplePrincipal! But good news is that this can be solved by the following JAAS code that allows the inspection of the EJB container authentication info:

try {
      Subject subject = (Subject) PolicyContext.getContext("javax.security.auth.Subject.container");
      Set<Group> subjectGroups = subject.getPrincipals(Group.class);
      Iterator<Group> iter = subjectGroups.iterator();
      while (iter.hasNext()) {
        Group group = iter.next();
        String name = group.getName();
        if (name.equals("CallerPrincipal")) {
          Enumeration<? extends Principal> members = group.members();
          if (members.hasMoreElements()) {
            context = members.nextElement();
            myCustomPrincipal = (MyCustomPrincipal) context;
          }
        }
      }
    } catch (PolicyContextException e) {
        ....
    }

I wrapped the above code in a POJO that I can inject in my EJBs to get the Principal similarly as the EJBContext class does.

like image 71
Gonzalo Garcia Lasurtegui Avatar answered Nov 16 '22 04:11

Gonzalo Garcia Lasurtegui