Commit 4bea59fc authored by Administrator's avatar Administrator

Adds security check to PeopleResourceTest

The PeopleResourceTests now include security tests to verify that normal
users can't access people data.
parent 1376aaa7
{ {
"name": "daa-example", "name": "daa-example",
"version": "0.2.0-alpha.1", "version": "0.2.0-alpha.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
......
{ {
"name": "daa-example", "name": "daa-example",
"version": "0.2.0-alpha.1", "version": "0.2.0-alpha.2",
"scripts": { "scripts": {
"ng": "./node_modules/.bin/ng", "ng": "./node_modules/.bin/ng",
"start": "./node_modules/.bin/ng serve", "start": "./node_modules/.bin/ng serve",
......
...@@ -3,12 +3,14 @@ package es.uvigo.esei.daa.filters; ...@@ -3,12 +3,14 @@ package es.uvigo.esei.daa.filters;
import java.io.IOException; import java.io.IOException;
import java.security.Principal; import java.security.Principal;
import java.util.Base64; import java.util.Base64;
import java.util.List;
import javax.annotation.Priority; import javax.annotation.Priority;
import javax.ws.rs.Priorities; import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.PathSegment;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.SecurityContext; import javax.ws.rs.core.SecurityContext;
...@@ -18,6 +20,12 @@ import es.uvigo.esei.daa.dao.DAOException; ...@@ -18,6 +20,12 @@ import es.uvigo.esei.daa.dao.DAOException;
import es.uvigo.esei.daa.dao.UsersDAO; import es.uvigo.esei.daa.dao.UsersDAO;
import es.uvigo.esei.daa.entities.User; import es.uvigo.esei.daa.entities.User;
/**
* This performs the Basic HTTP authentication following (almost) the same
* rules as the defined in the web.xml file.
*
* @author Miguel Reboiro Jato
*/
@Provider @Provider
@Priority(Priorities.AUTHENTICATION) @Priority(Priorities.AUTHENTICATION)
public class AuthorizationFilter implements ContainerRequestFilter { public class AuthorizationFilter implements ContainerRequestFilter {
...@@ -46,7 +54,11 @@ public class AuthorizationFilter implements ContainerRequestFilter { ...@@ -46,7 +54,11 @@ public class AuthorizationFilter implements ContainerRequestFilter {
if (this.dao.checkLogin(userPass[0], userPass[1])) { if (this.dao.checkLogin(userPass[0], userPass[1])) {
final User user = this.dao.get(userPass[0]); final User user = this.dao.get(userPass[0]);
if (isPeoplePath(requestContext) && !user.getRole().equals("ADMIN")) {
requestContext.abortWith(createResponse());
} else {
requestContext.setSecurityContext(new UserSecurityContext(user)); requestContext.setSecurityContext(new UserSecurityContext(user));
}
} else { } else {
requestContext.abortWith(createResponse()); requestContext.abortWith(createResponse());
} }
...@@ -59,6 +71,11 @@ public class AuthorizationFilter implements ContainerRequestFilter { ...@@ -59,6 +71,11 @@ public class AuthorizationFilter implements ContainerRequestFilter {
} }
} }
private static boolean isPeoplePath(ContainerRequestContext context) {
final List<PathSegment> pathSegments = context.getUriInfo().getPathSegments();
return !pathSegments.isEmpty() && pathSegments.get(0).getPath().equals("people");
}
private static Response createResponse() { private static Response createResponse() {
return Response.status(Status.UNAUTHORIZED) return Response.status(Status.UNAUTHORIZED)
.header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"DAAExample\"") .header(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"DAAExample\"")
......
...@@ -7,8 +7,12 @@ import static es.uvigo.esei.daa.dataset.PeopleDataset.newPerson; ...@@ -7,8 +7,12 @@ import static es.uvigo.esei.daa.dataset.PeopleDataset.newPerson;
import static es.uvigo.esei.daa.dataset.PeopleDataset.newSurname; import static es.uvigo.esei.daa.dataset.PeopleDataset.newSurname;
import static es.uvigo.esei.daa.dataset.PeopleDataset.nonExistentId; import static es.uvigo.esei.daa.dataset.PeopleDataset.nonExistentId;
import static es.uvigo.esei.daa.dataset.PeopleDataset.people; import static es.uvigo.esei.daa.dataset.PeopleDataset.people;
import static es.uvigo.esei.daa.dataset.UsersDataset.adminLogin;
import static es.uvigo.esei.daa.dataset.UsersDataset.normalLogin;
import static es.uvigo.esei.daa.dataset.UsersDataset.userToken;
import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasBadRequestStatus; import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasBadRequestStatus;
import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasOkStatus; import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasOkStatus;
import static es.uvigo.esei.daa.matchers.HasHttpStatus.hasUnauthorized;
import static es.uvigo.esei.daa.matchers.IsEqualToPerson.containsPeopleInAnyOrder; import static es.uvigo.esei.daa.matchers.IsEqualToPerson.containsPeopleInAnyOrder;
import static es.uvigo.esei.daa.matchers.IsEqualToPerson.equalsToPerson; import static es.uvigo.esei.daa.matchers.IsEqualToPerson.equalsToPerson;
import static javax.ws.rs.client.Entity.entity; import static javax.ws.rs.client.Entity.entity;
...@@ -40,7 +44,7 @@ import com.github.springtestdbunit.DbUnitTestExecutionListener; ...@@ -40,7 +44,7 @@ import com.github.springtestdbunit.DbUnitTestExecutionListener;
import com.github.springtestdbunit.annotation.DatabaseSetup; import com.github.springtestdbunit.annotation.DatabaseSetup;
import com.github.springtestdbunit.annotation.ExpectedDatabase; import com.github.springtestdbunit.annotation.ExpectedDatabase;
import es.uvigo.esei.daa.DAAExampleApplication; import es.uvigo.esei.daa.DAAExampleTestApplication;
import es.uvigo.esei.daa.entities.Person; import es.uvigo.esei.daa.entities.Person;
import es.uvigo.esei.daa.listeners.ApplicationContextBinding; import es.uvigo.esei.daa.listeners.ApplicationContextBinding;
import es.uvigo.esei.daa.listeners.ApplicationContextJndiBindingTestExecutionListener; import es.uvigo.esei.daa.listeners.ApplicationContextJndiBindingTestExecutionListener;
...@@ -67,7 +71,7 @@ import es.uvigo.esei.daa.listeners.DbManagementTestExecutionListener; ...@@ -67,7 +71,7 @@ import es.uvigo.esei.daa.listeners.DbManagementTestExecutionListener;
public class PeopleResourceTest extends JerseyTest { public class PeopleResourceTest extends JerseyTest {
@Override @Override
protected Application configure() { protected Application configure() {
return new DAAExampleApplication(); return new DAAExampleTestApplication();
} }
@Override @Override
...@@ -81,7 +85,9 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -81,7 +85,9 @@ public class PeopleResourceTest extends JerseyTest {
@Test @Test
public void testList() throws IOException { public void testList() throws IOException {
final Response response = target("people").request().get(); final Response response = target("people").request()
.header("Authorization", "Basic " + userToken(adminLogin()))
.get();
assertThat(response, hasOkStatus()); assertThat(response, hasOkStatus());
final List<Person> people = response.readEntity(new GenericType<List<Person>>(){}); final List<Person> people = response.readEntity(new GenericType<List<Person>>(){});
...@@ -89,9 +95,19 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -89,9 +95,19 @@ public class PeopleResourceTest extends JerseyTest {
assertThat(people, containsPeopleInAnyOrder(people())); assertThat(people, containsPeopleInAnyOrder(people()));
} }
@Test
public void testListUnauthorized() throws IOException {
final Response response = target("people").request()
.header("Authorization", "Basic " + userToken(normalLogin()))
.get();
assertThat(response, hasUnauthorized());
}
@Test @Test
public void testGet() throws IOException { public void testGet() throws IOException {
final Response response = target("people/" + existentId()).request().get(); final Response response = target("people/" + existentId()).request()
.header("Authorization", "Basic " + userToken(adminLogin()))
.get();
assertThat(response, hasOkStatus()); assertThat(response, hasOkStatus());
final Person person = response.readEntity(Person.class); final Person person = response.readEntity(Person.class);
...@@ -99,9 +115,19 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -99,9 +115,19 @@ public class PeopleResourceTest extends JerseyTest {
assertThat(person, is(equalsToPerson(existentPerson()))); assertThat(person, is(equalsToPerson(existentPerson())));
} }
@Test
public void testGetUnauthorized() throws IOException {
final Response response = target("people/" + existentId()).request()
.header("Authorization", "Basic " + userToken(normalLogin()))
.get();
assertThat(response, hasUnauthorized());
}
@Test @Test
public void testGetInvalidId() throws IOException { public void testGetInvalidId() throws IOException {
final Response response = target("people/" + nonExistentId()).request().get(); final Response response = target("people/" + nonExistentId()).request()
.header("Authorization", "Basic " + userToken(adminLogin()))
.get();
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
} }
...@@ -113,8 +139,8 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -113,8 +139,8 @@ public class PeopleResourceTest extends JerseyTest {
form.param("name", newName()); form.param("name", newName());
form.param("surname", newSurname()); form.param("surname", newSurname());
final Response response = target("people") final Response response = target("people").request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasOkStatus()); assertThat(response, hasOkStatus());
...@@ -123,13 +149,26 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -123,13 +149,26 @@ public class PeopleResourceTest extends JerseyTest {
assertThat(person, is(equalsToPerson(newPerson()))); assertThat(person, is(equalsToPerson(newPerson())));
} }
@Test
public void testAddUnauthorized() throws IOException {
final Form form = new Form();
form.param("name", newName());
form.param("surname", newSurname());
final Response response = target("people").request(MediaType.APPLICATION_JSON_TYPE)
.header("Authorization", "Basic " + userToken(normalLogin()))
.post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasUnauthorized());
}
@Test @Test
public void testAddMissingName() throws IOException { public void testAddMissingName() throws IOException {
final Form form = new Form(); final Form form = new Form();
form.param("surname", newSurname()); form.param("surname", newSurname());
final Response response = target("people") final Response response = target("people").request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
...@@ -140,8 +179,8 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -140,8 +179,8 @@ public class PeopleResourceTest extends JerseyTest {
final Form form = new Form(); final Form form = new Form();
form.param("name", newName()); form.param("name", newName());
final Response response = target("people") final Response response = target("people").request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .post(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
...@@ -154,8 +193,8 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -154,8 +193,8 @@ public class PeopleResourceTest extends JerseyTest {
form.param("name", newName()); form.param("name", newName());
form.param("surname", newSurname()); form.param("surname", newSurname());
final Response response = target("people/" + existentId()) final Response response = target("people/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasOkStatus()); assertThat(response, hasOkStatus());
...@@ -168,13 +207,26 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -168,13 +207,26 @@ public class PeopleResourceTest extends JerseyTest {
assertThat(modifiedPerson, is(equalsToPerson(person))); assertThat(modifiedPerson, is(equalsToPerson(person)));
} }
@Test
public void testModifyUnauthorized() throws IOException {
final Form form = new Form();
form.param("name", newName());
form.param("surname", newSurname());
final Response response = target("people/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE)
.header("Authorization", "Basic " + userToken(normalLogin()))
.put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasUnauthorized());
}
@Test @Test
public void testModifyName() throws IOException { public void testModifyName() throws IOException {
final Form form = new Form(); final Form form = new Form();
form.param("name", newName()); form.param("name", newName());
final Response response = target("people/" + existentId()) final Response response = target("people/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
...@@ -185,8 +237,8 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -185,8 +237,8 @@ public class PeopleResourceTest extends JerseyTest {
final Form form = new Form(); final Form form = new Form();
form.param("surname", newSurname()); form.param("surname", newSurname());
final Response response = target("people/" + existentId()) final Response response = target("people/" + existentId()).request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .put(entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
...@@ -198,8 +250,8 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -198,8 +250,8 @@ public class PeopleResourceTest extends JerseyTest {
form.param("name", newName()); form.param("name", newName());
form.param("surname", newSurname()); form.param("surname", newSurname());
final Response response = target("people/" + nonExistentId()) final Response response = target("people/" + nonExistentId()).request(MediaType.APPLICATION_JSON_TYPE)
.request(MediaType.APPLICATION_JSON_TYPE) .header("Authorization", "Basic " + userToken(adminLogin()))
.put(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE)); .put(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
...@@ -208,7 +260,9 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -208,7 +260,9 @@ public class PeopleResourceTest extends JerseyTest {
@Test @Test
@ExpectedDatabase("/datasets/dataset-delete.xml") @ExpectedDatabase("/datasets/dataset-delete.xml")
public void testDelete() throws IOException { public void testDelete() throws IOException {
final Response response = target("people/" + existentId()).request().delete(); final Response response = target("people/" + existentId()).request()
.header("Authorization", "Basic " + userToken(adminLogin()))
.delete();
assertThat(response, hasOkStatus()); assertThat(response, hasOkStatus());
...@@ -217,9 +271,20 @@ public class PeopleResourceTest extends JerseyTest { ...@@ -217,9 +271,20 @@ public class PeopleResourceTest extends JerseyTest {
assertThat(deletedId, is(equalTo(existentId()))); assertThat(deletedId, is(equalTo(existentId())));
} }
@Test
public void testDeleteUnauthorized() throws IOException {
final Response response = target("people/" + existentId()).request()
.header("Authorization", "Basic " + userToken(normalLogin()))
.delete();
assertThat(response, hasUnauthorized());
}
@Test @Test
public void testDeleteInvalidId() throws IOException { public void testDeleteInvalidId() throws IOException {
final Response response = target("people/" + nonExistentId()).request().delete(); final Response response = target("people/" + nonExistentId()).request()
.header("Authorization", "Basic " + userToken(adminLogin()))
.delete();
assertThat(response, hasBadRequestStatus()); assertThat(response, hasBadRequestStatus());
} }
......
...@@ -17,13 +17,7 @@ import javax.ws.rs.core.Application; ...@@ -17,13 +17,7 @@ import javax.ws.rs.core.Application;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.DeploymentContext;
import org.glassfish.jersey.test.JerseyTest; import org.glassfish.jersey.test.JerseyTest;
import org.glassfish.jersey.test.ServletDeploymentContext;
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerFactory;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
...@@ -74,20 +68,6 @@ public class UsersResourceTest extends JerseyTest { ...@@ -74,20 +68,6 @@ public class UsersResourceTest extends JerseyTest {
config.property("com.sun.jersey.api.json.POJOMappingFeature", Boolean.TRUE); config.property("com.sun.jersey.api.json.POJOMappingFeature", Boolean.TRUE);
} }
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyWebTestContainerFactory();
}
@Override
protected DeploymentContext configureDeployment() {
return ServletDeploymentContext.forServlet(
new ServletContainer(ResourceConfig.forApplication(configure()))
)
.servletPath("/rest")
.build();
}
@Test @Test
public void testGetAdminOwnUser() throws IOException { public void testGetAdminOwnUser() throws IOException {
final String admin = adminLogin(); final String admin = adminLogin();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment