diff --git a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java
index 12612c22e05806d2f4dd3d2dbf3e248b9268489f..1bbd9be6a3cf818565fe33ca590b7cc8f7c2f2b5 100644
--- a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java
+++ b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java
@@ -52,6 +52,7 @@ public class ContainerEndpoint {
     }
 
     @PostMapping
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
     @ApiOperation(value = "Creates a new container", notes = "Creates a new container whose image is registered in the metadata database too.")
     @ApiResponses({
             @ApiResponse(code = 201, message = "Successfully created a new container."),
@@ -82,6 +83,7 @@ public class ContainerEndpoint {
     }
 
     @PutMapping("/{id}")
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
     @ApiOperation(value = "Change the state of a container", notes = "The new state can only be one of START/STOP.")
     @ApiResponses({
             @ApiResponse(code = 202, message = "Changed the state of a container."),
diff --git a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java
index 09f7591ea9cb5e06fe4f189865c82b30a9e1ce48..701cb98379e53399b05234ef208ef07669a9f746 100644
--- a/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java
+++ b/fda-container-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java
@@ -57,7 +57,7 @@ public class ImageEndpoint {
     }
 
     @PostMapping
-    @PreAuthorize("hasRole('DEVELOPER')")
+    @PreAuthorize("hasRole('ROLE_DEVELOPER')")
     @ApiOperation(value = "Creates a new image", notes = "Creates a new image in the metadata database.")
     @ApiResponses({
             @ApiResponse(code = 201, message = "Successfully created a new image."),
diff --git a/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerDatabaseEndpoint.java b/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerDatabaseEndpoint.java
index cca4dca86db0a4864872943ded15141b355deea5..db25122bef1dfa2b6453715319d4cdba307aeac1 100644
--- a/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerDatabaseEndpoint.java
+++ b/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerDatabaseEndpoint.java
@@ -52,6 +52,7 @@ public class ContainerDatabaseEndpoint {
     }
 
     @PostMapping
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
     @ApiOperation(value = "Creates a new database in a container", notes = "Creates a new database in a container. Note that the backend distincts between numerical (req: categories), nominal (req: max_length) and categorical (req: max_length, siUnit, min, max, mean, median, standard_deviation, histogram) column types.")
     @ApiResponses({
             @ApiResponse(code = 201, message = "The database was successfully created."),
diff --git a/fda-identifier-service/pom.xml b/fda-identifier-service/pom.xml
index f69d3d5930dc2bc94561b4ca58772843e430c0c9..f59daef8532905c2b4771a98f7eef5a816d549f6 100644
--- a/fda-identifier-service/pom.xml
+++ b/fda-identifier-service/pom.xml
@@ -51,6 +51,16 @@
             <artifactId>spring-cloud-starter-bootstrap</artifactId>
             <version>${spring-cloud.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>javax.ws.rs</groupId>
             <artifactId>javax.ws.rs-api</artifactId>
diff --git a/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
index 8f3d287871eff0e418cbb3a42292a4d61fc34450..18f795121b5dd921a7172e35fc9547f45ba63a63 100644
--- a/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
+++ b/fda-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
@@ -12,6 +12,7 @@ import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
@@ -57,7 +58,8 @@ public class IdentifierEndpoint {
     }
 
     @PostMapping
-    @ApiOperation(value = "Create ID", notes = "Get Data from a Table in the database.")
+    @PreAuthorize("hasRole('ROLE_RESEARCHER') or hasRole('ROLE_DATA_STEWARD')")
+    @ApiOperation(value = "Create ID", notes = "Create a new identifier")
     @ApiResponses({
             @ApiResponse(code = 201, message = "Created the ID."),
             @ApiResponse(code = 401, message = "Not authorized to update tables."),
@@ -104,6 +106,7 @@ public class IdentifierEndpoint {
     }
 
     @DeleteMapping("/{identiferId}")
+    @PreAuthorize("hasRole('ROLE_DATA_STEWARD') or hasRole('ROLE_DEVELOPER')")
     @ApiOperation(value = "Delete ID", notes = "Get Data from a Table in the database.")
     @ApiResponses({
             @ApiResponse(code = 200, message = "Get data from the table."),
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/fda-identifier-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6bcb362bcd7ed5d338c250782c68145597fce5df
--- /dev/null
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
@@ -0,0 +1,56 @@
+package at.tuwien.auth;
+
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    public AuthTokenFilter(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        String jwt = parseJwt(request);
+        log.debug("parsed jwt {}", jwt);
+        if (jwt != null) {
+            final UserDetails userDetails = authenticationServiceGateway.validate(jwt);
+            final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+                    userDetails, null, userDetails.getAuthorities());
+            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }
+        filterChain.doFilter(request, response);
+    }
+
+    /**
+     * Parses the token from the HTTP header of the request
+     *
+     * @param request The request.
+     * @return The token.
+     */
+    private String parseJwt(HttpServletRequest request) {
+        String headerAuth = request.getHeader("Authorization");
+        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
+            return headerAuth.substring(7, headerAuth.length());
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/fda-identifier-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
index daa14ed009686194a3f0e6edea0aed2f8424830c..252235a1eb97fcee790d7cf270935f06924f007f 100644
--- a/fda-identifier-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
@@ -1,23 +1,21 @@
 package at.tuwien.config;
 
-import lombok.Getter;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.util.DefaultUriBuilderFactory;
 
-@Getter
 @Configuration
 public class GatewayConfig {
 
-    @Value("${fda.gateway.endpoint}")
-    private String gatewayEndpoint;
+    @Value("${fda.auth.endpoint}")
+    private String authEndpoint;
 
     @Bean
     public RestTemplate restTemplate() {
         final RestTemplate restTemplate =  new RestTemplate();
-        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(authEndpoint));
         return restTemplate;
     }
 
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/fda-identifier-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..b5e82d5dc0ed126ab015896fe9cd8d9aa78a29e4
--- /dev/null
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
@@ -0,0 +1,82 @@
+package at.tuwien.config;
+
+import at.tuwien.auth.AuthTokenFilter;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.servlet.http.HttpServletResponse;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    @Autowired
+    public WebSecurityConfig(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Bean
+    public AuthTokenFilter authTokenFilter() {
+        return new AuthTokenFilter(authenticationServiceGateway);
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        /* enable CORS and disable CSRF */
+        http = http.cors().and().csrf().disable();
+        /* set session management to stateless */
+        http = http
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and();
+        /* set unauthorized requests exception handler */
+        http = http
+                .exceptionHandling()
+                .authenticationEntryPoint(
+                        (request, response, ex) -> {
+                            response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+                                    ex.getMessage()
+                            );
+                        }
+                ).and();
+        /* set permissions on endpoints */
+        http.authorizeRequests()
+                /* our public endpoints */
+                .antMatchers(HttpMethod.GET, "/api/container/**/database/**/identifier/**").permitAll()
+                .antMatchers(HttpMethod.GET, "/api/pid/**").permitAll()
+                /* our private endpoints */
+                .anyRequest().authenticated();
+        /* add JWT token filter */
+        http.addFilterBefore(authTokenFilter(),
+                UsernamePasswordAuthenticationFilter.class
+        );
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        final CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        config.addAllowedOrigin("*");
+        config.addAllowedHeader("*");
+        config.addAllowedMethod("*");
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+
+}
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java b/fda-identifier-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc47ce246da851244cf1630b15f493ded20249d8
--- /dev/null
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
@@ -0,0 +1,14 @@
+package at.tuwien.gateway;
+
+import org.springframework.security.core.userdetails.UserDetails;
+
+public interface AuthenticationServiceGateway {
+
+    /**
+     * Validates a token
+     *
+     * @param token The token
+     * @return User details on success
+     */
+    UserDetails validate(String token);
+}
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java b/fda-identifier-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..30507c4b6e662a7e772e85c609fdb5fbc563a99f
--- /dev/null
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
@@ -0,0 +1,36 @@
+package at.tuwien.gateway.impl;
+
+import at.tuwien.api.user.UserDto;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import at.tuwien.mapper.UserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
+
+    private final UserMapper userMapper;
+    private final RestTemplate restTemplate;
+
+    @Autowired
+    public AuthenticationServiceGatewayImpl(UserMapper userMapper, RestTemplate restTemplate) {
+        this.userMapper = userMapper;
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public UserDetails validate(String token) {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.set("Authorization", "Bearer " + token);
+        final ResponseEntity<UserDto> response = restTemplate.exchange("/api/auth", HttpMethod.PUT,
+                new HttpEntity<>("", headers), UserDto.class);
+        return userMapper.userDtoToUserDetailsDto(response.getBody());
+    }
+
+}
diff --git a/fda-identifier-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f14430e9675c7a152c778df18fc892e3423afdc6
--- /dev/null
+++ b/fda-identifier-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
@@ -0,0 +1,18 @@
+package at.tuwien.mapper;
+
+import at.tuwien.api.user.GrantedAuthorityDto;
+import at.tuwien.api.user.UserDetailsDto;
+import at.tuwien.api.user.UserDto;
+import org.mapstruct.Mapper;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+@Mapper(componentModel = "spring")
+public interface UserMapper {
+
+    UserDetailsDto userDtoToUserDetailsDto(UserDto data);
+
+    default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) {
+        return new SimpleGrantedAuthority(data.getAuthority());
+    }
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java
index ea16db6f94a38d24cd58a6ac705f46ab1cda980d..41c49b17d642ac07c838be68e8fed6b4d78d1143 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/ExecuteStatementDto.java
@@ -26,5 +26,5 @@ public class ExecuteStatementDto {
 
     @NotNull
     @ApiModelProperty(name = "columns mentioned in the query")
-    private List<List<ColumnBriefDto>> columns;
+    private List<ColumnBriefDto> columns;
 }
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java
index cfc176a8573e9b051ed21e0b68c2689e84d42e57..c2f4a798d75b2be0e60032ec27f4d8fb02e8ceff 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryResultDto.java
@@ -4,7 +4,6 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.*;
 
 import javax.validation.constraints.NotNull;
-import java.math.BigInteger;
 import java.util.List;
 import java.util.Map;
 
@@ -17,9 +16,6 @@ import java.util.Map;
 @ToString
 public class QueryResultDto {
 
-    @ApiModelProperty(notes = "query count")
-    private BigInteger count;
-
     @NotNull
     @ApiModelProperty(notes = "query result")
     private List<Map<String, Object>> result;
diff --git a/fda-query-service/pom.xml b/fda-query-service/pom.xml
index 1516cbcf8513df52a00fbf5636c462d611d09379..f1cd8e06ea4da4831e683351d3aee223680febb2 100644
--- a/fda-query-service/pom.xml
+++ b/fda-query-service/pom.xml
@@ -57,6 +57,15 @@
             <artifactId>spring-cloud-starter-bootstrap</artifactId>
             <version>${spring-cloud.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
         <!-- Data Source -->
         <dependency>
             <groupId>org.postgresql</groupId>
diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/DataEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/DataEndpoint.java
index a3fb4ec88c7ebfc63c864e5540f23fa643869e91..ca5838d52809bfca59f31ac9fff3508afb5aa5bc 100644
--- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/DataEndpoint.java
+++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/DataEndpoint.java
@@ -3,7 +3,6 @@ package at.tuwien.endpoint;
 import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.TableCsvDto;
 import at.tuwien.exception.*;
-import at.tuwien.service.CommaValueService;
 import at.tuwien.service.QueryService;
 import io.swagger.annotations.ApiOperation;
 import io.swagger.annotations.ApiResponse;
@@ -16,28 +15,25 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
-import javax.transaction.Transactional;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import java.math.BigInteger;
 import java.time.Instant;
 
 @Log4j2
 @CrossOrigin(origins = "*")
 @RestController
-@RequestMapping("/api/container/{id}/database/{databaseId}/table/{tableId}/data")
+@RequestMapping("/api/container/{id}/database/{databaseId}/data")
 public class DataEndpoint {
 
     private final QueryService queryService;
-    private final CommaValueService commaValueService;
 
     @Autowired
-    public DataEndpoint(QueryService queryService, CommaValueService commaValueService) {
+    public DataEndpoint(QueryService queryService) {
         this.queryService = queryService;
-        this.commaValueService = commaValueService;
     }
 
-    @Transactional
-    @PostMapping
+    @PostMapping("/api/container/{id}/database/{databaseId}/table/{tableId}/data")
     @ApiOperation(value = "Insert values", notes = "Insert Data into a Table in the database. When the location string is set, the data argument is ignored and the location is used as data input")
     @ApiResponses({
             @ApiResponse(code = 201, message = "Updated the table."),
@@ -67,8 +63,7 @@ public class DataEndpoint {
                 .body(queryService.insert(id, databaseId, tableId, data));
     }
 
-    @Transactional
-    @GetMapping
+    @GetMapping("/api/container/{id}/database/{databaseId}/table/{tableId}/data")
     @ApiOperation(value = "Get values", notes = "Get Data from a Table in the database.")
     @ApiResponses({
             @ApiResponse(code = 200, message = "Get data from the table."),
@@ -80,16 +75,10 @@ public class DataEndpoint {
                                                  @NotNull @PathVariable("databaseId") Long databaseId,
                                                  @NotNull @PathVariable("tableId") Long tableId,
                                                  @RequestParam(required = false) Instant timestamp,
-                                                 @RequestParam(required = false) String total,
                                                  @RequestParam(required = false) Long page,
                                                  @RequestParam(required = false) Long size)
             throws TableNotFoundException, DatabaseNotFoundException, DatabaseConnectionException,
             ImageNotSupportedException, TableMalformedException, PaginationException, ContainerNotFoundException {
-        if (total != null) {
-            /* we ignore the value */
-            final QueryResultDto response = queryService.count(id, databaseId, tableId, timestamp);
-            return ResponseEntity.ok(response);
-        }
         if ((page == null && size != null) || (page != null && size == null)) {
             log.error("Cannot perform pagination with only one of page/size set.");
             log.debug("invalid pagination specification, one of page/size is null, either both should be null or none.");
@@ -101,12 +90,41 @@ public class DataEndpoint {
         if (size != null && size <= 0) {
             throw new PaginationException("Page number cannot be lower or equal to 0");
         }
+        final BigInteger count = queryService.count(id, databaseId, tableId, timestamp);
+        final HttpHeaders headers = new HttpHeaders();
+        headers.set("FDA-COUNT", count.toString());
         final QueryResultDto response = queryService.findAll(id, databaseId, tableId, timestamp, page, size);
-        return ResponseEntity.ok(response);
+        return ResponseEntity.ok()
+                .headers(headers)
+                .body(response);
+    }
+
+    @RequestMapping(value = "/api/container/{id}/database/{databaseId}/table/{tableId}/data", method = RequestMethod.HEAD)
+    @ApiOperation(value = "Get values", notes = "Get Data Count from a Table in the database.")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "Get data from the table."),
+            @ApiResponse(code = 401, message = "Not authorized to update tables."),
+            @ApiResponse(code = 404, message = "The table is not found in database."),
+            @ApiResponse(code = 405, message = "The connection to the database was unsuccessful."),
+    })
+    public ResponseEntity<QueryResultDto> getCount(@NotNull @PathVariable("id") Long id,
+                                                   @NotNull @PathVariable("databaseId") Long databaseId,
+                                                   @NotNull @PathVariable("tableId") Long tableId,
+                                                   @RequestParam(required = false) Instant timestamp)
+            throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
+            TableMalformedException, ContainerNotFoundException {
+        final BigInteger count = queryService.count(id, databaseId, tableId, timestamp);
+        final HttpHeaders headers = new HttpHeaders();
+        headers.set("FDA-COUNT", count.toString());
+        return ResponseEntity.ok()
+                .headers(headers)
+                .build();
     }
 
-    @Transactional
-    @GetMapping(value = "/export")
+    /**
+     * todo use dbs internal export functionality
+     */
+    @GetMapping(value = "/api/container/{id}/database/{databaseId}/table/{tableId}/export")
     @ApiOperation(value = "Download export", notes = "Get Data from a Table in the database.")
     @ApiResponses({
             @ApiResponse(code = 200, message = "Get data from the table."),
@@ -121,10 +139,11 @@ public class DataEndpoint {
             throws TableNotFoundException, DatabaseNotFoundException, DatabaseConnectionException,
             ImageNotSupportedException, TableMalformedException, FileStorageException, PaginationException,
             ContainerNotFoundException {
-        final InputStreamResource data = commaValueService.export(id, databaseId, tableId, timestamp);
-        HttpHeaders headers = new HttpHeaders();
-        headers.add("Content-Disposition", "attachment; filename=\"export.csv\"");
-        return new ResponseEntity<>(data, headers, HttpStatus.OK);
+//        final HttpHeaders headers = new HttpHeaders();
+//        headers.add("Content-Disposition", "attachment; filename=\"export.csv\"");
+//        return new ResponseEntity<>(data, headers, HttpStatus.OK);
+        return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED)
+                .build();
     }
 
 
diff --git a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
index 7a1d20dda101098809c3e6cf4d7f53716991e28f..2bdaddedb36c523f765ddc6c369d73a1aa4064cb 100644
--- a/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
+++ b/fda-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java
@@ -20,7 +20,7 @@ import javax.validation.constraints.NotNull;
 
 @Log4j2
 @RestController
-@RequestMapping("/api/container/{id}/database/{databaseId}/table/{tableId}/query")
+@RequestMapping("/api/container/{id}/database/{databaseId}/query")
 public class QueryEndpoint {
 
     private final QueryMapper queryMapper;
@@ -43,7 +43,6 @@ public class QueryEndpoint {
             @ApiResponse(code = 409, message = "The container image is not supported."),})
     public ResponseEntity<QueryResultDto> execute(@NotNull @PathVariable("id") Long id,
                                                   @NotNull @PathVariable("databaseId") Long databaseId,
-                                                  @NotNull @PathVariable("tableId") Long tableId,
                                                   @NotNull @RequestBody @Valid ExecuteStatementDto data)
             throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException, QueryMalformedException,
             TableNotFoundException, ContainerNotFoundException {
@@ -56,7 +55,7 @@ public class QueryEndpoint {
             log.error("Table list is empty");
             throw new QueryMalformedException("Invalid table");
         }
-        final QueryResultDto result = queryService.execute(id, databaseId, tableId, data);
+        final QueryResultDto result = queryService.execute(id, databaseId, data);
         final QueryDto query = queryMapper.queryToQueryDto(storeService.insert(id, databaseId, result, data));
         result.setId(query.getId());
         return ResponseEntity.status(HttpStatus.ACCEPTED)
@@ -72,7 +71,6 @@ public class QueryEndpoint {
             @ApiResponse(code = 409, message = "The container image is not supported."),})
     public ResponseEntity<QueryDto> save(@NotNull @PathVariable("id") Long id,
                                          @NotNull @PathVariable("databaseId") Long databaseId,
-                                         @NotNull @PathVariable("tableId") Long tableId,
                                          @NotNull @RequestBody SaveStatementDto data)
             throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException,
             ContainerNotFoundException {
@@ -91,14 +89,13 @@ public class QueryEndpoint {
             @ApiResponse(code = 409, message = "The container image is not supported."),})
     public ResponseEntity<QueryResultDto> reExecute(@NotNull @PathVariable("id") Long id,
                                                     @NotNull @PathVariable("databaseId") Long databaseId,
-                                                    @NotNull @PathVariable("tableId") Long tableId,
                                                     @NotNull @PathVariable("queryId") Long queryId)
             throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
             TableNotFoundException, QueryMalformedException, ContainerNotFoundException {
         final Query query = storeService.findOne(id, databaseId, queryId);
         final QueryDto queryDto = queryMapper.queryToQueryDto(query);
         final ExecuteStatementDto statement = queryMapper.queryDtoToExecuteStatementDto(queryDto);
-        final QueryResultDto result = queryService.execute(id, databaseId, tableId, statement);
+        final QueryResultDto result = queryService.execute(id, databaseId, statement);
         result.setId(queryId);
         return ResponseEntity.status(HttpStatus.ACCEPTED)
                 .body(result);
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/DataEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/DataEndpointUnitTest.java
index 961e19d879d98a93072928cc50f967efe8872b71..545c8428d7c6235d850bb0393517ad3a1232a691 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/DataEndpointUnitTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/DataEndpointUnitTest.java
@@ -97,7 +97,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
             DatabaseNotFoundException, ImageNotSupportedException, PaginationException, ContainerNotFoundException {
 
         /* test */
-        dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, null, null, null, null);
+        dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, null, null, null);
     }
 
     @Test
@@ -108,7 +108,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
         final Long size = null;
 
         /* test */
-        dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+        dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
     }
 
     @Test
@@ -118,7 +118,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -129,7 +129,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -140,7 +140,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -151,7 +151,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -162,7 +162,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -173,7 +173,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -184,7 +184,7 @@ public class DataEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PaginationException.class, () -> {
-            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, null, page, size);
+            dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1_CREATED, page, size);
         });
     }
 
@@ -194,10 +194,10 @@ public class DataEndpointUnitTest extends BaseUnitTest {
             PaginationException, ContainerNotFoundException {
 
         /* test */
-        final ResponseEntity<InputStreamResource> respone = dataEndpoint.export(CONTAINER_1_ID, DATABASE_1_ID,
+        final ResponseEntity<InputStreamResource> response = dataEndpoint.export(CONTAINER_1_ID, DATABASE_1_ID,
                 TABLE_1_ID, null);
-        assertNotNull(respone);
-        assertEquals(HttpStatus.OK, respone.getStatusCode());
+        assertNotNull(response);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
     }
 
     @Test
@@ -208,10 +208,10 @@ public class DataEndpointUnitTest extends BaseUnitTest {
                 .minusMillis(1000 * 1000);
 
         /* test */
-        final ResponseEntity<InputStreamResource> respone = dataEndpoint.export(CONTAINER_1_ID, DATABASE_1_ID,
+        final ResponseEntity<InputStreamResource> response = dataEndpoint.export(CONTAINER_1_ID, DATABASE_1_ID,
                 TABLE_1_ID, request);
-        assertNotNull(respone);
-        assertEquals(HttpStatus.OK, respone.getStatusCode());
+        assertNotNull(response);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
 
     }
 
@@ -223,24 +223,37 @@ public class DataEndpointUnitTest extends BaseUnitTest {
                 .plusMillis(1000 * 1000);
 
         /* test */
-        final ResponseEntity<InputStreamResource> respone = dataEndpoint.export(CONTAINER_1_ID, DATABASE_1_ID,
+        final ResponseEntity<InputStreamResource> response = dataEndpoint.export(CONTAINER_1_ID, DATABASE_1_ID,
                 TABLE_1_ID, request);
-        assertNotNull(respone);
-        assertEquals(HttpStatus.OK, respone.getStatusCode());
+        assertNotNull(response);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
     }
 
     @Test
     public void getAllTotal_succeeds() throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
+            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
             PaginationException, ContainerNotFoundException {
         final Instant timestamp = Instant.now();
-        final String total = "1";
 
         /* test */
-        final ResponseEntity<QueryResultDto> respone = dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID,
-                TABLE_1_ID, timestamp, total, null, null);
-        assertNotNull(respone);
-        assertEquals(HttpStatus.OK, respone.getStatusCode());
+        final ResponseEntity<QueryResultDto> response = dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID,
+                TABLE_1_ID, timestamp, null, null);
+        assertNotNull(response);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+    }
+
+    @Test
+    public void getAllCount_succeeds() throws TableNotFoundException, DatabaseConnectionException,
+            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+            PaginationException, ContainerNotFoundException {
+        final Instant timestamp = Instant.now();
+
+        /* test */
+        final ResponseEntity<QueryResultDto> response = dataEndpoint.getAll(CONTAINER_1_ID, DATABASE_1_ID,
+                TABLE_1_ID, timestamp, null, null);
+        assertNotNull(response);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        assertTrue(response.getHeaders().containsKey("FDA-COUNT"));
     }
 
 }
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointIntegrationTest.java
index 8e435df1de50823b2080542a7325e7224190d8bd..93bb02dd2c6bcdedbe83d1fc20ca01493dcce74e 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointIntegrationTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointIntegrationTest.java
@@ -150,7 +150,7 @@ public class QueryEndpointIntegrationTest extends BaseUnitTest {
 
         /* test */
         final ResponseEntity<QueryResultDto> response = queryEndpoint.reExecute(CONTAINER_1_ID, DATABASE_1_ID,
-                TABLE_1_ID, QUERY_1_ID);
+                QUERY_1_ID);
         assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
         assertNotNull(response.getBody());
         assertEquals(QUERY_1_ID, response.getBody().getId());
@@ -168,8 +168,7 @@ public class QueryEndpointIntegrationTest extends BaseUnitTest {
         MariaDbConfig.clearQueryStore(TABLE_1);
 
         /* test */
-        final ResponseEntity<QueryDto> response = queryEndpoint.save(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID,
-                statement);
+        final ResponseEntity<QueryDto> response = queryEndpoint.save(CONTAINER_1_ID, DATABASE_1_ID, statement);
         assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
         assertNotNull(response.getBody());
         assertEquals(QUERY_1_ID, response.getBody().getId());
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java
index 5376d7d145a3f88e758cd9dfd3e422ea5a9043fa..061853cd7732d64a04e97f05ddad03da4d6fbc44 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/endpoint/QueryEndpointUnitTest.java
@@ -58,13 +58,13 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* mock */
-        when(queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request))
+        when(queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request))
                 .thenReturn(result);
         when(storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, request))
                 .thenReturn(QUERY_1);
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = queryEndpoint.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+        final ResponseEntity<QueryResultDto> response = queryEndpoint.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
         assertEquals(result, response.getBody());
     }
@@ -81,13 +81,13 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* mock */
-        when(queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request))
+        when(queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request))
                 .thenReturn(result);
         when(storeService.insert(CONTAINER_1_ID, DATABASE_1_ID, result, request))
                 .thenReturn(QUERY_1);
 
         /* test */
-        final ResponseEntity<QueryResultDto> response = queryEndpoint.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+        final ResponseEntity<QueryResultDto> response = queryEndpoint.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
         assertEquals(result, response.getBody());
     }
@@ -100,12 +100,12 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* mock */
-        when(queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request))
+        when(queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request))
                 .thenThrow(TableNotFoundException.class);
 
         /* test */
         assertThrows(TableNotFoundException.class, () -> {
-            queryEndpoint.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+            queryEndpoint.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         });
     }
 
@@ -121,7 +121,7 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
                 .thenReturn(QUERY_1);
 
         /* test */
-        final ResponseEntity<QueryDto> response = queryEndpoint.save(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+        final ResponseEntity<QueryDto> response = queryEndpoint.save(CONTAINER_1_ID, DATABASE_1_ID, request);
         assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
         assertEquals(QUERY_1_DTO, response.getBody());
     }
@@ -139,7 +139,7 @@ public class QueryEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(DatabaseNotFoundException.class, () -> {
-            queryEndpoint.save(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+            queryEndpoint.save(CONTAINER_1_ID, DATABASE_1_ID, request);
         });
     }
 
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java
index 14a4204d66e8d2f58a185c6804549874d298eb4c..69ed0e5dcc78fde81e5a9653c8462131d573b7f1 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/DataServiceIntegrationTest.java
@@ -13,15 +13,11 @@ import com.github.dockerjava.api.model.Bind;
 import com.github.dockerjava.api.model.Network;
 import com.rabbitmq.client.Channel;
 import lombok.extern.log4j.Log4j2;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.*;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.core.io.Resource;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
@@ -31,7 +27,6 @@ import java.util.Arrays;
 import static at.tuwien.config.DockerConfig.dockerClient;
 import static at.tuwien.config.DockerConfig.hostConfig;
 import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @Log4j2
 @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
@@ -134,13 +129,14 @@ public class DataServiceIntegrationTest extends BaseUnitTest {
     }
 
     @Test
+    @Disabled
     public void write_succeeds() throws TableNotFoundException, DatabaseConnectionException, TableMalformedException,
             DatabaseNotFoundException, ImageNotSupportedException, FileStorageException, PaginationException,
             ContainerNotFoundException {
 
         /* test */
-        final Resource response = dataService.export(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID);
-        assertTrue(response.exists());
+//        final Resource response = dataService.export(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID);
+//        assertTrue(response.exists());
     }
 
     @Test
diff --git a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
index c27f890cf32a0f3dc1cd5e324048b3da0e79a9d4..50d55717bd76dbba50399ea0c6899f2c496cb1dc 100644
--- a/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
+++ b/fda-query-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
@@ -187,7 +187,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
         DockerConfig.startContainer(CONTAINER_1);
 
         /* test */
-        final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+        final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         assertEquals(3, response.getResult().size());
         assertEquals(BigInteger.valueOf(1L), response.getResult().get(0).get(COLUMN_1_1_NAME));
         assertEquals(toInstant("2008-12-01"), response.getResult().get(0).get(COLUMN_1_2_NAME));
@@ -220,26 +220,11 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
         DockerConfig.startContainer(CONTAINER_1);
 
         /* test */
-        final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+        final QueryResultDto response = queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         assertNotNull(response.getResult());
         assertEquals(3, response.getResult().size());
     }
 
-    @Test
-    public void execute_tableNotExists_fails() throws InterruptedException {
-        final ExecuteStatementDto request = ExecuteStatementDto.builder()
-                .statement(QUERY_1_STATEMENT)
-                .build();
-
-        /* mock */
-        DockerConfig.startContainer(CONTAINER_1);
-
-        /* test */
-        assertThrows(TableNotFoundException.class, () -> {
-            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, 9999L, request);
-        });
-    }
-
     @Test
     public void execute_databaseNotExists_fails() throws InterruptedException {
         final ExecuteStatementDto request = ExecuteStatementDto.builder()
@@ -251,7 +236,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
 
         /* test */
         assertThrows(DatabaseNotFoundException.class, () -> {
-            queryService.execute(CONTAINER_1_ID, 9999L, TABLE_1_ID, request);
+            queryService.execute(CONTAINER_1_ID, 9999L, request);
         });
     }
 
@@ -267,7 +252,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PersistenceException.class, () -> {
-            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         });
     }
 
@@ -282,7 +267,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
 
         /* test */
         assertThrows(PersistenceException.class, () -> {
-            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         });
     }
 
@@ -297,7 +282,7 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
 
         /* test */
         assertThrows(QueryMalformedException.class, () -> {
-            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, request);
+            queryService.execute(CONTAINER_1_ID, DATABASE_1_ID, request);
         });
     }
 
diff --git a/fda-query-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/fda-query-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6bcb362bcd7ed5d338c250782c68145597fce5df
--- /dev/null
+++ b/fda-query-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
@@ -0,0 +1,56 @@
+package at.tuwien.auth;
+
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    public AuthTokenFilter(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        String jwt = parseJwt(request);
+        log.debug("parsed jwt {}", jwt);
+        if (jwt != null) {
+            final UserDetails userDetails = authenticationServiceGateway.validate(jwt);
+            final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+                    userDetails, null, userDetails.getAuthorities());
+            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }
+        filterChain.doFilter(request, response);
+    }
+
+    /**
+     * Parses the token from the HTTP header of the request
+     *
+     * @param request The request.
+     * @return The token.
+     */
+    private String parseJwt(HttpServletRequest request) {
+        String headerAuth = request.getHeader("Authorization");
+        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
+            return headerAuth.substring(7, headerAuth.length());
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
index daa14ed009686194a3f0e6edea0aed2f8424830c..252235a1eb97fcee790d7cf270935f06924f007f 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
@@ -1,23 +1,21 @@
 package at.tuwien.config;
 
-import lombok.Getter;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.client.RestTemplate;
 import org.springframework.web.util.DefaultUriBuilderFactory;
 
-@Getter
 @Configuration
 public class GatewayConfig {
 
-    @Value("${fda.gateway.endpoint}")
-    private String gatewayEndpoint;
+    @Value("${fda.auth.endpoint}")
+    private String authEndpoint;
 
     @Bean
     public RestTemplate restTemplate() {
         final RestTemplate restTemplate =  new RestTemplate();
-        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(authEndpoint));
         return restTemplate;
     }
 
diff --git a/fda-query-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/fda-query-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..b26f8e2994bb2378aaa914d38daad30b567476a6
--- /dev/null
+++ b/fda-query-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
@@ -0,0 +1,84 @@
+package at.tuwien.config;
+
+import at.tuwien.auth.AuthTokenFilter;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.servlet.http.HttpServletResponse;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    @Autowired
+    public WebSecurityConfig(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Bean
+    public AuthTokenFilter authTokenFilter() {
+        return new AuthTokenFilter(authenticationServiceGateway);
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        /* enable CORS and disable CSRF */
+        http = http.cors().and().csrf().disable();
+        /* set session management to stateless */
+        http = http
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and();
+        /* set unauthorized requests exception handler */
+        http = http
+                .exceptionHandling()
+                .authenticationEntryPoint(
+                        (request, response, ex) -> {
+                            response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+                                    ex.getMessage()
+                            );
+                        }
+                ).and();
+        /* set permissions on endpoints */
+        http.authorizeRequests()
+                /* our public endpoints */
+                .antMatchers(HttpMethod.GET, "/api/container/**/database/data/**").permitAll()
+                .antMatchers(HttpMethod.GET, "/api/container/**/database/query/**").permitAll()
+                .antMatchers(HttpMethod.GET, "/api/container/**/database/**/query/**").permitAll()
+                .antMatchers(HttpMethod.GET, "/api/container/**/database/**/version/**").permitAll()
+                /* our private endpoints */
+                .anyRequest().authenticated();
+        /* add JWT token filter */
+        http.addFilterBefore(authTokenFilter(),
+                UsernamePasswordAuthenticationFilter.class
+        );
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        final CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        config.addAllowedOrigin("*");
+        config.addAllowedHeader("*");
+        config.addAllowedMethod("*");
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+
+}
diff --git a/fda-query-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java b/fda-query-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc47ce246da851244cf1630b15f493ded20249d8
--- /dev/null
+++ b/fda-query-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
@@ -0,0 +1,14 @@
+package at.tuwien.gateway;
+
+import org.springframework.security.core.userdetails.UserDetails;
+
+public interface AuthenticationServiceGateway {
+
+    /**
+     * Validates a token
+     *
+     * @param token The token
+     * @return User details on success
+     */
+    UserDetails validate(String token);
+}
diff --git a/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java b/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..30507c4b6e662a7e772e85c609fdb5fbc563a99f
--- /dev/null
+++ b/fda-query-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
@@ -0,0 +1,36 @@
+package at.tuwien.gateway.impl;
+
+import at.tuwien.api.user.UserDto;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import at.tuwien.mapper.UserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
+
+    private final UserMapper userMapper;
+    private final RestTemplate restTemplate;
+
+    @Autowired
+    public AuthenticationServiceGatewayImpl(UserMapper userMapper, RestTemplate restTemplate) {
+        this.userMapper = userMapper;
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public UserDetails validate(String token) {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.set("Authorization", "Bearer " + token);
+        final ResponseEntity<UserDto> response = restTemplate.exchange("/api/auth", HttpMethod.PUT,
+                new HttpEntity<>("", headers), UserDto.class);
+        return userMapper.userDtoToUserDetailsDto(response.getBody());
+    }
+
+}
diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
index 7b512825f2aaa4e5030bbd2af3ce81bb0c0d45ce..112effd8ba11e1ba7619b354d86c1fda86d60705 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/QueryMapper.java
@@ -53,7 +53,7 @@ public interface QueryMapper {
         return slug.toLowerCase(Locale.ENGLISH);
     }
 
-    default QueryResultDto resultListToQueryResultDto(Table table, List<?> result, ExecuteStatementDto metadata) {
+    default QueryResultDto resultListToQueryResultDto(List<TableColumn> columns, List<?> result) {
         final Iterator<?> iterator = result.iterator();
         final List<Map<String, Object>> resultList = new LinkedList<>();
         while (iterator.hasNext()) {
@@ -61,17 +61,11 @@ public interface QueryMapper {
             int[] idx = new int[]{0};
             final Object[] data = (Object[]) iterator.next();
             final Map<String, Object> map = new HashMap<>();
-            final List<TableColumn> cols = table.getColumns() /* todo extend for more than 1 table */;
-            metadata.getColumns()
-                    .forEach(columns -> columns.forEach(column -> map.put(column.getName(),
-                            dataColumnToObject(data[idx[0]++], cols.stream().filter(c -> c.getId()
-                                            .equals(column.getId()))
-                                    .findFirst()
-                                    .get()))));
+                    columns
+                    .forEach(column -> map.put(column.getName(),
+                            dataColumnToObject(data[idx[0]++], column)));
             resultList.add(map);
         }
-        log.info("Display data for table id {}", table.getId());
-        log.trace("table {} contains {} records", table, resultList.size());
         return QueryResultDto.builder()
                 .result(resultList)
                 .build();
@@ -223,7 +217,6 @@ public interface QueryMapper {
         log.trace("table {} contains {} records", table, queryResult.size());
         return QueryResultDto.builder()
                 .result(queryResult)
-                .count(BigInteger.valueOf(queryResult.size()))
                 .build();
     }
 
diff --git a/fda-query-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-query-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f14430e9675c7a152c778df18fc892e3423afdc6
--- /dev/null
+++ b/fda-query-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
@@ -0,0 +1,18 @@
+package at.tuwien.mapper;
+
+import at.tuwien.api.user.GrantedAuthorityDto;
+import at.tuwien.api.user.UserDetailsDto;
+import at.tuwien.api.user.UserDto;
+import org.mapstruct.Mapper;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+@Mapper(componentModel = "spring")
+public interface UserMapper {
+
+    UserDetailsDto userDtoToUserDetailsDto(UserDto data);
+
+    default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) {
+        return new SimpleGrantedAuthority(data.getAuthority());
+    }
+}
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/CommaValueService.java b/fda-query-service/services/src/main/java/at/tuwien/service/CommaValueService.java
index 94a766e5fa3f1db933e396c9e858bfae63c15806..c06664088e68b162926d3d24baff765efb39e894 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/CommaValueService.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/CommaValueService.java
@@ -2,12 +2,7 @@ package at.tuwien.service;
 
 import at.tuwien.api.database.table.TableCsvDto;
 import at.tuwien.exception.*;
-import com.opencsv.exceptions.CsvException;
 import org.springframework.core.io.InputStreamResource;
-import org.springframework.core.io.Resource;
-
-import java.io.IOException;
-import java.time.Instant;
 
 public interface CommaValueService {
 
@@ -46,41 +41,41 @@ public interface CommaValueService {
     TableCsvDto read(Long containerId, Long databaseId, Long tableId, String location, Character separator, Long skipLines, String nullElement,
                      String falseElement, String trueElement) throws TableNotFoundException, DatabaseNotFoundException, FileStorageException, ContainerNotFoundException;
 
-    /**
-     * Exports a table to a file by given database and table id for a specific point in time.
-     *
-     * @param containerId The container id.
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
-     * @param timestamp   The point in time.
-     * @return The export.
-     * @throws TableNotFoundException      The table was not found.
-     * @throws DatabaseConnectionException The connection to the database failed.
-     * @throws DatabaseNotFoundException   The database was not found.
-     * @throws ImageNotSupportedException  The image is not supported. Currently only MariaDB is supported.
-     * @throws PaginationException         The pagination failed.
-     * @throws FileStorageException        The table could not be exported.
-     * @throws TableMalformedException     The table is malformed.
-     */
-    InputStreamResource export(Long containerId, Long databaseId, Long tableId, Instant timestamp) throws TableNotFoundException,
-            DatabaseConnectionException, DatabaseNotFoundException, ImageNotSupportedException,
-            PaginationException, FileStorageException, TableMalformedException, ContainerNotFoundException;
+//    /**
+//     * Exports a table to a file by given database and table id for a specific point in time.
+//     *
+//     * @param containerId The container id.
+//     * @param databaseId  The database id.
+//     * @param tableId     The table id.
+//     * @param timestamp   The point in time.
+//     * @return The export.
+//     * @throws TableNotFoundException      The table was not found.
+//     * @throws DatabaseConnectionException The connection to the database failed.
+//     * @throws DatabaseNotFoundException   The database was not found.
+//     * @throws ImageNotSupportedException  The image is not supported. Currently only MariaDB is supported.
+//     * @throws PaginationException         The pagination failed.
+//     * @throws FileStorageException        The table could not be exported.
+//     * @throws TableMalformedException     The table is malformed.
+//     */
+//    InputStreamResource export(Long containerId, Long databaseId, Long tableId, Instant timestamp) throws TableNotFoundException,
+//            DatabaseConnectionException, DatabaseNotFoundException, ImageNotSupportedException,
+//            PaginationException, FileStorageException, TableMalformedException, ContainerNotFoundException;
 
-    /**
-     * Exports a table to a file by given database and table id for a specific point in time.
-     *
-     * @param containerId The container id.
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
-     * @return The export.
-     * @throws TableNotFoundException      The table was not found.
-     * @throws DatabaseConnectionException The connection to the database failed.
-     * @throws DatabaseNotFoundException   The database was not found.
-     * @throws ImageNotSupportedException  The image is not supported. Currently only MariaDB is supported.
-     * @throws PaginationException         The pagination failed.
-     * @throws FileStorageException        The table could not be exported.
-     * @throws TableMalformedException     The table is malformed.
-     */
-    InputStreamResource export(Long containerId, Long databaseId, Long tableId) throws TableNotFoundException, DatabaseConnectionException,
-            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, FileStorageException, ContainerNotFoundException;
+//    /**
+//     * Exports a table to a file by given database and table id for a specific point in time.
+//     *
+//     * @param containerId The container id.
+//     * @param databaseId  The database id.
+//     * @param tableId     The table id.
+//     * @return The export.
+//     * @throws TableNotFoundException      The table was not found.
+//     * @throws DatabaseConnectionException The connection to the database failed.
+//     * @throws DatabaseNotFoundException   The database was not found.
+//     * @throws ImageNotSupportedException  The image is not supported. Currently only MariaDB is supported.
+//     * @throws PaginationException         The pagination failed.
+//     * @throws FileStorageException        The table could not be exported.
+//     * @throws TableMalformedException     The table is malformed.
+//     */
+//    InputStreamResource export(Long containerId, Long databaseId, Long tableId) throws TableNotFoundException, DatabaseConnectionException,
+//            TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, PaginationException, FileStorageException, ContainerNotFoundException;
 }
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
index 2c75e1d2fa904cb6845dce490fa2e7974c23d3a8..b5e14e0bb25204a178d3a7db9599bafe59cf865d 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/QueryService.java
@@ -5,8 +5,8 @@ import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.TableCsvDto;
 import at.tuwien.exception.*;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigInteger;
 import java.time.Instant;
 
 @Service
@@ -17,7 +17,6 @@ public interface QueryService {
      * default "mariadb" user is allowed read-only access "SELECT".
      *
      * @param databaseId The database id.
-     * @param tableId    The table id.
      * @param query      The query.
      * @return The result.
      * @throws TableNotFoundException
@@ -26,7 +25,7 @@ public interface QueryService {
      * @throws DatabaseNotFoundException
      * @throws ImageNotSupportedException
      */
-    QueryResultDto execute(Long containerId, Long databaseId, Long tableId, ExecuteStatementDto query) throws TableNotFoundException,
+    QueryResultDto execute(Long containerId, Long databaseId, ExecuteStatementDto query) throws TableNotFoundException,
             QueryStoreException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException;
 
     /**
@@ -57,7 +56,7 @@ public interface QueryService {
      *
      * @param containerId The container-database id tuple.
      * @param databaseId  The container-database id tuple.
-     * @param tableId     The table id.
+     * @param tableId     The container-database id tuple.
      * @param timestamp   The time.
      * @return The number of records, if successful
      * @throws ContainerNotFoundException The container was not found in the metadata database.
@@ -66,7 +65,7 @@ public interface QueryService {
      * @throws TableMalformedException    The table columns are messed up what we got from the metadata database.
      * @throws ImageNotSupportedException The image is not supported.
      */
-    QueryResultDto count(Long containerId, Long databaseId, Long tableId, Instant timestamp)
+    BigInteger count(Long containerId, Long databaseId, Long tableId, Instant timestamp)
             throws ContainerNotFoundException, DatabaseNotFoundException, TableNotFoundException,
             TableMalformedException, ImageNotSupportedException;
 
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/CommaValueServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/CommaValueServiceImpl.java
index b11e9c386e94eccc117d0864453e1a39e4cfad5b..aa225abfaa83ae51897d6f1f631375539decbd4c 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/CommaValueServiceImpl.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/CommaValueServiceImpl.java
@@ -1,6 +1,5 @@
 package at.tuwien.service.impl;
 
-import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.TableCsvDto;
 import at.tuwien.entities.container.Container;
 import at.tuwien.entities.database.table.Table;
@@ -8,7 +7,6 @@ import at.tuwien.exception.*;
 import at.tuwien.mapper.DataMapper;
 import at.tuwien.service.CommaValueService;
 import at.tuwien.service.ContainerService;
-import at.tuwien.service.QueryService;
 import at.tuwien.service.TableService;
 import at.tuwien.utils.FileUtils;
 import at.tuwien.utils.TableUtils;
@@ -20,8 +18,6 @@ import com.opencsv.exceptions.CsvException;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.InputStreamResource;
-import org.springframework.core.io.Resource;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -31,7 +27,6 @@ import java.io.*;
 import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Paths;
-import java.time.Instant;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -41,15 +36,12 @@ import java.util.stream.Stream;
 public class CommaValueServiceImpl implements CommaValueService {
 
     private final DataMapper dataMapper;
-    private final QueryService queryService;
     private final TableService tableService;
     private final ContainerService containerService;
 
     @Autowired
-    public CommaValueServiceImpl(DataMapper dataMapper, QueryService queryService, TableService tableService,
-                                 ContainerService containerService) {
+    public CommaValueServiceImpl(DataMapper dataMapper, TableService tableService, ContainerService containerService) {
         this.dataMapper = dataMapper;
-        this.queryService = queryService;
         this.tableService = tableService;
         this.containerService = containerService;
     }
@@ -180,35 +172,35 @@ public class CommaValueServiceImpl implements CommaValueService {
                 .build();
     }
 
-    @Override
-    @Transactional
-    public InputStreamResource export(Long containerId, Long databaseId, Long tableId, Instant timestamp)
-            throws TableNotFoundException, DatabaseNotFoundException, DatabaseConnectionException,
-            TableMalformedException, ImageNotSupportedException, PaginationException, FileStorageException,
-            ContainerNotFoundException {
-        /* find */
-        final Container container = containerService.find(containerId);
-        final Table table = tableService.find(databaseId, tableId);
-        final QueryResultDto result = queryService.findAll(containerId, databaseId, tableId, timestamp, null, null);
-        /* write */
-        final Resource csv = dataMapper.resultTableToResource(result, table);
-        final InputStreamResource resource;
-        try {
-            resource = new InputStreamResource(csv.getInputStream());
-        } catch (IOException e) {
-            log.error("Failed to map resource");
-            throw new FileStorageException("Failed to map resource", e);
-        }
-        log.trace("produced csv {}", csv);
-        return resource;
-    }
+//    @Override
+//    @Transactional
+//    public InputStreamResource export(Long containerId, Long databaseId, Long tableId, Instant timestamp)
+//            throws TableNotFoundException, DatabaseNotFoundException, DatabaseConnectionException,
+//            TableMalformedException, ImageNotSupportedException, PaginationException, FileStorageException,
+//            ContainerNotFoundException {
+//        /* find */
+//        final Container container = containerService.find(containerId);
+//        final Table table = tableService.find(databaseId, tableId);
+//        final QueryResultDto result = queryService.findAll(containerId, databaseId, tableId, timestamp, null, null);
+//        /* write */
+//        final Resource csv = dataMapper.resultTableToResource(result, table);
+//        final InputStreamResource resource;
+//        try {
+//            resource = new InputStreamResource(csv.getInputStream());
+//        } catch (IOException e) {
+//            log.error("Failed to map resource");
+//            throw new FileStorageException("Failed to map resource", e);
+//        }
+//        log.trace("produced csv {}", csv);
+//        return resource;
+//    }
 
-    @Override
-    @Transactional
-    public InputStreamResource export(Long containerId, Long databaseId, Long tableId) throws TableNotFoundException,
-            DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
-            FileStorageException, PaginationException, ContainerNotFoundException {
-        return export(containerId, databaseId, tableId, Instant.now());
-    }
+//    @Override
+//    @Transactional
+//    public InputStreamResource export(Long containerId, Long databaseId, Long tableId) throws TableNotFoundException,
+//            DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
+//            FileStorageException, PaginationException, ContainerNotFoundException {
+//        return export(containerId, databaseId, tableId, Instant.now());
+//    }
 
 }
diff --git a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
index bfcd0750b4172ddc465ca251c43ee9039cf82c3b..958b92858b145ad248d02b83838b02611fda1725 100644
--- a/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
+++ b/fda-query-service/services/src/main/java/at/tuwien/service/impl/QueryServiceImpl.java
@@ -4,11 +4,12 @@ import at.tuwien.InsertTableRawQuery;
 import at.tuwien.api.database.query.ExecuteStatementDto;
 import at.tuwien.api.database.query.QueryResultDto;
 import at.tuwien.api.database.table.TableCsvDto;
-import at.tuwien.entities.container.Container;
 import at.tuwien.entities.database.Database;
 import at.tuwien.entities.database.table.Table;
+import at.tuwien.entities.database.table.columns.TableColumn;
 import at.tuwien.exception.*;
 import at.tuwien.mapper.QueryMapper;
+import at.tuwien.repository.jpa.TableColumnRepository;
 import at.tuwien.service.*;
 import lombok.extern.log4j.Log4j2;
 import org.hibernate.Session;
@@ -23,6 +24,9 @@ import javax.persistence.PersistenceException;
 import java.math.BigInteger;
 import java.time.DateTimeException;
 import java.time.Instant;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
 
 @Log4j2
 @Service
@@ -32,32 +36,30 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
     private final StoreService storeService;
     private final TableService tableService;
     private final DatabaseService databaseService;
-    private final ContainerService containerService;
+    private final TableColumnRepository tableColumnRepository;
 
     @Autowired
     public QueryServiceImpl(QueryMapper queryMapper, StoreService storeService, TableService tableService,
-                            DatabaseService databaseService, ContainerService containerService) {
+                            DatabaseService databaseService, TableColumnRepository tableColumnRepository) {
         this.queryMapper = queryMapper;
         this.storeService = storeService;
         this.tableService = tableService;
         this.databaseService = databaseService;
-        this.containerService = containerService;
+        this.tableColumnRepository = tableColumnRepository;
     }
 
     @Override
     @Transactional
-    public QueryResultDto execute(Long containerId, Long databaseId, Long tableId, ExecuteStatementDto statement)
-            throws DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException,
-            TableNotFoundException, ContainerNotFoundException {
+    public QueryResultDto execute(Long containerId, Long databaseId, ExecuteStatementDto statement)
+            throws DatabaseNotFoundException, ImageNotSupportedException, QueryMalformedException {
         /* find */
-        final Container container = containerService.find(containerId);
-        final Table table = tableService.find(databaseId, tableId);
-        if (!table.getDatabase().getContainer().getImage().getRepository().equals("mariadb")) {
+        final Database database = databaseService.find(databaseId);
+        if (!database.getContainer().getImage().getRepository().equals("mariadb")) {
             throw new ImageNotSupportedException("Currently only MariaDB is supported");
         }
         /* run query */
         final long startSession = System.currentTimeMillis();
-        final SessionFactory factory = getSessionFactory(table.getDatabase());
+        final SessionFactory factory = getSessionFactory(database);
         final Session session = factory.openSession();
         log.debug("opened hibernate session in {} ms", System.currentTimeMillis() - startSession);
         session.beginTransaction();
@@ -67,7 +69,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
         try {
             log.debug("execute raw view-only query {}", statement);
             affectedTuples = query.executeUpdate();
-            log.info("Execution on table id {} affected {} rows", tableId, affectedTuples);
+            log.info("Execution on database id {} affected {} rows", databaseId, affectedTuples);
             session.getTransaction()
                     .commit();
         } catch (SQLGrammarException e) {
@@ -75,7 +77,9 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
             factory.close();
             throw new QueryMalformedException("Query not valid for this database", e);
         }
-        final QueryResultDto result = queryMapper.resultListToQueryResultDto(table, query.getResultList(), statement);
+        /* map the result to the tables (with respective columns) from the statement metadata */
+        final List<TableColumn> columns = parseColumns(statement);
+        final QueryResultDto result = queryMapper.resultListToQueryResultDto(columns, query.getResultList());
         session.close();
         factory.close();
         log.debug("query id {}", result.getId());
@@ -90,12 +94,11 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
             ImageNotSupportedException, DatabaseConnectionException, TableMalformedException, PaginationException,
             ContainerNotFoundException {
         /* find */
-        final Container container = containerService.find(containerId);
         final Database database = databaseService.find(databaseId);
         final Table table = tableService.find(databaseId, tableId);
         /* run query */
         final long startSession = System.currentTimeMillis();
-        final SessionFactory factory = getSessionFactory(table.getDatabase(), true);
+        final SessionFactory factory = getSessionFactory(database, true);
         final Session session = factory.openSession();
         log.debug("opened hibernate session in {} ms", System.currentTimeMillis() - startSession);
         session.beginTransaction();
@@ -104,7 +107,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
         final int affectedTuples;
         try {
             affectedTuples = query.executeUpdate();
-            log.info("Found {} tuples in table id {}", affectedTuples, tableId);
+            log.info("Found {} tuples in database id {}", affectedTuples, databaseId);
         } catch (PersistenceException e) {
             log.error("Failed to find data");
             session.close();
@@ -127,16 +130,15 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
 
     @Override
     @Transactional
-    public QueryResultDto count(Long containerId, Long databaseId, Long tableId, Instant timestamp)
-            throws ContainerNotFoundException, DatabaseNotFoundException, TableNotFoundException,
+    public BigInteger count(Long containerId, Long databaseId, Long tableId, Instant timestamp)
+            throws DatabaseNotFoundException, TableNotFoundException,
             TableMalformedException, ImageNotSupportedException {
         /* find */
-        final Container container = containerService.find(containerId);
         final Database database = databaseService.find(databaseId);
         final Table table = tableService.find(databaseId, tableId);
         /* run query */
         final long startSession = System.currentTimeMillis();
-        final SessionFactory factory = getSessionFactory(table.getDatabase(), false);
+        final SessionFactory factory = getSessionFactory(database, false);
         final Session session = factory.openSession();
         log.debug("opened hibernate session in {} ms", System.currentTimeMillis() - startSession);
         session.beginTransaction();
@@ -153,12 +155,10 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
         }
         session.getTransaction()
                 .commit();
-        final QueryResultDto result = QueryResultDto.builder()
-                .count(query.getSingleResult())
-                .build();
+        final BigInteger count = query.getSingleResult();
         session.close();
         factory.close();
-        return result;
+        return count;
     }
 
     @Override
@@ -167,13 +167,12 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
             throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException,
             TableNotFoundException, ContainerNotFoundException {
         /* find */
-        final Container container = containerService.find(containerId);
         final Database database = databaseService.find(databaseId);
         final Table table = tableService.find(databaseId, tableId);
         /* run query */
         if (data.getData().size() == 0) return null;
         final long startSession = System.currentTimeMillis();
-        final SessionFactory factory = getSessionFactory(table.getDatabase(), true);
+        final SessionFactory factory = getSessionFactory(database, true);
         final Session session = factory.openSession();
         log.debug("opened hibernate session in {} ms", System.currentTimeMillis() - startSession);
         session.beginTransaction();
@@ -181,7 +180,7 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
         final InsertTableRawQuery raw = queryMapper.tableCsvDtoToRawInsertQuery(table, data);
         final NativeQuery<?> query = session.createSQLQuery(raw.getQuery());
         log.trace("query with parameters {}", query.setParameterList(1, raw.getData()));
-        final Integer affected = insert(query, session, factory, tableId);
+        final Integer affected = insert(query, session, factory);
         storeService.createVersion(containerId, databaseId);
         return affected;
     }
@@ -192,19 +191,18 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
             throws ImageNotSupportedException, TableMalformedException, DatabaseNotFoundException,
             TableNotFoundException, ContainerNotFoundException {
         /* find */
-        final Container container = containerService.find(containerId);
         final Database database = databaseService.find(databaseId);
         final Table table = tableService.find(databaseId, tableId);
         /* run query */
         final long startSession = System.currentTimeMillis();
-        final SessionFactory factory = getSessionFactory(table.getDatabase(), true);
+        final SessionFactory factory = getSessionFactory(database, true);
         final Session session = factory.openSession();
         log.debug("opened hibernate session in {} ms", System.currentTimeMillis() - startSession);
         session.beginTransaction();
         /* prepare the statement */
         final InsertTableRawQuery raw = queryMapper.pathToRawInsertQuery(table, path);
         final NativeQuery<?> query = session.createSQLQuery(raw.getQuery());
-        final Integer affected = insert(query, session, factory, tableId);
+        final Integer affected = insert(query, session, factory);
         storeService.createVersion(containerId, databaseId);
         return affected;
     }
@@ -215,15 +213,13 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
      * @param query   The query.
      * @param session The active Hibernate session.
      * @param factory The active Hibernate session factory.
-     * @param tableId The table id.
      * @return The affected rows, if successful.
      * @throws TableMalformedException The table metadata is wrong.
      */
-    private Integer insert(NativeQuery<?> query, Session session, SessionFactory factory, Long tableId) throws TableMalformedException {
+    private Integer insert(NativeQuery<?> query, Session session, SessionFactory factory) throws TableMalformedException {
         final int affectedTuples;
         try {
             affectedTuples = query.executeUpdate();
-            log.info("Inserted {} tuples on table id {}", affectedTuples, tableId);
         } catch (PersistenceException e) {
             log.error("Could not insert data");
             session.close();
@@ -237,4 +233,19 @@ public class QueryServiceImpl extends HibernateConnector implements QueryService
         return affectedTuples;
     }
 
+    /**
+     * Retrieves the columns from the tables (ids) and referenced column ids from the metadata database
+     *
+     * @param statement The list of tables (ids) and referenced column ids.
+     * @return The list of columns if successful
+     */
+    private List<TableColumn> parseColumns(ExecuteStatementDto statement) {
+        return statement.getColumns()
+                .stream()
+                .map(c -> tableColumnRepository.findById(c.getId()))
+                .filter(Optional::isPresent)
+                .map(Optional::get)
+                .collect(Collectors.toList());
+    }
+
 }
diff --git a/fda-table-service/pom.xml b/fda-table-service/pom.xml
index bac6894b3c2fe019881eda35b4bb75a486614912..c438df0222d945aae4bd61ded57b955ce033aecf 100644
--- a/fda-table-service/pom.xml
+++ b/fda-table-service/pom.xml
@@ -56,6 +56,15 @@
             <artifactId>spring-cloud-starter-bootstrap</artifactId>
             <version>${spring-cloud.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
         <!-- Entities and API -->
         <dependency>
             <groupId>at.tuwien</groupId>
diff --git a/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
index 7c4870663a2de27e2378d50bae620e3a40efdadc..78f9cb54d6d5526f6a392f1a7a5a52ef1808d836 100644
--- a/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
+++ b/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
@@ -15,6 +15,7 @@ import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
@@ -40,7 +41,6 @@ public class TableEndpoint {
         this.tableMapper = tableMapper;
     }
 
-    @Transactional
     @GetMapping
     @ApiOperation(value = "List all tables", notes = "Lists the tables in the metadata database for this database.")
     @ApiResponses({
@@ -56,8 +56,8 @@ public class TableEndpoint {
                 .collect(Collectors.toList()));
     }
 
-    @Transactional
     @PostMapping
+    @PreAuthorize("hasRole('ROLE_RESEARCHER')")
     @ApiOperation(value = "Create a table", notes = "Creates a new table for a database, requires a running container.")
     @ApiResponses({
             @ApiResponse(code = 201, message = "The table was created."),
@@ -80,7 +80,6 @@ public class TableEndpoint {
     }
 
 
-    @Transactional
     @GetMapping("/{tableId}")
     @ApiOperation(value = "Get information about table", notes = "Lists the information of a table from the metadata database for this database.")
     @ApiResponses({
@@ -112,6 +111,7 @@ public class TableEndpoint {
     }
 
     @DeleteMapping("/{tableId}")
+    @PreAuthorize("hasRole('ROLE_DEVELOPER') or hasRole('ROLE_DATA_STEWARD')")
     @ApiOperation(value = "Delete a table", notes = "Delete a table in the database.")
     @ApiResponses({
             @ApiResponse(code = 200, message = "Deleted the table."),
diff --git a/fda-table-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/fda-table-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..6bcb362bcd7ed5d338c250782c68145597fce5df
--- /dev/null
+++ b/fda-table-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
@@ -0,0 +1,56 @@
+package at.tuwien.auth;
+
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.util.StringUtils;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    public AuthTokenFilter(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        String jwt = parseJwt(request);
+        log.debug("parsed jwt {}", jwt);
+        if (jwt != null) {
+            final UserDetails userDetails = authenticationServiceGateway.validate(jwt);
+            final UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
+                    userDetails, null, userDetails.getAuthorities());
+            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+
+            SecurityContextHolder.getContext().setAuthentication(authentication);
+        }
+        filterChain.doFilter(request, response);
+    }
+
+    /**
+     * Parses the token from the HTTP header of the request
+     *
+     * @param request The request.
+     * @return The token.
+     */
+    private String parseJwt(HttpServletRequest request) {
+        String headerAuth = request.getHeader("Authorization");
+        if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
+            return headerAuth.substring(7, headerAuth.length());
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/fda-table-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/fda-table-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..252235a1eb97fcee790d7cf270935f06924f007f
--- /dev/null
+++ b/fda-table-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
@@ -0,0 +1,22 @@
+package at.tuwien.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+@Configuration
+public class GatewayConfig {
+
+    @Value("${fda.auth.endpoint}")
+    private String authEndpoint;
+
+    @Bean
+    public RestTemplate restTemplate() {
+        final RestTemplate restTemplate =  new RestTemplate();
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(authEndpoint));
+        return restTemplate;
+    }
+
+}
diff --git a/fda-table-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/fda-table-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..4fbc0cf4c291754bfefc6102ed0de24e244ea337
--- /dev/null
+++ b/fda-table-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
@@ -0,0 +1,81 @@
+package at.tuwien.config;
+
+import at.tuwien.auth.AuthTokenFilter;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+import javax.servlet.http.HttpServletResponse;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+    private final AuthenticationServiceGateway authenticationServiceGateway;
+
+    @Autowired
+    public WebSecurityConfig(AuthenticationServiceGateway authenticationServiceGateway) {
+        this.authenticationServiceGateway = authenticationServiceGateway;
+    }
+
+    @Bean
+    public AuthTokenFilter authTokenFilter() {
+        return new AuthTokenFilter(authenticationServiceGateway);
+    }
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+        /* enable CORS and disable CSRF */
+        http = http.cors().and().csrf().disable();
+        /* set session management to stateless */
+        http = http
+                .sessionManagement()
+                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+                .and();
+        /* set unauthorized requests exception handler */
+        http = http
+                .exceptionHandling()
+                .authenticationEntryPoint(
+                        (request, response, ex) -> {
+                            response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
+                                    ex.getMessage()
+                            );
+                        }
+                ).and();
+        /* set permissions on endpoints */
+        http.authorizeRequests()
+                /* our public endpoints */
+                .antMatchers(HttpMethod.GET, "/api/container/**/database/**/table/**").permitAll()
+                /* our private endpoints */
+                .anyRequest().authenticated();
+        /* add JWT token filter */
+        http.addFilterBefore(authTokenFilter(),
+                UsernamePasswordAuthenticationFilter.class
+        );
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        final CorsConfiguration config = new CorsConfiguration();
+        config.setAllowCredentials(true);
+        config.addAllowedOrigin("*");
+        config.addAllowedHeader("*");
+        config.addAllowedMethod("*");
+        source.registerCorsConfiguration("/**", config);
+        return new CorsFilter(source);
+    }
+
+}
diff --git a/fda-table-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java b/fda-table-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc47ce246da851244cf1630b15f493ded20249d8
--- /dev/null
+++ b/fda-table-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
@@ -0,0 +1,14 @@
+package at.tuwien.gateway;
+
+import org.springframework.security.core.userdetails.UserDetails;
+
+public interface AuthenticationServiceGateway {
+
+    /**
+     * Validates a token
+     *
+     * @param token The token
+     * @return User details on success
+     */
+    UserDetails validate(String token);
+}
diff --git a/fda-table-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java b/fda-table-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..30507c4b6e662a7e772e85c609fdb5fbc563a99f
--- /dev/null
+++ b/fda-table-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
@@ -0,0 +1,36 @@
+package at.tuwien.gateway.impl;
+
+import at.tuwien.api.user.UserDto;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import at.tuwien.mapper.UserMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+@Service
+public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
+
+    private final UserMapper userMapper;
+    private final RestTemplate restTemplate;
+
+    @Autowired
+    public AuthenticationServiceGatewayImpl(UserMapper userMapper, RestTemplate restTemplate) {
+        this.userMapper = userMapper;
+        this.restTemplate = restTemplate;
+    }
+
+    @Override
+    public UserDetails validate(String token) {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.set("Authorization", "Bearer " + token);
+        final ResponseEntity<UserDto> response = restTemplate.exchange("/api/auth", HttpMethod.PUT,
+                new HttpEntity<>("", headers), UserDto.class);
+        return userMapper.userDtoToUserDetailsDto(response.getBody());
+    }
+
+}
diff --git a/fda-table-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-table-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f14430e9675c7a152c778df18fc892e3423afdc6
--- /dev/null
+++ b/fda-table-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
@@ -0,0 +1,18 @@
+package at.tuwien.mapper;
+
+import at.tuwien.api.user.GrantedAuthorityDto;
+import at.tuwien.api.user.UserDetailsDto;
+import at.tuwien.api.user.UserDto;
+import org.mapstruct.Mapper;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+@Mapper(componentModel = "spring")
+public interface UserMapper {
+
+    UserDetailsDto userDtoToUserDetailsDto(UserDto data);
+
+    default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) {
+        return new SimpleGrantedAuthority(data.getAuthority());
+    }
+}