I have implemented a ContainerRequestFilter
that performs JWT-based authentication:
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
AuthenticationResult authResult = ...
if (authResult.isSuccessful()) {
// Client successfully authenticated.
// Now update the security context to be the augmented security context that contains information read from the JWT.
requestContext.setSecurityContext(new JwtSecurityContect(...));
} else {
// Client provided no or an invalid authentication token.
// Deny request by sending a 401 response.
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
}
As you can see, I update the SecurityContext
of the request, setting it to be an instance of my own custom implementation (JwtSecurityContext
) if authentication succeeds. This implementation adds extra authentication and authorization data, which I would like to later access in my subsequent filter(s) and my resource methods.
I have also implemented an AuthorizationFilter
that is invoked immediately after the AuthenticationFilter
. Here, I can access the updated JwtSecurityContext
just fine.
However, I am having problems when I try to inject the JwtSecurityContext
into a resource (method).
I am currently using Jersey, and I've read the following in its documentation:
The
SecurityContext
can be directly retrieved fromContainerRequestContext
viagetSecurityContext()
method. You can also replace the defaultSecurityContext
in a request context with a custom one using thesetSecurityContext(SecurityContext)
method. If you set a customSecurityContext
instance in yourContainerRequestFilter
, this security context instance will be used for injection into JAX-RS resource class fields. This way you can implement a custom authentication filter that may setup your ownSecurityContext
to be used. To ensure the early execution of your custom authentication request filter, set the filter priority to AUTHENTICATION using constants fromPriorities
. An early execution of you authentication filter will ensure that all other filters, resources, resource methods and sub-resource locators will execute with your customSecurityContext
instance.
I try to inject the JwtSecurityContext
into a resource method like so:
@Path("/somepath")
public class SomeResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<SomeItem> getItems(@Context SecurityContext securityContext) {
// securityContext is of type 'SecurityContextInjectee'
}
}
As the comment indicates, the runtime type of the securityContext
variable becomes SecurityContextInjectee
. From debugging, I've observed that this wraps a ContainerRequest
which in turn wraps my JwtSecurityContext
. However, there are no getters, and I do not want to use reflection to drill down this object hierarchy, so I don't know how to get a hold on my JwtSecurityContext
.
I have tried changing @Context SecurityContext securityContext
to @Context JwtSecurityContext jwtSecurityContext
, but if I do this, the variable becomes null
. I have also tried field injection, but this behaves the same way.
Am I heading down a wrong path? Should I not be accessing my custom SecurityContext
in my resource method? One alternative could be to wrap all my data in the Principal
implementation I return from getUserPrincipal
in my JwtSecurityContext
. I suppose the proxy (SecurityContextInjectee
) would forward the call to its underlying JwtSecurityContext
and hence return my Principal
, but I am not sure, and ultimately I would prefer to use my JwtSecurityContext
instead of wrapping these values in a Principal
implementation.
You can inject the ContainerRequestContext
(as mentioned in this post) and just get the SecurityContext
from there.
public List<SomeItem> getItems(@Context ContainerRequestContext context) {
JwtSecurityContext sec = (JwtSecurityContext)context.getSecurityContext();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With