Elytron security identity is not being propagated to EJB.

1,029 views
Skip to first unread message

Elia Zaides

unread,
Mar 23, 2023, 8:45:22 PM3/23/23
to WildFly

We are trying to migrate from Wildfly 24 to Wildfly 26, where we are migrating to Elyton security subsystem.

We were successfully able to migrate our JAAS configurations to JAAS Elytron Realm, the login modules are being successfully executed.


Yet when we create an ejb call, the EJBContext#getCallerPrincipal() is always anonymous, 


Any help with identifying what could be the possible reasons for the security identity not bening propagated to the EJB?




relevant configurations, structure of our ear file, and code samples are below:


Configuration in our standalone.xml:


<subsystem xmlns="urn:jboss:domain:ejb3:9.0">

    <application-security-domains>

        <application-security-domain name="company_security" security-domain="company_security-domain"/>

    </application-security-domains>

</subsystem>


<subsystem xmlns="urn:wildfly:elytron:15.1" final-providers="combined-providers" disallowed-providers="OracleUcrypto">

    <security-domains>

        <security-domain name="company_security-domain" default-realm="company_security-realm" permission-mapper="default-permission-mapper">

            <realm name="company_security-realm"/>

        </security-domain>

    </security-domains>


    <security-realms>

        <jaas-realm name="company_security-realm" entry="indicee-jaas-dummy" module="indicee-jaas">

            <file path="jaas.conf"/>

        </jaas-realm>


    </security-realms>

    <http>

        <http-authentication-factory name="company_security-http-auth" security-domain="company_security-domain" http-server-mechanism-factory="global">

            <mechanism-configuration>

                <mechanism mechanism-name="FORM">

                    <mechanism-realm realm-name="FSRealmUsers"/>

                </mechanism>

                <mechanism mechanism-name="FORM"/>

            </mechanism-configuration>

        </http-authentication-factory>        

    </http>

</subsystem>


<subsystem xmlns="urn:jboss:domain:undertow:12.0">

    <application-security-domains>

        <application-security-domain name="company_security" http-authentication-factory="company_security-http-auth"/>

    </application-security-domains>

</subsystem>


<subsystem xmlns="urn:jboss:domain:ee:6.0">

    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>

</subsystem>


Our Project structure:

myapp.ear

 |

  ------- web.war

  ------- webadmin.war

 | ------ services.jar (EJB Services)





web.war configuration:

--- jboss-web.xml

    <jboss-web>

        <security-domain>company_security</security-domain>

    </jboss-web>

--- web.xml

   ... 

    <filter>

        <filter-name>AuthenticationFilter</filter-name>

        ....

    </filter>    

    ...


webadmin.war configuration:

--- jboss-web.xml

    <jboss-web>

        <security-domain>company_security</security-domain>

    </jboss-web>

--- web.xml

   ... 

    <filter>

        <filter-name>AuthenticationFilter</filter-name>

        ....

    </filter>    

    ...    


services.jar configuration:

--- ejb-jar.xml

    <ejb-jar xmlns....>

        <description>Deployment descriptor</description>

        <display-name>EJB Services</display-name>        

    </ejb-jar>



Code inside AuthenticationFilter:

    public void doFilter(ServletRequest req, ServletResponse res, ... ) {

        

        HttpServletRequest request = (HttpServletRequest) req;

        HttpServletResponse response = (HttpServletRequest) res;

        try {

            request.login() ---> Invokes the elytron JAAS authentication process .... 

            // At this point the security domain is set, and not anonymous.

            // Invoking service enpoint that is an EJB, this will fail due to anonymous principal.

            Account account = accountService.getAccount();

        } catch(LoginException e) {

            response.sendError(403);

        }

    }




Code inside AccontService (EJB):

    @stateless

    @Local({AccountService.class})

    public class AccountServiceImpl implements AccountService {

        

        @Resource

        private EJBContext context;



        public Account getAccount() {

            // Principal is always anonymouse here 

            Principal principal = context.getCallerPrincipal()

            

            // .. rest of the code logic

        }

    }

Miha Štemberger

unread,
Mar 24, 2023, 5:37:33 AM3/24/23
to WildFly
Not sure if this is the same issue as I have had, but more info can be found at: https://groups.google.com/g/wildfly/c/kUxRRipfYV4 . What you are probably interested is this:

Currently, with the elytron-oidc-client subsystem, it's only possible to propagate the identity from the web layer to the EJB layer when the EJB is contained in the same WAR. If the EJB is located outside the WAR, the identity won't be propagated.

