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:
source share