JASPIC Wildfly 9 validateRequest with session

Based on this Jaspic Example, I wrote the following validateRequest method for ServerAuthModule :

 public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { boolean authenticated = false; final HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage(); final String token = request.getParameter("token"); TokenPrincipal principal = (TokenPrincipal) request.getUserPrincipal(); Callback[] callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, (TokenPrincipal) null) }; if (principal != null) { callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, principal) }; authenticated = true; } else { if (token != null && token.length() == Constants.tokenLength) { try { principal = fetchUser(token); } catch (final Exception e) { throw (AuthException) new AuthException().initCause(e); } callbacks = new Callback[] { new CallerPrincipalCallback(clientSubject, principal), new GroupPrincipalCallback(clientSubject, new String[] { "aRole" }) }; messageInfo.getMap().put("javax.servlet.http.registerSession", "TRUE"); authenticated = true; } } if (authenticated) { try { handler.handle(callbacks); } catch (final Exception e) { throw (AuthException) new AuthException().initCause(e); } return SUCCESS; } return AuthStatus.SEND_FAILURE; } 

This works as expected for the first ejb call with @RolesAllowed("aRole") , but for the next call it doesn't work at all. Wildfly denies this error message:

 ERROR [org.jboss.as.ejb3.invocation] (default task-4) WFLYEJB0034: EJB Invocation failed on component TestEJB for method public java.lang.String com.jaspic.security.TestEJB.getPrincipalName(): javax.ejb.EJBAccessException: WFLYSEC0027: Invalid User 

If I'm right, the error occurs in: org.jboss.as.security.service.SimpleSecurityManager line 367 of the wilfly source code, due to line 405 , in which credential checked, but it is null .

This seems equal in Wildfly 8/9 / 10CR (other versions have not been tested).

Again, I'm not sure if I am doing it wrong, or if it is the same error as https://issues.jboss.org/browse/WFLY-4626 ? And is this generally a mistake, or is this the expected behavior?

+5
source share
1 answer

This sounds like an error to me, as the caller ID (caller / group Principal s) is stored in subsequent calls on the Internet, but not in the EJB container. My own JASPIC classes (which work correctly on GlassFish 4.1) for the same reason do not work on WildFly 9.0.2.Final and 10.0.0.CR4 when used with a simple servlet and SLSB, even with the last @PermitAll marked.

Since I myself am not familiar with WildFly's internal services, I cannot help you in this regard. If you cannot get this fix, the only workaround at the SAM level that I can think of right now would be to not use the javax.servlet.http.registerSession callback property, which apparently causes the problem, but instead has CallbackHandler register as the calling Principal and its group each time validateRequest(...) called. If applicable to your use case, you can attach this information to the HttpSession to speed things up a bit; otherwise repeat from scratch. So for example:

 public class Sam implements ServerAuthModule { // ... @Override public AuthStatus validateRequest(MessageInfo mi, Subject client, Subject service) throws AuthException { boolean authenticated = false; boolean attachAuthnInfoToSession = false; final String callerSessionKey = "authn.caller"; final String groupsSessionKey = "authn.groups"; final HttpServletRequest req = (HttpServletRequest) mi.getRequestMessage(); TokenPrincipal tp = null; String[] groups = null; String token = null; HttpSession hs = req.getSession(false); if (hs != null) { tp = (TokenPrincipal) hs.getAttribute(callerSessionKey); groups = (String[]) hs.getAttribute(groupsSessionKey); } Callback[] callbacks = null; if (tp != null) { callbacks = new Callback[] { new CallerPrincipalCallback(client, tp), new GroupPrincipalCallback(client, groups) }; authenticated = true; } else if (isValid(token = req.getParameter("token"))) { tp = newTokenPrincipal(token); groups = fetchGroups(tp); callbacks = new Callback[] { new CallerPrincipalCallback(client, tp), new GroupPrincipalCallback(client, groups) }; authenticated = true; attachAuthnInfoToSession = true; } if (authenticated) { try { handler.handle(callbacks); if (attachAuthnInfoToSession && ((hs = req.getSession(false)) != null)) { hs.setAttribute(callerSessionKey, tp); hs.setAttribute(groupsSessionKey, groups); } } catch (IOException | UnsupportedCallbackException e) { throw (AuthException) new AuthException().initCause(e); } return AuthStatus.SUCCESS; } return AuthStatus.SEND_FAILURE; } // ... @Override public void cleanSubject(MessageInfo mi, Subject subject) throws AuthException { // ... // just to be safe HttpSession hs = ((HttpServletRequest) mi.getRequestMessage()).getSession(false); if (hs != null) { hs.invalidate(); } } private boolean isValid(String token) { // whatever return ((token != null) && (token.length() == 10)); } private TokenPrincipal newTokenPrincipal(String token) { // whatever return new TokenPrincipal(token); } private String[] fetchGroups(TokenPrincipal tp) { // whatever return new String[] { "aRole" }; } } 

I tested the above versions of WildFly and in the way described above (i.e. with one servlet referencing one SLSB marked with @DeclareRoles / method-level @RolesAllowed ) and it seems to work as expected. Obviously, I cannot guarantee that this approach will not fail in another unexpected way.


See also:
+7
source

Source: https://habr.com/ru/post/1236266/


All Articles