However, the ability to propagate the identity when the EJB is located in another deployment is something that we are in the process of adding. Please keep an eye on WFLY-16793 (and https://github.com/wildfly/wildfly/pull/16552) for updates.

We have also just recently updated the documentation to remove the section you mentioned about the Keycloak adapter:

Br,
Miha


petek, 24. marec 2023 ob 01:45:22 UTC+1 je oseba Elia Zaides napisala:

Elia Zaides

unread,
Mar 24, 2023, 2:32:38 PM3/24/23
to WildFly
Thanks a lot Miha, for your quick reply!

We use the default JAAS Realm that is being provided, thought the problem of code being located in different war files might be the same issue. 

Is there any solution \ workaround to this with the JAAS realm?

Elia Zaides

unread,
Mar 27, 2023, 8:33:00 PM3/27/23
to WildFly
Bumping up this question, as it becomes critical for our migration process. Is there any way in wildfly 26.1.3 to configure security-domain propagation between ejb and a war file, that are both in the same ear ? Or it is only being implemented as part of: https://issues.redhat.com/browse/WFCORE-6190 ?

Diana Krepinska

unread,
Mar 29, 2023, 6:26:31 AM3/29/23
to WildFly
hello Elia,

I am not sure about the usage of AuthenticationFilter, is it needed? Is it meant to provide authentication functionality, or is related to https://docs.jboss.org/picketlink/2/2.6.0.CR5/reference/html/sect-HTTP_Authentication.html ? Can it be removed and let elytron handle the authentication process, sending 403 responses etc?

Elia Zaides

unread,
Mar 29, 2023, 1:55:13 PM3/29/23
to WildFly
Hi Diana,

AuthenticationFilter has some additional logic before and after invoking the request.login() , not related picketlink. 

Thanks a lot, Elia

Elia Zaides

unread,
Mar 29, 2023, 3:54:31 PM3/29/23
to WildFly
Another related information and question, is that when invoking request.login(), despite the login is successful (and will eventually return true, and that SecurityDomain is set to non-anonymous principal. 

The flow of the execution is a little bit strange, as this method will call HttpAuthenticator -> which will create a ServerAuthenticationContext in a try resource block -> which as part of its close() method, eventually invokes logout methods of the LoginModules due to: https://github.com/wildfly-security/wildfly-elytron/blob/1.19.x/auth/server/base/src/main/java/org/wildfly/security/auth/server/ServerAuthenticationContext.java#L2101

Is it a bug, why the logout method is being called despite a successful login. Should \ can we use a different method instead of request.login() when using Elytron?

Diana Krepinska

unread,
Mar 30, 2023, 7:35:55 AM3/30/23
to WildFly
You mentioned that SecurityDomain is set to non anonymous principal. What does that mean? Can you obtain the security identity with SecurityIdentity identity = SecurityDomain.getCurrent().getCurrentSecurityIdentity(); and use one of its runAs methods it exposes https://wildfly-security.github.io/wildfly-elytron/documentation/api/current/org/wildfly/security/auth/server/SecurityIdentity.html for the invocation of the EJB ?

Elia Zaides

unread,
Mar 30, 2023, 9:43:54 AM3/30/23
to Diana Krepinska, WildFly
Yes,  I tried to use the RunAs method, but it did not propagate to the EJB, maybe because it is in a different class loader?

--
You received this message because you are subscribed to a topic in the Google Groups "WildFly" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/wildfly/EsB4sTZZa7I/unsubscribe.
To unsubscribe from this group and all its topics, send an email to wildfly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/wildfly/865ecafa-e7b3-4372-9de3-262a643534fcn%40googlegroups.com.

Elia Zaides

unread,
Mar 30, 2023, 10:38:34 AM3/30/23
to WildFly
Adding a little bit information:

I tried to run:
Account currentAccount =
     SecurityDomain.getCurrent().getCurrentSecurityIdentity().runAsFunction(
         (x) -> accountService.getAccount(), null);


Account - Is our application internal class.
accountSrv - is the EJB that we call from our AuthenticatorFilter, the instance is being injected through @EJB annotation.


SecurityDomain.getCurrent() - on the EJB side equals to null. 

Diana Krepinska

unread,
Mar 30, 2023, 1:41:58 PM3/30/23
to WildFly
Is your EJB secured with some security annotation? You can define a security domain for the EJB with @SecurityDomain annotation on top of the class. You can take a look at these quickstarts:


to see if you are missing anything to secure your EJB.

Elia Zaides

unread,
Apr 3, 2023, 1:58:11 AM4/3/23
to WildFly
Thanks Diana for the references! I was missing @SecurityDomain annotation on my EJB.

What is the recommended way to access the current security identity from EJB, should I use SecurityDomain.getuCurrent().getCurrentIdentity , or there is other preferred way instead of invoking the static getCurrent() method ?

Diana Krepinska

unread,
Apr 4, 2023, 4:27:32 AM4/4/23
to WildFly
To obtain the current security identity the SecurityDomain.getCurrent().getCurrentSecurityIdentity() is recommended. To obtain the principal from EJB you can use context.getCallerPrincipal also
Reply all
Reply to author
Forward
0 new messages