Open darranl opened 3 years ago
Jakarta Authentication is clear about the usage of the MessageInfo
to share state between calls to a ServerAuthModule
, but not super clear with respect to state in the CallbackHandler
.
We have already seen that this leads to some portability issues; Soteria considers the CallbackHandler
completely stateless and assumes all state is stored in either thread locals or in the Subject
.
This brings us to a second state issue. The assumption now would be only "state is not in the CallbackHandler
", but a step beyond that is saying "state must be in the Subject
"
(from https://github.com/eclipse-ee4j/authentication/issues/110#issuecomment-830020432)
Well would it be unreasonable to discuss some minimal requirements on the resulting Subject? It seems as though it would be useful to have some common expectations set for the resulting Subject.
From Soteria this is roughly what current implementations do:
private Principal getVendorCallerPrincipal(Principal principal, boolean isEjb) {
switch (principal.getClass().getName()) {
case "org.glassfish.security.common.PrincipalImpl": // GlassFish/Payara
return getAuthenticatedPrincipal(principal, "ANONYMOUS", isEjb);
case "weblogic.security.principal.WLSUserImpl": // WebLogic
return getAuthenticatedPrincipal(principal, "<anonymous>", isEjb);
case "com.ibm.ws.security.authentication.principals.WSPrincipal": // Liberty
return getAuthenticatedPrincipal(principal, "UNAUTHENTICATED", isEjb);
// JBoss EAP/WildFly convention 1 - single top level principal of the below type
case "org.jboss.security.SimplePrincipal":
return getAuthenticatedPrincipal(principal, "anonymous", isEjb);
// JBoss EAP/WildFly convention 2 - the one and only principal in group called CallerPrincipal
case "org.jboss.security.SimpleGroup":
if (principal.getName().equals("CallerPrincipal") && principal.getClass().getName().equals("org.jboss.security.SimpleGroup")) {
Enumeration<? extends Principal> groupMembers = null;
try {
groupMembers = (Enumeration<? extends Principal>) Class.forName(className("org.jboss.security.SimpleGroup"))
.getMethod("members")
.invoke(principal);
} catch (Exception e) {
}
if (groupMembers != null && groupMembers.hasMoreElements()) {
return getAuthenticatedPrincipal(groupMembers.nextElement(), "anonymous", isEjb);
}
}
break;
case "org.apache.tomee.catalina.TomcatSecurityService$TomcatUser": // TomEE
try {
Principal tomeePrincipal = (Principal) Class.forName(className("org.apache.catalina.realm.GenericPrincipal"))
.getMethod("getUserPrincipal")
.invoke(
Class.forName(className("org.apache.tomee.catalina.TomcatSecurityService$TomcatUser"))
.getMethod("getTomcatPrincipal")
.invoke(principal));
return getAuthenticatedPrincipal(tomeePrincipal, "guest", isEjb);
} catch (Exception e) {
}
break;
}
if (CallerPrincipal.class.isAssignableFrom(principal.getClass())) {
return principal;
}
return null;
}
The easiest thing to say is perhaps that "some vendor specific representation of the caller principal and groups" must be present in the subject. The CallerPrincipalCallback
or GroupPrincipalCallback
are currently able to write these into the Subject
. The test to see if they are stored correctly would be to have both these two callbacks being able to retrieve exactly what they wrote into it.
so say (pseudo code)
handle CallerPrincipalCallback subject write fooWritten
string fooRead = handle CallerPrincipalCallback subject read
assert fooRead == fooWritten
I am going to put together some examples, IMO there are some parts of the API to consider before we get to the CallbackHandler. For the CallbackHandler there are three areas state may be relevent:
@darranl time is running out quickly for Jakarta Authentication 3.0 and Jakarta EE 10. Do we still want to address something here for 3.0 though? I think at this point with about 2 weeks to go we can only really go for the low hanging fruit.
This issue is to explore and clarify the state expectations of the Jakarta Authentication APIs and the parameters passed to those APIs.
This is to follow up on some discussions regarding state in the CallbackHandler but I think we should also consider some of the Authentication APIs where state may be shared.