diff --git a/build.gradle b/build.gradle
index 2db4c2a9130d2e13c72f98dd3b2b56ef8108487f..bd129852b1516184b9d622f9b55dae687f6b70c0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -27,7 +27,7 @@ allprojects {
     apply plugin: ScompPlugin
 
     group 'nl.tudelft.ewi'
-    version = '2.0.0'
+    version = '2.1.0'
 
     sourceCompatibility = '1.11'
     targetCompatibility = '1.11'
diff --git a/core/build.gradle b/core/build.gradle
index daaa103016ce6cbea9202804543771862bf21f81..90ab169144773dcfdb5c7701265c0f125893bb18 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -44,10 +44,13 @@ dependencies {
 
     testImplementation 'org.mockito:mockito-core:2.+'
     testImplementation 'org.springframework:spring-test:5.1.+'
+    testImplementation 'org.springframework.boot:spring-boot-starter-test:2.1.+'
+    testImplementation 'org.springframework.security:spring-security-test:5.1.+'
     testImplementation 'org.hamcrest:hamcrest-all:1.3'
     testImplementation 'com.jayway.jsonpath:json-path:2.4.+'
     testImplementation 'nl.jqno.equalsverifier:equalsverifier:3.1.+'
     testImplementation 'org.skyscreamer:jsonassert:0.9.0'
+    testImplementation 'de.flapdoodle.embed:de.flapdoodle.embed.mongo:2.2.+'
 
     testImplementation project(':test-common')
 }
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/Core.java b/core/src/main/java/nl/tudelft/ewi/auta/core/Core.java
index 69fb1ac22d45930313b3f565b3c6e9d48ed0d677..993c6f9df7950c15af36a93fece2b2ce32afaa4d 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/Core.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/Core.java
@@ -118,7 +118,8 @@ public class Core implements WebMvcConfigurer {
 
         System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
 
-        final var spring = new SpringApplicationBuilder(Core.class).logStartupInfo(false).run(args);
+        final var spring =
+                new SpringApplicationBuilder(Core.class).logStartupInfo(false).run(args);
         logger.info("Starting AuTA Core...");
 
         final var env = spring.getBean(Environment.class);
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/benchmarking/Benchmarker.java b/core/src/main/java/nl/tudelft/ewi/auta/core/benchmarking/Benchmarker.java
index 5a9d83e62175342a0260dda3572ebc6fd9dc7075..b5cf69670a64a355d61c61986a30e8a943f2ef55 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/benchmarking/Benchmarker.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/benchmarking/Benchmarker.java
@@ -180,7 +180,7 @@ public class Benchmarker {
         }
         final Map<Integer, List<Entity>> aggregatedMetrics = new HashMap<>();
         //Filters children by level
-        final var allFilteredChildren = projectEntity.getAllChildren().stream()
+        final var allFilteredChildren = projectEntity.getAllEntities().stream()
                 .filter(e -> e.getLevel().equals(level))
                 .collect(Collectors.toSet());
 
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/AssignmentController.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/AssignmentController.java
index 1d274fa3cf22be9200078bfd5fce9978f2697e94..fa36fa8df50f5a669912bf4bf9f25064b3780ab6 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/AssignmentController.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/AssignmentController.java
@@ -1,18 +1,10 @@
 package nl.tudelft.ewi.auta.core.controller;
 
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.servlet.http.HttpServletRequest;
-
 import nl.tudelft.ewi.auta.common.model.metric.MetricName;
 import nl.tudelft.ewi.auta.common.model.metric.MetricSettings;
+import nl.tudelft.ewi.auta.core.database.AssignmentRepository;
+import nl.tudelft.ewi.auta.core.model.Assignment;
+import nl.tudelft.ewi.auta.core.response.Response;
 import nl.tudelft.ewi.auta.core.response.exception.AssignmentAlreadyExistsException;
 import nl.tudelft.ewi.auta.core.response.exception.InvalidAssignmentNameException;
 import nl.tudelft.ewi.auta.core.response.exception.InvalidLanguageException;
@@ -21,6 +13,7 @@ import org.slf4j.LoggerFactory;
 import org.springframework.dao.DuplicateKeyException;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -29,9 +22,15 @@ import org.springframework.web.bind.annotation.PutMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RestController;
 
-import nl.tudelft.ewi.auta.core.database.AssignmentRepository;
-import nl.tudelft.ewi.auta.core.model.Assignment;
-import nl.tudelft.ewi.auta.core.response.Response;
+import javax.servlet.http.HttpServletRequest;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * The controller handling requests related to assignmentStore.
@@ -47,13 +46,21 @@ public class AssignmentController extends ControllerBase {
      */
     private final AssignmentRepository assignmentStore;
 
+
+    /**
+     * The service that manages course-level security for this controller.
+     */
+    private final CourseSecuredService securedService;
+
     /**
      * Creates a new assignment controller.
      *
      * @param assignmentStore the assignment repository
      */
-    public AssignmentController(final AssignmentRepository assignmentStore) {
+    public AssignmentController(final AssignmentRepository assignmentStore,
+                                final CourseSecuredService securedService) {
         this.assignmentStore = assignmentStore;
+        this.securedService = securedService;
     }
 
     /**
@@ -63,27 +70,31 @@ public class AssignmentController extends ControllerBase {
     @GetMapping(value = "/api/v1/assignment", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Response> getAllAction(final HttpServletRequest req) {
         final var res = new Response();
-
-        final List<?> assignmentsList;
+        final List<Assignment> assignmentsList;
         if (req.getParameterMap().containsKey("include_deleted")) {
             assignmentsList = this.assignmentStore.findAll();
         } else {
             assignmentsList = this.assignmentStore.findAllActive();
         }
+        final var authentication = SecurityContextHolder.getContext().getAuthentication();
+        final var assignmentsWithAccess = assignmentsList.stream()
+                .filter(assignment ->
+                        this.securedService.userHasAssignmentAccess(authentication, assignment))
+                .collect(Collectors.toList());
 
-        res.put("assignments", assignmentsList);
+        res.put("assignments", assignmentsWithAccess);
         return ResponseEntity.ok(res);
     }
 
 
-        /**
-         * Creates a new assignment and adds it to the store.
-         * By default, no checks will be run if no static or dynamic checks are specified.
-         *
-         * @param req the request body
-         *
-         * @return the response
-         */
+    /**
+     * Creates a new assignment and adds it to the store.
+     * By default, no checks will be run if no static or dynamic checks are specified.
+     *
+     * @param req the request body
+     *
+     * @return the response
+     */
     @PostMapping(value = "/api/v1/assignment", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Response> createAction(final @RequestBody Map<String, Object> req)
             throws URISyntaxException {
@@ -122,8 +133,8 @@ public class AssignmentController extends ControllerBase {
     @GetMapping(value = "/api/v1/assignment/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Response> getAction(final @PathVariable String id) {
         final var res = new Response();
-
         final var assignment = this.assignmentStore.findExisting(id);
+        this.securedService.checkForAssignmentAccess(assignment);
 
         final var options = new HashMap<String, Object>();
         options.put("static", assignment.getMetricSettings());
@@ -137,6 +148,12 @@ public class AssignmentController extends ControllerBase {
         return ResponseEntity.ok(res);
     }
 
+    /**
+     * Updates an assignment.
+     *
+     * @param id the id of the assignment to update
+     * @return the response
+     */
     @PutMapping(value = "/api/v1/assignment/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Response> updateAction(
             final @PathVariable String id,
@@ -145,6 +162,7 @@ public class AssignmentController extends ControllerBase {
         final var res = new Response();
 
         var assignment = this.assignmentStore.findExisting(id);
+        this.securedService.checkForAssignmentAccess(assignment);
 
         this.populateFromRequest(req, assignment);
 
@@ -167,6 +185,7 @@ public class AssignmentController extends ControllerBase {
         final var res = new Response();
 
         var assignment = this.assignmentStore.findExisting(id);
+        this.securedService.checkForAssignmentAccess(assignment);
 
         assignment.setDeleted(true);
 
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingController.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingController.java
index c6bad949b3a7c98c57f87e2be62806bffea0de35..13338331f7421443b3a312cb5c0f5288f8cd544f 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingController.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingController.java
@@ -67,6 +67,11 @@ public class BenchmarkingController extends ControllerBase {
      */
     private final BenchmarkingReportGenerator generator;
 
+    /**
+     * The service that manages course-level security for this controller.
+     */
+    private final CourseSecuredService securedService;
+
     /**
      * Creates a benchmarking controller.
      * @param entityRepository the repository where the entities are stored
@@ -76,11 +81,13 @@ public class BenchmarkingController extends ControllerBase {
     public BenchmarkingController(final EntityRepository entityRepository,
                                   final BadgeGenerator badgeGenerator,
                                   final Benchmarker benchmarker,
-                                  final BenchmarkingReportGenerator generator) {
+                                  final BenchmarkingReportGenerator generator,
+                                  final CourseSecuredService securedService) {
         this.entityRepository = entityRepository;
         this.badgeGenerator = badgeGenerator;
         this.benchmarker = benchmarker;
         this.generator = generator;
+        this.securedService = securedService;
     }
 
     /**
@@ -98,6 +105,7 @@ public class BenchmarkingController extends ControllerBase {
             final @RequestBody BenchmarkingData data) throws IOException {
         final var res = new Response();
         final var entityContainer = this.entityRepository.findExisting(aid, sid);
+        this.securedService.checkForEntityContainerAccess(entityContainer);
         final var projectEntity = entityContainer.getEntity();
         projectEntity.postProcess();
 
@@ -130,7 +138,9 @@ public class BenchmarkingController extends ControllerBase {
             final @PathVariable String aid,
             final @PathVariable String sid) throws IOException, TemplateException {
         final var res = new Response();
-        final var projectEntity = this.entityRepository.findExisting(aid, sid).getEntity();
+        final var entityContainer = this.entityRepository.findExisting(aid, sid);
+        this.securedService.checkForEntityContainerAccess(entityContainer);
+        final var projectEntity = entityContainer.getEntity();
         final var badge = this.badgeGenerator.generateBadge(projectEntity, aid);
         res.put("badge", badge);
         return ResponseEntity.ok(res);
@@ -192,7 +202,9 @@ public class BenchmarkingController extends ControllerBase {
             final @PathVariable String sid,
             final @RequestBody BenchmarkingData data) {
         final var res = new Response();
-        final var projectEntity = this.entityRepository.findExisting(aid, sid).getEntity();
+        final var entityContainer = this.entityRepository.findExisting(aid, sid);
+        this.securedService.checkForEntityContainerAccess(entityContainer);
+        final var projectEntity = entityContainer.getEntity();
         data.validateMetricAndEntity();
         projectEntity.postProcess();
         final var chartData = this.generator.getChartData(projectEntity, data.getMetricName(),
@@ -216,7 +228,9 @@ public class BenchmarkingController extends ControllerBase {
             final @RequestParam(defaultValue = "entity") String type,
             final @RequestBody BenchmarkingData data) throws IOException {
         final var res = new Response();
-        final var projectEntity = this.entityRepository.findExisting(aid, sid).getEntity();
+        final var entityContainer = this.entityRepository.findExisting(aid, sid);
+        this.securedService.checkForEntityContainerAccess(entityContainer);
+        final var projectEntity = entityContainer.getEntity();
         projectEntity.postProcess();
         data.validateMetricAndEntity();
         final @Nonnull var metricName = data.getMetricName();
@@ -259,7 +273,9 @@ public class BenchmarkingController extends ControllerBase {
             final @PathVariable String sid,
             final @RequestBody BenchmarkingData data) throws IOException, TemplateException {
 
-        final var projectEntity = this.entityRepository.findExisting(aid, sid).getEntity();
+        final var entityContainer = this.entityRepository.findExisting(aid, sid);
+        this.securedService.checkForEntityContainerAccess(entityContainer);
+        final var projectEntity = entityContainer.getEntity();
         data.validateMetricAndEntity();
         projectEntity.postProcess();
 
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseController.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseController.java
index 2aa5207fca0f68ec27e732185e05dbc53c5e4122..655ae8b08097bfba48127d8fe7b144916fbd50f5 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseController.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseController.java
@@ -15,6 +15,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Controller;
 import org.springframework.validation.BindingResult;
 import org.springframework.validation.annotation.Validated;
@@ -30,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestBody;
 import java.sql.SQLException;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 
 /**
@@ -60,16 +62,6 @@ public class CourseController extends ControllerBase {
      */
     private final CourseSecuredService securedService;
 
-    /**
-     * Initializes the binders used in this controller, which is a validator for the createNewCourse
-     * endpoint.
-     * @param webDataBinder the data binder.
-     */
-    @InitBinder("course")
-    public void initBinder(final WebDataBinder webDataBinder) {
-        webDataBinder.addValidators(new CourseValidator());
-    }
-
     /**
      * Creates a course controller.
      * @param repositories the repositories
@@ -82,14 +74,31 @@ public class CourseController extends ControllerBase {
         this.securedService = securedService;
     }
 
+    /**
+     * Initializes the binders used in this controller, which is a validator for the createNewCourse
+     * endpoint.
+     *
+     * @param webDataBinder the data binder.
+     */
+    @InitBinder("course")
+    public void initBinder(final WebDataBinder webDataBinder) {
+        webDataBinder.addValidators(new CourseValidator());
+    }
+
     /**
      * Gets all courses.
+     *
      * @return the list of all courses
      */
     @GetMapping(value = "/api/v1/course", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Response> getAllAction() {
+        final var authentication = SecurityContextHolder.getContext().getAuthentication();
         final var res = new Response();
-        res.put("courses", this.repositories.getCourseRepository().findAll());
+        final var courses = this.repositories.getCourseRepository().findAll();
+        final var coursesWithAccess = courses.stream()
+                .filter(course -> this.securedService.userHasCourseAccess(authentication, course))
+                .collect(Collectors.toList());
+        res.put("courses", coursesWithAccess);
         return ResponseEntity.ok(res);
     }
 
@@ -123,7 +132,8 @@ public class CourseController extends ControllerBase {
     @DeleteMapping(value = "/api/v1/course/{cid}", produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<Response> deleteCourseAction(final @PathVariable String cid) {
         final var res = new Response();
-        this.repositories.getCourseRepository().findExisting(cid);
+        final var course = this.repositories.getCourseRepository().findExisting(cid);
+        this.securedService.checkForCourseAccess(course);
         this.repositories.getCourseRepository().deleteById(cid);
         return ResponseEntity.ok(res);
     }
@@ -143,6 +153,7 @@ public class CourseController extends ControllerBase {
 
         final var courseRepository = this.repositories.getCourseRepository();
         final var oldCourse = courseRepository.findExisting(cid);
+        this.securedService.checkForCourseAccess(oldCourse);
 
         oldCourse.setName(course.getName());
         oldCourse.setCourseCode(course.getCourseCode());
@@ -159,14 +170,14 @@ public class CourseController extends ControllerBase {
     public ResponseEntity<Response> getCourseAction(
             final @PathVariable String cid) {
         final var res = new Response();
-
         final var courseRepository = this.repositories.getCourseRepository();
-        res.put("course", courseRepository.findExisting(cid));
+        final var course = courseRepository.findExisting(cid);
+        this.securedService.checkForCourseAccess(course);
+        res.put("course", course);
         return ResponseEntity.ok(res);
     }
 
 
-
     /**
      * Adds an assignment to a course.
      *
@@ -195,6 +206,7 @@ public class CourseController extends ControllerBase {
         final var courseRepository = this.repositories.getCourseRepository();
 
         final var course = courseRepository.findExisting(cid);
+        this.securedService.checkForCourseAccess(course);
         final var successfullyAdded = course.addAssignmentId(aid);
         logger.debug("Assignment {} added to course {} successfully: {}", aid, cid,
                 successfullyAdded);
@@ -239,6 +251,7 @@ public class CourseController extends ControllerBase {
         final var courseRepository = this.repositories.getCourseRepository();
 
         final var course = courseRepository.findExisting(cid);
+        this.securedService.checkForCourseAccess(course);
 
         try (var dc = this.db.connect()) {
             final var user = dc.getUser(username).orElseThrow(() ->  new MissingUserException(
@@ -274,6 +287,7 @@ public class CourseController extends ControllerBase {
             throw new InvalidRoleException("Role must be one of ROLE_TA, ROLE_TEACHER");
         }
         final var course = this.repositories.getCourseRepository().findExisting(cid);
+        this.securedService.checkForCourseAccess(course);
         if (role.equals("ROLE_TA")) {
             final var removed = this.securedService.removeTA(course, username);
             logger.debug("Removed TA {} successfully: {}", username, removed);
@@ -301,6 +315,7 @@ public class CourseController extends ControllerBase {
         final var res = new Response();
 
         final var course = this.repositories.getCourseRepository().findExisting(cid);
+        this.securedService.checkForCourseAccess(course);
         final var removed = course.removeAssignmentId(aid);
         logger.debug("Removed assignment {} successfully: {}", aid, removed);
         this.repositories.getCourseRepository().save(course);
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseSecuredService.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseSecuredService.java
index 1bea512fe1841e54358c26730ca85deb1d8cbd67..7e48d8d766edda0badf7df1c0a8d71622c9c3585 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseSecuredService.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/CourseSecuredService.java
@@ -1,12 +1,23 @@
 package nl.tudelft.ewi.auta.core.controller;
 
+import nl.tudelft.ewi.auta.core.database.CourseRepository;
+import nl.tudelft.ewi.auta.core.database.EntityContainer;
+import nl.tudelft.ewi.auta.core.model.Assignment;
 import nl.tudelft.ewi.auta.core.model.Course;
+import nl.tudelft.ewi.auta.core.model.Submission;
+import nl.tudelft.ewi.auta.core.response.exception.UserNotAuthorizedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.security.access.annotation.Secured;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.stereotype.Service;
 
 /**
  * A class that is needed for spring method-level security.
- *
+ * <p>
  * Defining these methods in the controller results in spring ignoring all security.
  * This is because Spring AOP Proxying is used to apply method-level security. If a secured method
  * is called by another method in the same class, all method security is ignored.
@@ -14,9 +25,26 @@ import org.springframework.stereotype.Service;
 @Service
 public class CourseSecuredService {
 
+    private static final Logger logger = LoggerFactory.getLogger(CourseSecuredService.class);
+
     /**
-     * Adds an instructor to a course.
+     * The course repository used to look up course ids.
+     */
+    private final CourseRepository courseRepository;
+
+    /**
+     * Creates a new course secured service, which uses the course repository to manage access
+     * rights for different users.
      *
+     * @param courseRepository the course repository where courses are stored.
+     */
+    public CourseSecuredService(final CourseRepository courseRepository) {
+        this.courseRepository = courseRepository;
+    }
+
+    /**
+     * Adds an instructor to a course.
+     * <p>
      * Only admins should be able to do this.
      *
      * @param course the course the instructor is being added to
@@ -30,7 +58,7 @@ public class CourseSecuredService {
 
     /**
      * Adds a TA to a course.
-     *
+     * <p>
      * Both ADMINs and TEACHERs can do this.
      *
      * @param course the course the TA is being added to
@@ -44,7 +72,7 @@ public class CourseSecuredService {
 
     /**
      * Removes an instructor from a course.
-     *
+     * <p>
      * Only admins should be able to do this.
      *
      * @param course the course the instructor is being removed from
@@ -58,7 +86,7 @@ public class CourseSecuredService {
 
     /**
      * Removes a TA from a course.
-     *
+     * <p>
      * Both ADMINs and TEACHERs can do this.
      *
      * @param course the course the TA is being removed from
@@ -70,4 +98,163 @@ public class CourseSecuredService {
         return course.removeTA(username);
     }
 
+    /**
+     * Checks if a user has access to an assignment by checking for access to the courses the
+     * assignment is registered to.
+     *
+     * @param authentication the {@link Authentication} to use.
+     * @param aid the assignment id
+     * @return {@code true} if the user has access to any of the courses the assignment belongs
+     * to, or the user is an admin
+     */
+    public boolean userHasAssignmentAccess(final Authentication authentication, final String aid) {
+        final var userDetails = (UserDetails) authentication.getPrincipal();
+        final var username = userDetails.getUsername();
+        logger.trace("Checking assignment access for user {}, cid {}", username, aid);
+        if (this.userIsAdmin(userDetails)) {
+            return true;
+        }
+        final var courseList = this.courseRepository.findByAssignmentIdsContaining(aid);
+        return courseList.stream().anyMatch(course
+                -> this.userHasCourseAccess(authentication, course));
+    }
+
+    /**
+     * Checks if a user has access to an assignment by checking for access to the courses the
+     * assignment is registered to.
+     *
+     * @param authentication the {@link Authentication} to use.
+     * @param assignment the assignment
+     * @return {@code true} if the user has access to any of the courses the assignment belongs
+     * to, or the user is an admin
+     */
+    public boolean userHasAssignmentAccess(final Authentication authentication,
+                                           final Assignment assignment) {
+        return this.userHasAssignmentAccess(authentication, assignment.getId());
+    }
+
+    /**
+     * Checks if a user has an admin role.
+     * @param userDetails the user details object that belongs to the user
+     * @return true if the user is an admin, else returns false
+     */
+    private boolean userIsAdmin(final UserDetails userDetails) {
+        return userDetails.getAuthorities().stream()
+                .map(GrantedAuthority::getAuthority)
+                .anyMatch(authority -> authority.equals("ROLE_ADMIN"));
+    }
+
+    /**
+     * Checks if a user has access to a course by looking for the username in the course's TA or
+     * instructor set.
+     *
+     * @param authentication the {@link Authentication} to use.
+     * @param course the {@link Course} to use
+     * @return {@code false} if there is no such course, or the user is not a TA or instructor in
+     * that course. Otherwise, returns {@code true}. If the user is an admin, always returns
+     * {@code true}.
+     */
+    public boolean userHasCourseAccess(final Authentication authentication, final Course course) {
+
+        final var userDetails = (UserDetails) authentication.getPrincipal();
+        final var username = userDetails.getUsername();
+        if (this.userIsAdmin(userDetails)) {
+            return true;
+        }
+        final var cid = course.getId();
+        logger.debug("Checking course access for user {}, cid {}", username, cid);
+        if (course.getTaSet().contains(username)) {
+            logger.debug("User {} is registered as a TA in course {}", username, cid);
+            return true;
+        }
+
+        if (course.getInstructorSet().contains(username)) {
+            logger.debug("User {} is registered as an instructor in course {}", username, cid);
+            return true;
+        }
+
+        logger.debug("User {} does not have access to course {}", username, cid);
+        return false;
+    }
+
+    /**
+     * Checks if a user has access to a submission by checking if they have access to the parent
+     * assignment.
+     *
+     * @param authentication the {@link Authentication} objec tassociated with the user.
+     * @param submission the submission to check access for
+     * @return {@code true} if the user has access, else {@code false}.
+     */
+    public boolean userHasSubmissionAccess(final Authentication authentication,
+                                           final Submission submission) {
+        assert submission.getAssignmentId() != null;
+        return this.userHasAssignmentAccess(authentication, submission.getAssignmentId());
+    }
+
+    /**
+     * Checks if access to a course is allowed in the current security context.
+     *
+     * @param course the {@link Course} that will be checked.
+     *
+     * @throws UserNotAuthorizedException if access to the course is not allowed in the current
+     * security context.
+     */
+    public void checkForCourseAccess(final Course course) {
+        final var authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (!this.userHasCourseAccess(authentication, course)) {
+            throw new UserNotAuthorizedException("User is not authorized to access course: "
+                    + course.getId());
+        }
+    }
+
+    /**
+     * Checks if access to an assignment is allowed in the current security context.
+     *
+     * @param assignment the {@link Assignment} that will be checked.
+     *
+     * @throws UserNotAuthorizedException if access to the assignment is not allowed in the current
+     * security context.
+     */
+    public void checkForAssignmentAccess(final Assignment assignment) {
+        final var authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (!this.userHasAssignmentAccess(authentication, assignment)) {
+            throw new UserNotAuthorizedException("User is not authorized to access assignment: "
+                    + assignment.getId());
+        }
+    }
+
+
+    /**
+     * Checks if access to a submission is allowed in the current security context.
+     *
+     * @param submission the {@link Submission} that will be checked.
+     *
+     * @throws UserNotAuthorizedException if access to the submission is not allowed in the current
+     * security context.
+     */
+    public void checkForSubmissionAccess(final Submission submission) {
+        final var authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (!this.userHasSubmissionAccess(authentication, submission)) {
+            throw new UserNotAuthorizedException("User is not authorized to access submission: "
+                    + submission.getId());
+        }
+    }
+
+
+    /**
+     * Checks if access to an entity container is allowed in the current security context.
+     *
+     * @param container the {@link EntityContainer} that will be checked.
+     *
+     * @throws UserNotAuthorizedException if access to the container is not allowed in the current
+     * security context.
+     */
+
+    public void checkForEntityContainerAccess(final EntityContainer container) {
+        final var authentication = SecurityContextHolder.getContext().getAuthentication();
+        if (!this.userHasAssignmentAccess(authentication, container.getAssignmentId())) {
+            throw new UserNotAuthorizedException("User is not authorized to access container: "
+                    + container.getId());
+        }
+    }
 }
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/ReportController.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/ReportController.java
index aec7046ac6cfe69d10646dd4bdd399fdefada61f..561e43c50eee73640b0fe4929a6a5990bf34b080 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/ReportController.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/ReportController.java
@@ -18,13 +18,20 @@ public class ReportController extends ControllerBase {
      */
     private final Repositories repositories;
 
+    /**
+     * The service that only prevents unauthorized users from accessing information.
+     */
+    private final CourseSecuredService securedService;
+
     /**
      * Creates a new report controller.
      *
      * @param repositories the repositories
      */
-    public ReportController(final Repositories repositories) {
+    public ReportController(final Repositories repositories,
+                            final CourseSecuredService securedService) {
         this.repositories = repositories;
+        this.securedService = securedService;
     }
 
     @GetMapping(
@@ -36,7 +43,9 @@ public class ReportController extends ControllerBase {
         final var res = new Response();
 
         this.repositories.getAssignmentRepository().findExisting(aid);
-        this.repositories.getSubmissionRepository().findExisting(aid, sid);
+        final var submission = this.repositories.getSubmissionRepository().findExisting(aid, sid);
+        this.securedService.checkForSubmissionAccess(submission);
+
         final var entityContainerOptional =  this.repositories.getEntityRepository()
                 .findByParentIds(sid, aid);
 
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionController.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionController.java
index 669ac485e2b509312874e7e7f7166d1338dd8440..ee7aae21a2ed5198480e4aaf89a8b9845de68843 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionController.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionController.java
@@ -1,23 +1,15 @@
 package nl.tudelft.ewi.auta.core.controller;
 
-import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.time.Instant;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
 import freemarker.template.TemplateException;
 import nl.tudelft.ewi.auta.core.database.EntityContainer;
 import nl.tudelft.ewi.auta.core.database.IdentityContainer;
 import nl.tudelft.ewi.auta.core.database.Repositories;
+import nl.tudelft.ewi.auta.core.jobs.JobQueue;
 import nl.tudelft.ewi.auta.core.model.FileStore;
 import nl.tudelft.ewi.auta.core.model.Job;
 import nl.tudelft.ewi.auta.core.model.Submission;
 import nl.tudelft.ewi.auta.core.report.HtmlReportGenerator;
+import nl.tudelft.ewi.auta.core.response.Response;
 import nl.tudelft.ewi.auta.core.response.exception.InvalidFileTypeException;
 import nl.tudelft.ewi.auta.core.response.exception.InvalidSubmissionNameException;
 import org.slf4j.Logger;
@@ -31,13 +23,19 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
-
-import nl.tudelft.ewi.auta.core.jobs.JobQueue;
-import nl.tudelft.ewi.auta.core.response.Response;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * The controller serving endpoints related to submissions.
@@ -73,6 +71,11 @@ public class SubmissionController extends ControllerBase {
      */
     private HtmlReportGenerator htmlReportGenerator;
 
+    /**
+     * The service used to make sure only authorized users can access submissions.
+     */
+    private final CourseSecuredService securedService;
+
     /**
      * The repositories.
      */
@@ -88,12 +91,14 @@ public class SubmissionController extends ControllerBase {
     public SubmissionController(final JobQueue queue,
                                 final FileStore files,
                                 final HtmlReportGenerator htmlReportGenerator,
-                                final Repositories repositories
+                                final Repositories repositories,
+                                final CourseSecuredService securedService
     ) {
         this.repositories = repositories;
         this.queue = queue;
         this.files = files;
         this.htmlReportGenerator = htmlReportGenerator;
+        this.securedService = securedService;
     }
 
     /**
@@ -110,12 +115,17 @@ public class SubmissionController extends ControllerBase {
      *
      * @param aid the assignment id used to fetch the assignment
      * @return list of submissions for given assignments.
+     *
+     * @throws nl.tudelft.ewi.auta.core.response.exception.UserNotAuthorizedException if the
+     * user is not allowed to access the assignment
+     * @throws nl.tudelft.ewi.auta.core.response.exception.NoSuchAssignmentException if the
+     * assignment could not be found
      */
     @GetMapping(
             path = "/api/v1/assignment/{aid}/submission",
             produces = MediaType.APPLICATION_JSON_VALUE
     )
-    private ResponseEntity<Response> getAllSubmissions(
+    public ResponseEntity<Response> getAllSubmissions(
             final @PathVariable String aid,
             final @RequestParam(value = "page", required = false) Optional<Integer> pageNum,
             final @RequestParam(value = "size", required = false) Optional<Integer> pageSize
@@ -127,6 +137,8 @@ public class SubmissionController extends ControllerBase {
         final var pageReq = PageRequest.of(pageIndex, numPerPage);
 
         final var identityRepository = this.repositories.getIdentityRepository();
+        final var assignment = this.repositories.getAssignmentRepository().findExisting(aid);
+        this.securedService.checkForAssignmentAccess(assignment);
         final var page = this.repositories.getSubmissionRepository()
                 .findByAssignmentId(aid, pageReq);
 
@@ -156,6 +168,11 @@ public class SubmissionController extends ControllerBase {
      * @param aid the identifier of the assignment the submission should be added to
      * @param req the request body
      * @return the response
+     *
+     * @throws nl.tudelft.ewi.auta.core.response.exception.NoSuchAssignmentException if the
+     * assignment could not be found
+     * @throws nl.tudelft.ewi.auta.core.response.exception.UserNotAuthorizedException if the user
+     * has no access to the submission
      */
     @PostMapping(
             value = "/api/v1/assignment/{aid}/submission",
@@ -170,6 +187,7 @@ public class SubmissionController extends ControllerBase {
         final var submissionRepository = this.repositories.getSubmissionRepository();
 
         final var assignment = assignmentRepository.findExisting(aid);
+        this.securedService.checkForAssignmentAccess(assignment);
 
         final var name = this.getString(req, "name");
         if (name.isEmpty() || name.length() > MAX_FIELD_SIZE) {
@@ -235,6 +253,7 @@ public class SubmissionController extends ControllerBase {
 
         assignmentRepository.findExisting(aid);
         final var submission = submissionRepository.findExisting(aid, sid);
+        this.securedService.checkForSubmissionAccess(submission);
 
         res.put("id", submission.getId());
         res.put("aid", submission.getAssignmentId());
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportController.java b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportController.java
index 25fd65256223ebc0aa4e6d57f1af48507cce2da7..6197ad81bc6ade57a143add779029564d71bcdc8 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportController.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportController.java
@@ -120,6 +120,11 @@ public class SubmissionExportController {
      */
     private final MongoTemplate mongo;
 
+    /**
+     * A service that prevents unauthorized users from accessing endpoints.
+     */
+    private final CourseSecuredService securedService;
+
     /**
      * Creates a new assignment export controller.
      *
@@ -130,11 +135,13 @@ public class SubmissionExportController {
     public SubmissionExportController(
             final Repositories repositories,
             final Gson gson,
-            final MongoTemplate mongo
+            final MongoTemplate mongo,
+            final CourseSecuredService securedService
     ) {
         this.repositories = repositories;
         this.gson = gson;
         this.mongo = mongo;
+        this.securedService = securedService;
     }
 
     /**
@@ -248,13 +255,17 @@ public class SubmissionExportController {
      *
      * @throws nl.tudelft.ewi.auta.core.response.exception.NoSuchAssignmentException if the
      *         assignment does not exist
+     * @throws nl.tudelft.ewi.auta.core.response.exception.UserNotAuthorizedException if the user
+     *         does not have access to the assignment
      */
     @Contract("null -> null; !null -> !null")
     @Nullable
     private Assignment findAssignment(final @Nullable String aid) {
         if (aid != null) {
             final var assignmentRepository = this.repositories.getAssignmentRepository();
-            return assignmentRepository.findExisting(aid);
+            final var assignment = assignmentRepository.findExisting(aid);
+            this.securedService.checkForAssignmentAccess(assignment);
+            return assignment;
         } else {
             return null;
         }
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/database/CourseRepository.java b/core/src/main/java/nl/tudelft/ewi/auta/core/database/CourseRepository.java
index dc9e275e06fef38aa5c9774fdb974bdf3da5ba04..90ddc5c147646e1dc772fb18630ed2074dc2ac89 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/database/CourseRepository.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/database/CourseRepository.java
@@ -5,11 +5,22 @@ import nl.tudelft.ewi.auta.core.response.exception.NoSuchCourseException;
 import org.springframework.data.mongodb.repository.MongoRepository;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
 import java.util.Optional;
 
 @Repository
 public interface CourseRepository extends MongoRepository<Course, String> {
 
+
+    /**
+     * Finds all courses that contain an assignment id.
+     *
+     * @param assignmentId the assignment id to look for
+     * @return the list of courses that contain the assignment id
+     */
+    List<Course> findByAssignmentIdsContaining(String assignmentId);
+
+
     /**
      * Finds the course by course code + year combination.
      *
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/database/MongoConfig.java b/core/src/main/java/nl/tudelft/ewi/auta/core/database/MongoConfig.java
index fd5618f5fec0a8b936f50921ccf1d9317484e106..134b8cc86a57db4643a2d7c26be6b82303c223fb 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/database/MongoConfig.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/database/MongoConfig.java
@@ -2,6 +2,7 @@ package nl.tudelft.ewi.auta.core.database;
 
 import nl.tudelft.ewi.auta.core.settings.GlobalSettings;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
 import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
 import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
 
@@ -13,6 +14,7 @@ import javax.annotation.Nonnull;
  * The database connection object.
  */
 @Configuration
+@Profile("!test")
 @EnableMongoRepositories(basePackages = "nl.tudelft.ewi.auta.core.database")
 public class MongoConfig extends AbstractMongoConfiguration {
     /**
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/report/GenericReportGenerator.java b/core/src/main/java/nl/tudelft/ewi/auta/core/report/GenericReportGenerator.java
index 29866c61ee755e0092386ad5643b90a8ca7ca0f4..22e26ca84710647471218fe39775bc9554dd27b0 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/report/GenericReportGenerator.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/report/GenericReportGenerator.java
@@ -92,7 +92,7 @@ public abstract class GenericReportGenerator {
      */
     private Map<String, List<String>> aggregateNotesBySeverity(final ProjectEntity projectEntity,
                                                                final Severity severity) {
-        final var allChildren = projectEntity.getAllChildren();
+        final var allChildren = projectEntity.getAllEntities();
         final var noteMap = new HashMap<String, List<String>>();
         allChildren.forEach(
                 c -> {
@@ -121,7 +121,7 @@ public abstract class GenericReportGenerator {
      * @return the aggregated map of tips.
      */
     private Map<String, List<String>> aggregateTips(final ProjectEntity projectEntity) {
-        final var allChildren = projectEntity.getAllChildren();
+        final var allChildren = projectEntity.getAllEntities();
         final var tipMap = new HashMap<String, List<String>>();
         allChildren.forEach(
                 c -> {
diff --git a/core/src/main/java/nl/tudelft/ewi/auta/core/response/ErrorCode.java b/core/src/main/java/nl/tudelft/ewi/auta/core/response/ErrorCode.java
index 5c66c277e7ce7e95c059f887d747c3c9d8098260..ec512f1ed0e6678fb118b9ef6d373c76f2299a61 100644
--- a/core/src/main/java/nl/tudelft/ewi/auta/core/response/ErrorCode.java
+++ b/core/src/main/java/nl/tudelft/ewi/auta/core/response/ErrorCode.java
@@ -148,7 +148,7 @@ public enum ErrorCode {
      * When the client tries to do they are not allowed to do (such as add a user to a course
      * while they do not have high enough authority).
      */
-    FORBIDDEN(HttpStatus.BAD_REQUEST),
+    FORBIDDEN(HttpStatus.FORBIDDEN),
 
     /**
      * If the client attempted to authenticate using an unknown SAML identity provider.
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/AbstractIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/AbstractIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..caed5119b0e033e901914c5f2a01c0b37391e1ef
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/AbstractIntegrationTest.java
@@ -0,0 +1,40 @@
+package nl.tudelft.ewi.auta.core;
+
+
+import nl.tudelft.ewi.auta.core.report.ScriptExecutor;
+import nl.tudelft.ewi.auta.core.response.OptionalSerializer;
+import nl.tudelft.ewi.auta.srf.iface.ScriptExecutionContextFactory;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@ActiveProfiles("test")
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public abstract class AbstractIntegrationTest {
+
+    @MockBean
+    ScriptExecutor executor;
+
+    // The ScriptExecutor and ScriptExecutionContextFactory are both mocked, as this is the
+    // easiest way to get the SpringBootTest working.
+    @MockBean
+    ScriptExecutionContextFactory factory;
+
+    @Configuration
+    @Import(Core.class)
+    public static class TestConfig {
+        @Bean
+        public OptionalSerializer serializer() {
+            // This bean needs to be declared seperately, as spring is unable to instantiate it
+            // for some reason.
+            return new OptionalSerializer();
+        }
+    }
+
+}
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AbstractWebSecurityIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AbstractWebSecurityIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..24eef28bef2a683cb206dd8fcd2e83ae556dbb39
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AbstractWebSecurityIntegrationTest.java
@@ -0,0 +1,169 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import com.google.gson.Gson;
+import nl.tudelft.ewi.auta.common.model.entity.ProjectEntity;
+import nl.tudelft.ewi.auta.core.AbstractIntegrationTest;
+import nl.tudelft.ewi.auta.core.database.AssignmentRepository;
+import nl.tudelft.ewi.auta.core.database.CourseRepository;
+import nl.tudelft.ewi.auta.core.database.EntityContainer;
+import nl.tudelft.ewi.auta.core.database.EntityRepository;
+import nl.tudelft.ewi.auta.core.database.IdentityContainer;
+import nl.tudelft.ewi.auta.core.database.IdentityRepository;
+import nl.tudelft.ewi.auta.core.database.SubmissionRepository;
+import nl.tudelft.ewi.auta.core.model.Assignment;
+import nl.tudelft.ewi.auta.core.model.Course;
+import nl.tudelft.ewi.auta.core.model.Submission;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+import java.util.Set;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+public abstract class AbstractWebSecurityIntegrationTest extends AbstractIntegrationTest {
+
+    protected MockMvc mockMvc;
+    private Gson gson = new Gson();
+
+    @Autowired
+    private WebApplicationContext context;
+
+    @BeforeAll
+    public static void setupClass(@Autowired final AssignmentRepository assignmentRepository,
+                                  @Autowired final CourseRepository courseRepository,
+                                  @Autowired final SubmissionRepository submissionRepository,
+                                  @Autowired final IdentityRepository identityRepository,
+                                  @Autowired final EntityRepository entityRepository) {
+        populateDatabase(assignmentRepository, courseRepository, submissionRepository,
+                identityRepository, entityRepository);
+    }
+
+    @BeforeEach
+    public void setUp() {
+        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
+                .build();
+    }
+
+    protected MockHttpServletRequestBuilder withJsonBody(
+            final MockHttpServletRequestBuilder request,
+            final Object content) {
+        return request.content(this.gson.toJson(content))
+                .contentType(MediaType.APPLICATION_JSON);
+    }
+
+    public ResultActions getForbidden(final String url) throws Exception {
+        return this.mockMvc.perform(get(url)).andExpect(status().isForbidden());
+    }
+
+    public ResultActions deleteForbidden(final String url) throws Exception {
+        return this.mockMvc.perform(delete(url)).andExpect(status().isForbidden());
+    }
+
+    public ResultActions postForbidden(final String url, final Object content) throws Exception {
+        return this.mockMvc.perform(this.withJsonBody(post(url), content))
+                .andExpect(status().isForbidden());
+    }
+
+    public ResultActions putForbidden(final String url, final Object content) throws Exception {
+        return this.mockMvc.perform(this.withJsonBody(put(url), content))
+                .andExpect(status().isForbidden());
+    }
+
+    public ResultActions postExpectOk(final String url, final Object content) throws Exception {
+        return this.mockMvc.perform(this.withJsonBody(post(url), content))
+                .andExpect(status().isOk());
+    }
+
+
+    public ResultActions getExpectOk(final String url) throws Exception {
+        return this.mockMvc.perform(get(url)).andExpect(status().isOk());
+    }
+
+    public static void populateDatabase(final AssignmentRepository assignmentRepository,
+                                        final CourseRepository courseRepository,
+                                        final SubmissionRepository submissionRepository,
+                                        final IdentityRepository identityRepository,
+                                        final EntityRepository entityRepository) {
+        final var assignment1 = new Assignment();
+        assignment1.setId("assignment1");
+        assignment1.setName("assignment1");
+        assignment1.setAllowedLanguages(Set.of("java"));
+        assignmentRepository.save(assignment1);
+
+        final var assignment2 = new Assignment();
+        assignment2.setName("assignment2");
+        assignment2.setId("assignment2");
+        assignment2.setAllowedLanguages(Set.of("java"));
+        assignmentRepository.save(assignment2);
+
+        final var assignment3 = new Assignment();
+        assignment3.setName("assignment3");
+        assignment3.setId("assignment3");
+        assignment3.setAllowedLanguages(Set.of("java"));
+        assignmentRepository.save(assignment3);
+
+        final var course = new Course();
+        course.setCourseCode("AB1234");
+        course.setName("NO_TA_NO_INSTRUCTORS");
+        course.setId("course1");
+        course.addAssignmentId("assignment1");
+        courseRepository.save(course);
+
+        final var course2 = new Course();
+        course2.setCourseCode("AB1234");
+        course2.setName("TA_AND_INSTRUCTOR");
+        course2.addInstructor("instructor");
+        course2.setId("course2");
+        course2.addTA("ta");
+        course2.addAssignmentId("assignment2");
+        courseRepository.save(course2);
+
+        final var course3 = new Course();
+        course3.setCourseCode("AB1234_2");
+        course3.setName("TA_AND_INSTRUCTOR2");
+        course3.addInstructor("instructor");
+        course3.setId("course3");
+        course3.addTA("ta");
+        course3.addAssignmentId("assignment3");
+        courseRepository.save(course3);
+
+        final var submission = new Submission();
+        submission.setName("submission1");
+        submission.setId("submission1");
+        submission.setAssignmentId("assignment1");
+        submissionRepository.save(submission);
+
+        final var submission2 = new Submission();
+        submission2.setName("submission2");
+        submission2.setId("submission2");
+        submission2.setAssignmentId("assignment2");
+        submissionRepository.save(submission2);
+
+        final var identity = new IdentityContainer("submission1", "id1");
+        identityRepository.save(identity);
+        final var identity2 = new IdentityContainer("submission2", "id2");
+        identityRepository.save(identity2);
+
+        final var container1 = new EntityContainer(new ProjectEntity(), "submission1", false, null,
+                "assignment1");
+        container1.setId("container1");
+        entityRepository.save(container1);
+
+        final var container2 = new EntityContainer(new ProjectEntity(), "submission2", false, null,
+                "assignment2");
+        container2.setId("container2");
+        entityRepository.save(container2);
+    }
+
+}
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..2ad11b5c75dc67f21ca0b84fd93237016b386d31
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerIntegrationTest.java
@@ -0,0 +1,61 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.test.context.support.WithMockUser;
+
+import java.util.Map;
+
+import static org.hamcrest.Matchers.hasSize;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@EnableAutoConfiguration
+public class AssignmentControllerIntegrationTest extends AbstractWebSecurityIntegrationTest {
+
+    @Test
+    @WithMockUser(username = "admin", roles = "ADMIN")
+    public void adminCanViewAllAssignments() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/assignment"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.assignments", hasSize(3)));
+    }
+
+    @Test
+    @WithMockUser(username = "admin", roles = "ADMIN")
+    public void adminCanViewSinglelAssignment() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/assignment/assignment1"))
+                .andExpect(status().isOk());
+    }
+
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotViewAllCourses() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/assignment"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.assignments", hasSize(2)));
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotAccessUnautorizedCourse() throws Exception {
+        this.getForbidden("/api/v1/assignment/assignment1");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotDeleteUnautorizedCourse() throws Exception {
+        this.deleteForbidden("/api/v1/assignment/assignment1");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotUpdateUnautorizedCourse() throws Exception {
+        this.putForbidden("/api/v1/assignment/assignment1",
+                Map.of("name", "test", "language", "java"));
+    }
+}
+
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerTest.java
index 8a22c5f58d300ab52432b65c0984a569ec6d3d6d..95d831d140fef6215a0054d07c9748a6d8b52de4 100644
--- a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerTest.java
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/AssignmentControllerTest.java
@@ -1,18 +1,8 @@
 package nl.tudelft.ewi.auta.core.controller;
 
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
-import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
-import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
-
-import java.util.Optional;
-
+import nl.tudelft.ewi.auta.core.database.AssignmentRepository;
+import nl.tudelft.ewi.auta.core.model.Assignment;
+import nl.tudelft.ewi.auta.core.model.Submission;
 import nl.tudelft.ewi.auta.core.response.exception.NoSuchAssignmentException;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -26,17 +16,28 @@ import org.springframework.http.HttpMethod;
 import org.springframework.test.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.setup.MockMvcBuilders;
 
-import nl.tudelft.ewi.auta.core.database.AssignmentRepository;
-import nl.tudelft.ewi.auta.core.model.Assignment;
-import nl.tudelft.ewi.auta.core.model.Submission;
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
 
 public class AssignmentControllerTest {
+    private static final String ID = "UNIQUE_ID";
     private MockMvc mvc;
-
     @Mock
     private AssignmentRepository assignmentStore;
 
-    private static final String ID = "UNIQUE_ID";
+    @Mock
+    private CourseSecuredService securedService;
 
     @InjectMocks
     private AssignmentController controller;
@@ -48,15 +49,15 @@ public class AssignmentControllerTest {
         MockitoAnnotations.initMocks(this);
 
         final Answer<Assignment> storeAnswer = invocation -> {
-            Assignment assignmt = invocation.getArgument(0);
+            final Assignment assignmt = invocation.getArgument(0);
             assignmt.setId(ID);
             return assignmt;
         };
 
-        Mockito.when(this.assignmentStore.save(Mockito.any(Assignment.class)))
+        Mockito.when(this.assignmentStore.save(any(Assignment.class)))
                 .thenAnswer(storeAnswer);
 
-        Mockito.when(this.assignmentStore.insert(Mockito.any(Assignment.class)))
+        Mockito.when(this.assignmentStore.insert(any(Assignment.class)))
                 .thenAnswer(storeAnswer);
 
         this.assignment = new Assignment("name");
@@ -72,14 +73,14 @@ public class AssignmentControllerTest {
         this.assignment.addSubmission(submission1);
         this.assignment.addSubmission(submission2);
 
-        Mockito.when(this.assignmentStore.findExisting(Mockito.any(String.class)))
+        Mockito.when(this.assignmentStore.findExisting(any(String.class)))
                 .thenThrow(new NoSuchAssignmentException("not found"));
         Mockito.when(this.assignmentStore.findExisting(Mockito.eq("existing")))
                 .thenReturn(this.assignment);
 
         this.mvc = MockMvcBuilders.standaloneSetup(this.controller)
-                           .setControllerAdvice(new RestExceptionHandler())
-                           .build();
+                .setControllerAdvice(new RestExceptionHandler())
+                .build();
     }
 
     @Test
@@ -111,7 +112,7 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.id", equalTo(ID)));
 
         Mockito.verify(this.assignmentStore, Mockito.times(1))
-                .insert(Mockito.any(Assignment.class));
+                .insert(any(Assignment.class));
     }
 
     @Test
@@ -124,7 +125,7 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.errors", hasSize(1)))
                 .andExpect(jsonPath("$.errors[0].code", equalTo("MISSING_FIELD")));
 
-        Mockito.verify(this.assignmentStore, Mockito.never()).insert(Mockito.any(Assignment.class));
+        Mockito.verify(this.assignmentStore, Mockito.never()).insert(any(Assignment.class));
     }
 
     @Test
@@ -137,7 +138,7 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.errors", hasSize(1)))
                 .andExpect(jsonPath("$.errors[0].code", equalTo("INVALID_ASSIGNMENT_NAME")));
 
-        Mockito.verify(this.assignmentStore, Mockito.never()).insert(Mockito.any(Assignment.class));
+        Mockito.verify(this.assignmentStore, Mockito.never()).insert(any(Assignment.class));
     }
 
     @Test
@@ -150,12 +151,12 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.errors", hasSize(1)))
                 .andExpect(jsonPath("$.errors[0].code", equalTo("INVALID_LANGUAGE")));
 
-        Mockito.verify(this.assignmentStore, Mockito.never()).insert(Mockito.any(Assignment.class));
+        Mockito.verify(this.assignmentStore, Mockito.never()).insert(any(Assignment.class));
     }
 
     @Test
     public void testCreateDuplicateName() throws Exception {
-        Mockito.when(this.assignmentStore.insert(Mockito.any(Assignment.class)))
+        Mockito.when(this.assignmentStore.insert(any(Assignment.class)))
                 .thenThrow(DuplicateKeyException.class);
 
         this.mvc.perform(request(HttpMethod.POST, "/api/v1/assignment")
@@ -166,7 +167,7 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.errors", hasSize(1)))
                 .andExpect(jsonPath("$.errors[0].code", equalTo("ASSIGNMENT_ALREADY_EXISTS")));
 
-        Mockito.verify(this.assignmentStore, Mockito.never()).save(Mockito.any());
+        Mockito.verify(this.assignmentStore, Mockito.never()).save(any());
     }
 
     @Test
@@ -180,7 +181,7 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.id", equalTo(ID)));
 
         Mockito.verify(this.assignmentStore, Mockito.times(1))
-                .save(Mockito.any(Assignment.class));
+                .save(any(Assignment.class));
     }
 
     @Test
@@ -193,12 +194,12 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.errors", hasSize(1)))
                 .andExpect(jsonPath("$.errors[0].code", equalTo("MISSING_FIELD")));
 
-        Mockito.verify(this.assignmentStore, Mockito.never()).save(Mockito.any());
+        Mockito.verify(this.assignmentStore, Mockito.never()).save(any());
     }
 
     @Test
     public void testUpdateDuplicateName() throws Exception {
-        Mockito.when(this.assignmentStore.save(Mockito.any(Assignment.class)))
+        Mockito.when(this.assignmentStore.save(any(Assignment.class)))
                 .thenThrow(DuplicateKeyException.class);
 
         this.mvc.perform(request(HttpMethod.PUT, "/api/v1/assignment/existing")
@@ -209,7 +210,7 @@ public class AssignmentControllerTest {
                 .andExpect(jsonPath("$.errors", hasSize(1)))
                 .andExpect(jsonPath("$.errors[0].code", equalTo("ASSIGNMENT_ALREADY_EXISTS")));
 
-        Mockito.verify(this.assignmentStore, Mockito.times(1)).save(Mockito.any());
+        Mockito.verify(this.assignmentStore, Mockito.times(1)).save(any());
     }
 
     @Test
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..f61a21dfbcb0354098e96575e506792b03aa8d94
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerIntegrationTest.java
@@ -0,0 +1,42 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import nl.tudelft.ewi.auta.core.benchmarking.BenchmarkingData;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.test.context.support.WithMockUser;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@EnableAutoConfiguration
+public class BenchmarkingControllerIntegrationTest extends AbstractWebSecurityIntegrationTest {
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotAccessUnautorizedSubmission() throws Exception {
+        this.postForbidden("/api/v1/assignment/assignment1/submission/submission1/benchmark/"
+                + "rank", new BenchmarkingData());
+
+        this.getForbidden("/api/v1/assignment/assignment1/submission/submission1/benchmark/"
+                + "score");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCanAccessAuthorizedSubmissionRank() throws Exception {
+        this.mockMvc.perform(this.withJsonBody(post("/api/v1/assignment/assignment2/"
+                + "submission/submission2/benchmark/"), new BenchmarkingData()))
+                .andExpect(status().is(Matchers.not(HttpStatus.FORBIDDEN.value())));
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCanAccessAuthorizedSubmissionScore() throws Exception {
+        this.mockMvc.perform(get("/api/v1/assignment/assignment2/"
+                + "submission/submission2/benchmark/score"))
+                .andExpect(status().is(Matchers.not(HttpStatus.FORBIDDEN.value())));
+    }
+}
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerTest.java
index f76412dd8002bafd6d940a87bccf0bb5ca3b57b0..c5d77a9551c0e7fbc14014768de45d2fd83ecd39 100644
--- a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerTest.java
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/BenchmarkingControllerTest.java
@@ -67,6 +67,9 @@ public class BenchmarkingControllerTest extends JsonControllerTestHelper {
     @Mock
     private BadgeGenerator generator;
 
+    @Mock
+    CourseSecuredService securedService;
+
     @InjectMocks
     private BenchmarkingController controller;
 
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..357c030039acc93854bbca9c359b6e179013016d
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerIntegrationTest.java
@@ -0,0 +1,120 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import com.google.gson.Gson;
+import nl.tudelft.ewi.auta.core.database.CourseRepository;
+import nl.tudelft.ewi.auta.core.model.Course;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.security.test.context.support.WithMockUser;
+
+import java.util.Map;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.request;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@EnableAutoConfiguration
+public class CourseControllerIntegrationTest extends AbstractWebSecurityIntegrationTest {
+
+    @Test
+    @WithMockUser(username = "admin", roles = "ADMIN")
+    public void adminCanViewAuthorizedCourse() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/course/course1"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.course.id", is("course1")));
+    }
+
+    @Test
+    @WithMockUser(username = "bob", roles = "ADMIN")
+    public void adminCanViewAllCoursesTest() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/course"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.courses", hasSize(3)));
+    }
+
+    @Test
+    @WithMockUser(username = "ta", roles = "TA")
+    public void taCannotViewAllCoursesTest() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/course"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.courses", hasSize(2)));
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotViewAllCoursesTest() throws Exception {
+        this.mockMvc.perform(request(HttpMethod.GET, "/api/v1/course"))
+                .andExpect(status().isOk())
+                .andExpect(jsonPath("$.courses", hasSize(2)));
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseGet() throws Exception {
+        this.getForbidden("/api/v1/course/course1");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseDelete() throws Exception {
+        this.deleteForbidden("/api/v1/course/course1");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseUpdateCourse() throws Exception {
+        final var newCourse = new Course();
+        newCourse.setYear(2025);
+        newCourse.setCourseCode("1234");
+        newCourse.setName("course name");
+        this.putForbidden("/api/v1/course/course1", newCourse);
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseAddUser() throws Exception {
+        this.putForbidden("/api/v1/course/course1/user",
+                Map.of("username", "instructor", "role", "ROLE_TEACHER"));
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseDeleteUser() throws Exception {
+        this.deleteForbidden("/api/v1/course/course1/user/ROLE_TEACHER/instructor");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseAddAssignment() throws Exception {
+        this.putForbidden("/api/v1/course/course1/assignment", Map.of("aid",
+                "assignment1"));
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCanAccessAuthorizedCourseAddAssignment(
+            @Autowired final CourseRepository courseRepository
+    ) throws Exception {
+        this.mockMvc.perform(put("/api/v1/course/course2/assignment")
+                .content(new Gson().toJson(Map.of("aid", "assignment1")))
+                .contentType(MediaType.APPLICATION_JSON))
+                .andExpect(status().isOk());
+
+        final var course = courseRepository.findExisting("course2");
+        assertThat(course.getAssignmentIds()).contains("assignment1");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void userCannotAccessUnauthorizedCourseDeleteAssignment() throws Exception {
+        this.deleteForbidden("/api/v1/course/course1/assignment/aid");
+    }
+}
+
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerTest.java
index 0f4aa67a3fc5e84e4a478a31f9db6d692106f695..45c09e7b5a49d9413d920b7375e60a1b86a04b4f 100644
--- a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerTest.java
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/CourseControllerTest.java
@@ -19,7 +19,6 @@ import org.junit.jupiter.params.provider.CsvSource;
 import org.mockito.AdditionalMatchers;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.Spy;
 import org.springframework.http.HttpMethod;
 import org.springframework.http.MediaType;
@@ -39,6 +38,8 @@ import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -52,26 +53,24 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
 
 public class CourseControllerTest extends JsonControllerTestHelper {
 
+    private static final String CID = "cid";
+    private static final String AID = "aid";
+    private static final String AID_ALREADY_EXISTS = "alreadyExists";
     private MockMvc mvc;
-
     @Mock
     private Repositories repositories;
-
     @Mock
     private CourseRepository courseRepository;
-
     @Mock
     private AssignmentRepository assignmentRepository;
-
     @Mock
     private DatabaseConnection databaseConnection;
 
+    @InjectMocks
     @Spy
     private CourseSecuredService securedService;
-
     @Mock
     private DatabaseConnector databaseConnector;
-
     private Course course;
 
     private AutaUser ta;
@@ -79,11 +78,6 @@ public class CourseControllerTest extends JsonControllerTestHelper {
     private AutaUser admin;
     private AutaUser student;
 
-    private static final String CID = "cid";
-    private static final String AID = "aid";
-    private static final String AID_ALREADY_EXISTS = "alreadyExists";
-
-    @InjectMocks
     private CourseController controller;
 
     @BeforeEach
@@ -91,9 +85,11 @@ public class CourseControllerTest extends JsonControllerTestHelper {
 
         initMocks(this);
 
-        //secured service
-        this.securedService = new CourseSecuredService();
-
+        this.controller = new CourseController(this.repositories, this.databaseConnector,
+                this.securedService);
+        doNothing().when(this.securedService).checkForCourseAccess(any());
+        doReturn(true).when(this.securedService)
+                .userHasCourseAccess(any(), any(Course.class));
         //courses
         this.course = new Course();
         this.course.setCourseCode("courseCode");
@@ -169,13 +165,13 @@ public class CourseControllerTest extends JsonControllerTestHelper {
 
     @Test
     public void addCourseDoesNotExistTest() throws Exception {
-        var courseWithId = new Course();
+        final var courseWithId = new Course();
         courseWithId.setId(CID);
         when(this.courseRepository.findByCodeAndYear(eq("otherCourseCode"), eq(2019)))
                 .thenReturn(Optional.empty());
         when(this.courseRepository.save(any())).thenReturn(courseWithId);
 
-        var newCourse = new Course();
+        final var newCourse = new Course();
         newCourse.setCourseCode("otherCourseCode");
         newCourse.setName("course name");
         newCourse.setYear(2019);
@@ -187,13 +183,13 @@ public class CourseControllerTest extends JsonControllerTestHelper {
                 .content(new Gson().toJson(newCourse)))
                 .andExpect(status().isOk())
                 .andExpect(jsonPath("$.id", equalTo(CID)));
-        verify(this.courseRepository, Mockito.atLeastOnce()).save(any());
+        verify(this.courseRepository, atLeastOnce()).save(any());
         verify(this.courseRepository, never()).save(eq(this.course));
     }
 
     @Test
     public void addCourseInvalidTest() throws Exception {
-        var newCourse = new Course();
+        final var newCourse = new Course();
         newCourse.setCourseCode("otherCourseCode");
         newCourse.setName("course name");
         //no year
@@ -209,7 +205,7 @@ public class CourseControllerTest extends JsonControllerTestHelper {
 
     @Test
     public void addCourseMissingNameTest() throws Exception {
-        var newCourse = new Course();
+        final var newCourse = new Course();
         newCourse.setCourseCode("otherCourseCode");
         newCourse.setYear(2019);
         // Serializes the course object, should already exist in the repository.
@@ -223,7 +219,7 @@ public class CourseControllerTest extends JsonControllerTestHelper {
 
     @Test
     public void addCourseMissingCourseCodeTest() throws Exception {
-        var newCourse = new Course();
+        final var newCourse = new Course();
         newCourse.setName("course name");
         newCourse.setYear(2019);
         //no year
@@ -239,7 +235,7 @@ public class CourseControllerTest extends JsonControllerTestHelper {
 
     @Test
     public void addCourseTooOldTest() throws Exception {
-        var newCourse = new Course();
+        final var newCourse = new Course();
         newCourse.setName("course name");
         newCourse.setCourseCode("otherCourseCode");
         newCourse.setYear(1835);
@@ -254,8 +250,6 @@ public class CourseControllerTest extends JsonControllerTestHelper {
     }
 
 
-
-
     //Adding users with too low authorities should fail
     @ParameterizedTest
     @CsvSource({"student, ROLE_TA", "student, ROLE_TEACHER", "ta, ROLE_TEACHER"})
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e6035020f78c404b227b1b2c86ab11722c6ce4c8
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerIntegrationTest.java
@@ -0,0 +1,21 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.security.test.context.support.WithMockUser;
+
+@EnableAutoConfiguration
+public class ReportControllerIntegrationTest extends AbstractWebSecurityIntegrationTest {
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotAccessUnauthorizedSubmission() throws Exception {
+        this.getForbidden("/api/v1/assignment/assignment1/submission/submission1/verdict");
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCanAccessAuthorizedSubmission() throws Exception {
+        this.getExpectOk("/api/v1/assignment/assignment2/submission/submission2/verdict");
+    }
+}
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerTest.java
index a3fa32c3dc21ad5c9b6bbdbdae69ff49380a353a..7d793cba43f65c6ff5b02248b019aaf47e1a2449 100644
--- a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerTest.java
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/ReportControllerTest.java
@@ -45,6 +45,9 @@ public class ReportControllerTest {
     @Mock
     private EntityRepository entityRepository;
 
+    @Mock
+    private CourseSecuredService securedService;
+
     private static final String ID = "UNIQUE_ID";
 
     @InjectMocks
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..5a7823093f394615b3fbf79281830228877c747e
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerIntegrationTest.java
@@ -0,0 +1,54 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.test.context.support.WithMockUser;
+
+import java.util.Map;
+
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@EnableAutoConfiguration
+public class SubmissionControllerIntegrationTest extends AbstractWebSecurityIntegrationTest {
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "/api/v1/assignment/assignment1/submission",
+            "/api/v1/assignment/assignment1/submission/submission1"
+    })
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotAccessUnauthorizedSubmission(final String input) throws Exception {
+        this.getForbidden(input);
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotAddNewUnauthorizedSubmission() throws Exception {
+        this.postForbidden("/api/v1/assignment/assignment1/submission",
+                Map.of());
+    }
+
+    @Test
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCanAddNewSubmission() throws Exception {
+        this.mockMvc.perform(
+                this.withJsonBody(
+                        post("/api/v1/assignment/assignment2/submission"),
+                        Map.of("name", "new-submission")))
+                .andExpect(status().is(HttpStatus.CREATED.value()));
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "/api/v1/assignment/assignment2/submission",
+            "/api/v1/assignment/assignment2/submission/submission2"
+    })
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCanAccessAuthorizedSubmission(final String input) throws Exception {
+        this.getExpectOk(input);
+    }
+}
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerTest.java
index 8eb452c0e16ea863b29801a0ea427301de0ae418..b7e8b818b701de587ffe227ca5c7813dd6f0860d 100644
--- a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerTest.java
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionControllerTest.java
@@ -93,6 +93,8 @@ public class SubmissionControllerTest {
     @Mock
     private IdentityRepository identityRepository;
 
+    @Mock
+    CourseSecuredService securedService;
 
     @InjectMocks
     private SubmissionController controller;
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerIntegrationTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d24e4c32cc4601239c0d8f6268d1c001ab8ade76
--- /dev/null
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerIntegrationTest.java
@@ -0,0 +1,32 @@
+package nl.tudelft.ewi.auta.core.controller;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.security.test.context.support.WithMockUser;
+
+@EnableAutoConfiguration
+public class SubmissionExportControllerIntegrationTest extends AbstractWebSecurityIntegrationTest {
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "/api/v1/assignment/assignment1/export",
+            "/api/v1/assignment/assignment1/export/id1"
+    })
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCannotAccessUnauthorizedSubmissionExport(final String input)
+            throws Exception {
+        this.getForbidden(input);
+    }
+
+    @ParameterizedTest
+    @ValueSource(strings = {
+            "/api/v1/assignment/assignment2/export",
+            "/api/v1/assignment/assignment2/export/id2"
+    })
+    @WithMockUser(username = "instructor", roles = "TEACHER")
+    public void instructorCanAccessAuthorizedSubmissionExport(final String input)
+            throws Exception {
+        this.getExpectOk(input);
+    }
+}
diff --git a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerTest.java b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerTest.java
index 27e399b49363fad7cfe03c1b411e5b8a9e5e7d12..b915bf315973facc278101353d5c5018970e340c 100644
--- a/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerTest.java
+++ b/core/src/test/java/nl/tudelft/ewi/auta/core/controller/SubmissionExportControllerTest.java
@@ -29,10 +29,10 @@ import static org.assertj.core.api.Assertions.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.hasSize;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.any;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.asyncDispatch;
 import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
@@ -77,12 +77,13 @@ public class SubmissionExportControllerTest {
 
     private Assignment assignment;
 
+    private CourseSecuredService securedService;
     private MockMvc mvc;
 
     @BeforeEach
     public void before() {
         // Dependencies
-
+        this.securedService = mock(CourseSecuredService.class);
         this.repositories = RepositoriesTestHelper.getMockRepositories();
         this.gson = new Gson();
         this.mongoTemplate = mock(MongoTemplate.class);
@@ -176,7 +177,7 @@ public class SubmissionExportControllerTest {
         // Spring
 
         this.mvc = MockMvcBuilders.standaloneSetup(new SubmissionExportController(
-                        this.repositories, this.gson, this.mongoTemplate
+                        this.repositories, this.gson, this.mongoTemplate, this.securedService
                 ))
                 .setControllerAdvice(new RestExceptionHandler())
                 .build();
diff --git a/core/src/test/resources/application.properties b/core/src/test/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..c9297a6f5b877e799ba34a9a5232681f7ac1be78
--- /dev/null
+++ b/core/src/test/resources/application.properties
@@ -0,0 +1,9 @@
+logging.level.org.springframework.web=TRACE
+logging.level.org.springframework.boot.autoconfigure.mongo.embedded=TRACE
+logging.level.org.mongodb = DEBUG
+logging.file=test.log
+spring.servlet.multipart.max-file-size=128MB
+spring.servlet.multipart.max-request-size=128MB
+spring.data.mongodb.port=0
+spring.data.mongodb.database=auta-test
+spring.data.mongodb.host=localhost
diff --git a/src/main/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntity.java b/src/main/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntity.java
index 86a1d02b27b1f52bda18db5e8be1b328b826763d..2ec23b1ffcd371434f7d8a64d557778d89eacb98 100644
--- a/src/main/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntity.java
+++ b/src/main/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntity.java
@@ -1,7 +1,10 @@
 package nl.tudelft.ewi.auta.common.model.entity;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Set;
 
 public class ProjectEntity extends Entity {
 
@@ -82,4 +85,16 @@ public class ProjectEntity extends Entity {
         }
         this.addAll(toBeAdded);
     }
+
+    /**
+     * Returns all entities in the project, including the project entity itself.
+     *
+     * @return all entities in the project
+     */
+    @JsonIgnore
+    public Set<Entity> getAllEntities() {
+        final var children = this.getAllChildren();
+        children.add(this);
+        return children;
+    }
 }
diff --git a/src/test/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntityTest.java b/src/test/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntityTest.java
index df95acbb2aa4952cc413cb8491a5311eba3966fb..5bc97014ceab926aee3ea003b96e16e11326172f 100644
--- a/src/test/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntityTest.java
+++ b/src/test/java/nl/tudelft/ewi/auta/common/model/entity/ProjectEntityTest.java
@@ -83,4 +83,10 @@ public class ProjectEntityTest {
         assertThat(recoverEntity).isEqualTo(this.projectEntity);
 
     }
+
+    @Test
+    public void testGetAllEntitiesIncludesProject() {
+        final var entities = this.projectEntity.getAllEntities();
+        assertThat(entities).contains(this.projectEntity);
+    }
 }