I am struggling to understand when and how to use the different interfaces.
They seem to be quite similar, with some minor differences in method names to dynamically check security roles or retrieve the Principal, but - as far as I am currently understanding - are only accessible in their specific context.
I am trying to implement fine grained authorization with specific requirements. Mainly the roles are not stored in the tokens, but must be read from a table in the database.
Therefore I have an implementation of IdentityStore
that provides a CallerPrincipal with all available roles.
The IdentityStore is used by my HttpAuthenticationMechanism
implementation, which is fairly simple, thus all it does is for valid requests to call HttpMessageContext.notifyContainerAboutLogin
to push the CallerPrincipal into the SecurityContext - as far as I know.
Because there are a lot of generic endpoints in the codebase with path parameters, that decide which role has to be checked I need a generic way of checking if the user is in a role depending on the value of some path segments of the requested uri.
I created a method interceptor for that, where I want to access the SecurityContext
, but both interfaces have their problems here:
@Interceptor
public class RolesAllowedInterceptor {
@Context
private UriInfo uriInfo;
// this injection is always null
@Context
private javax.security.enterprise.SecurityContext securityContext;
// this injection works
@Context
private javax.ws.rs.core.SecurityContext securityContext;
@AroundInvoke
public Object validate(InvocationContext ctx) throws Exception {
... // read path param to retrieve role and check SecurityContext.isUserInRole()
}
}
- The injection of javax.security.enterprise.SecurityContext does not work. I assume the reason for this is, that the interceptor is called in a JAX-RS context.
- The injection of javax.ws.rs.core.SecurityContext works (my assumption in 1. is based on this). But when
SecurityContext.isUserInRole(String)
is called, the debugger shows, that the Principal does not have any of the groups (roles in my business context) that were assigned via myIdentityStore
implementation and thus the validation incorrectly fails.
I am currently using another approach with ContainerRequestFilter
to set the javax.ws.rs.core.SecurityContext
explicitly, which is working fine for the interceptor, but not with the javax.annotation.security.RolesAllowed
annotation. For that I shifted the invocation of my IdentityStore
into the filter, because I obviously do not want to call it twice.
I am not looking for complete code examples/solutions.
I am merely trying to understand why there are different interfaces of SecurityContext
, as the Java Docs do not elaborate on that.
And therefore hopefully understand how I can use RolesAllowed
for static endpoints and my interceptor for generic endpoints, without the need of a ContainerRequestFilter
to set the SecurityContext for the later.
--
For context: I am using Payara Micro and jakartaee-api:8.0.0