Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shiro: How to write a test for an endpoint protected with @RequiresRoles?

Tags:

java

jax-rs

shiro

Say I have this resource:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.shiro.authz.annotation.RequiresAuthentication;
import org.apache.shiro.authz.annotation.RequiresRoles;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

@Path("/authhello")
@Api(value = "hello", description = "Simple endpoints for testing api authentification",
    hidden = true)
@Produces(MediaType.APPLICATION_JSON)
@RequiresAuthentication
public class AuthenticatedHelloWorldResource {

  private static final String READ = "READ";
  private static final String WRITE = "WRITE";

  @GET
  @ApiOperation(value = "helloworld",
      notes = "Simple hello world.",
      response = String.class)
  @RequiresRoles(READ)
  public Response helloWorld() {
    String hello = "Hello world!";
    return Response.status(Response.Status.OK).entity(hello).build();
  }

  @GET
  @Path("/{param}")
  @ApiOperation(value = "helloReply",
      notes = "Returns Hello you! and {param}",
      response = String.class)
  @RequiresRoles(WRITE)
  public Response getMsg(@PathParam("param") String msg) {
    String output = "Hello you! " + msg;
    return Response.status(Response.Status.OK).entity(output).build();
  }
}

Should I write tests that confirm that certain (test) users get a response from the endpoints, and certain users don't? And if so: How can I write those tests? I've tried something like this:

import javax.ws.rs.core.Application;

import org.glassfish.jersey.server.ResourceConfig;
import org.junit.Test;

import com.cognite.api.shiro.AbstractShiroTest;

import static org.junit.Assert.assertEquals;

public class AuthenticatedHelloWorldTest extends AbstractShiroTest {

  @Override
  protected Application configure() {
    return new ResourceConfig(AuthenticatedHelloWorldResource.class);
  }

  @Test
  public void testAuthenticatedReadHelloWorld() {
    final String hello = target("/authhello").request().get(String.class);
    assertEquals("Hello world!", hello);
  }

  @Test
  public void testAuthenticatedWriteHelloWorld() {
    final String hello = target("/authhello/test").request().get(String.class);
    assertEquals("Hello you! test", hello);
  }

}

but I'm not sure how to actually test the function of the @RequiresRoles-annotation. I've read Shiro's page on testing, but I haven't been able to write a failing test (e.g. a test for a subject that does not have the WRITE role trying to access /authhello/test). Any tips would be appreciated.

like image 383
L42 Avatar asked Oct 06 '17 11:10

L42


1 Answers

Should I even test this?

Yes. Provided you want to make sure that certain roles will have or have not access to your resource. This will be a security integration test.

How should I go about setting up the whole application + actually call it with an http request in a test if I am to test it? Or is there a simpler way?

Part of the issue is that @RequiresAuthentication and @RequiresRoles themselves are just class and method meta information. Annotations themselves do not provide the security check functionality.

It is not clear from your question what type of container you are using but I can guess that it is plain Jersey JAX-RS service (am I right?). For Shiro to perform security checks you should have added some JAX-RS filter (maybe some other way?) around your endpoints. To test security you should replicate this setup in your tests. Otherwise there is no engine processing your annotations and no security checks as the result.

like image 94
Aleh Maksimovich Avatar answered Sep 29 '22 03:09

Aleh Maksimovich