Custom Security Context in JAX-RS

And the JAX-RS juggernaut continues ….

This blog briefly talks about how to override the default security related information associated with a JAX-RS request i.e. how to mess with the SecurityContext

Wait.. Security Context ?

  • Think of it as a JAX-RS abstraction over HTTPServletRequest for security related information only
  • Can be used for
    • figuring out how the caller was authenticated
    • extracting authenticated Principal info
    • role membership confirmation (programmatic authorization)
    • and whether or not the request was initiated securely (over HTTPS)

Ok, but why would I need a custom implementation ?

It helps when you have a custom authentication mechanism not implemented using standard Java EE security realm

  • your web container will not be aware of the authentication details
  • as a result, the SecurityContext instance will not contain the subject, role and other details (mentioned above)
  • a typical example is token based authentication based on custom (app specific) HTTP headers
@Priority(Priorities.AUTHENTICATION)
public class JWTAuthFilter implements ContainerRequestFilter{
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String authHeaderVal = requestContext.getHeaderString("Authorization");
//consume JWT i.e. execute signature validation
if(authHeaderVal.startsWith("Bearer")){
try {
validate(authHeaderVal.split(" ")[1]);
} catch (InvalidJwtException ex) {
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}else{
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}

Your RESTful application would definitely want to make use of the authenticated caller

  • the JAX-RS request pipeline needs to be aware of the associated ‘security context’
  • make use of it within its business logic

How to…

SecurityContext is an interface after all..

  • just implement it
  • inject it (using @Context) and use it in your resource methods
@Priority(Priorities.AUTHENTICATION)
public class AuthFilterWithCustomSecurityContext implements ContainerRequestFilter {
@Context
UriInfo uriInfo;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
String authHeaderVal = requestContext.getHeaderString("Auth-Token");
String subject = validateToken(authHeaderVal); //execute custom authentication
if (subject!=null) {
final SecurityContext securityContext = requestContext.getSecurityContext();
requestContext.setSecurityContext(new SecurityContext() {
@Override
public Principal getUserPrincipal() {
return new Principal() {
@Override
public String getName() {
return subject;
}
};
}
@Override
public boolean isUserInRole(String role) {
List<Role> roles = findUserRoles(subject);
return roles.contains(role);
}
@Override
public boolean isSecure() {
return uriInfo.getAbsolutePath().toString().startsWith("https");
}
@Override
public String getAuthenticationScheme() {
return "Token-Based-Auth-Scheme";
}
});
}
}
}

 

Cheers!

About Abhishek

Loves Go, NoSQL DBs and messaging systems
This entry was posted in Java EE and tagged , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s