diff --git a/fda-authentication-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/fda-authentication-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
index e7684780cda97e9bd74f6869b5fcd248b6d009c3..017992fda0e7314069d5fff2e461e88cfcd0c321 100644
--- a/fda-authentication-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
+++ b/fda-authentication-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
@@ -1,6 +1,5 @@
 package at.tuwien.config;
 
-import at.tuwien.auth.AuthEntrypoint;
 import at.tuwien.auth.AuthTokenFilter;
 import at.tuwien.auth.JwtUtils;
 import at.tuwien.service.impl.UserDetailsServiceImpl;
diff --git a/fda-container-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java b/fda-container-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..2d1d0258855ba5fa3444a8008e0db5a53594445c
--- /dev/null
+++ b/fda-container-service/services/src/main/java/at/tuwien/auth/AuthTokenFilter.java
@@ -0,0 +1,52 @@
+package at.tuwien.auth;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+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.stereotype.Component;
+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
+@Component
+public class AuthTokenFilter extends OncePerRequestFilter {
+
+    @Override
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+            throws ServletException, IOException {
+        String jwt = parseJwt(request);
+        if (jwt != null) {
+
+            final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
+            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-container-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java b/fda-container-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
index 9832234740ead10f80163b75958b5363a7789cd5..5f0bd4772059fb3410c182bffc929ac069f988aa 100644
--- a/fda-container-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
+++ b/fda-container-service/services/src/main/java/at/tuwien/config/WebSecurityConfig.java
@@ -1,6 +1,6 @@
 package at.tuwien.config;
 
-import org.springframework.beans.factory.annotation.Value;
+import at.tuwien.auth.AuthTokenFilter;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.http.HttpMethod;
@@ -9,7 +9,6 @@ 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;
@@ -21,8 +20,10 @@ import javax.servlet.http.HttpServletResponse;
 @EnableGlobalMethodSecurity(prePostEnabled = true)
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 
-    @Value("${fda.auth.url}")
-    private String authUrl;
+    @Bean
+    public AuthTokenFilter authTokenFilter() {
+        return new AuthTokenFilter()
+    }
 
     @Override
     protected void configure(HttpSecurity http) throws Exception {
@@ -45,11 +46,11 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
                 ).and();
         /* set permissions on endpoints */
         http.authorizeRequests()
+                /* our public endpoints */
+                .antMatchers(HttpMethod.GET, "/api/container/**").permitAll()
+                .antMatchers(HttpMethod.GET, "/api/image/**").permitAll()
                 /* our private endpoints */
                 .anyRequest().authenticated();
-        /* set auth url */
-        http.formLogin()
-                .loginProcessingUrl(authUrl);
     }
 
     @Bean
diff --git a/fda-ui/components/dialogs/CreateDB.vue b/fda-ui/components/dialogs/CreateDB.vue
index 8f1dac773c8a193343670c2edca4b67b69c38782..1316c5fd642e920f302ed1b361c050897212b656 100644
--- a/fda-ui/components/dialogs/CreateDB.vue
+++ b/fda-ui/components/dialogs/CreateDB.vue
@@ -1,22 +1,22 @@
 <template>
   <div>
-    <v-card>
-      <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
-      <v-card-title>
-        Create Database
-      </v-card-title>
-      <v-card-text>
-        <v-alert
-          border="left"
-          color="amber lighten-4 black--text">
-          Choose an expressive database name and select a database engine.
-        </v-alert>
-        <v-form v-model="formValid" autocomplete="off">
+    <v-form ref="form" v-model="valid" @submit.prevent="submit">
+      <v-card>
+        <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
+        <v-card-title>
+          Create Database
+        </v-card-title>
+        <v-card-text>
+          <v-alert
+            border="left"
+            color="amber lighten-4 black--text">
+            Choose an expressive database name and select a database engine.
+          </v-alert>
           <v-text-field
             id="database"
             v-model="database"
             name="database"
-            label="Database Name"
+            label="Name *"
             :rules="[v => !!v || $t('Required')]"
             required />
           <v-textarea
@@ -24,14 +24,14 @@
             v-model="description"
             name="description"
             rows="2"
-            label="Database Description"
+            label="Description *"
             :rules="[v => !!v || $t('Required')]"
             required />
           <v-select
             id="engine"
             v-model="engine"
             name="engine"
-            label="Database Engine"
+            label="Engine *"
             :items="engines"
             :item-text="item => `${item.repository}:${item.tag}`"
             :rules="[v => !!v || $t('Required')]"
@@ -43,25 +43,26 @@
             name="public"
             disabled
             label="Public" />
-        </v-form>
-      </v-card-text>
-      <v-card-actions>
-        <v-spacer />
-        <v-btn
-          class="mb-2"
-          @click="cancel">
-          Cancel
-        </v-btn>
-        <v-btn
-          id="createDB"
-          class="mb-2"
-          :disabled="!formValid || loading"
-          color="primary"
-          @click="createDB">
-          Create
-        </v-btn>
-      </v-card-actions>
-    </v-card>
+        </v-card-text>
+        <v-card-actions>
+          <v-spacer />
+          <v-btn
+            class="mb-2"
+            @click="cancel">
+            Cancel
+          </v-btn>
+          <v-btn
+            id="createDB"
+            class="mb-2"
+            :disabled="!valid || loading"
+            color="primary"
+            type="submit"
+            @click="createDB">
+            Create
+          </v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-form>
   </div>
 </template>
 
@@ -69,7 +70,7 @@
 export default {
   data () {
     return {
-      formValid: false,
+      valid: false,
       loading: false,
       error: false,
       database: null,
@@ -83,12 +84,18 @@ export default {
   computed: {
     loadingColor () {
       return this.error ? 'red lighten-2' : 'primary'
+    },
+    token () {
+      return this.$store.state.token
     }
   },
   beforeMount () {
     this.getImages()
   },
   methods: {
+    submit () {
+      this.$refs.form.validate()
+    },
     cancel () {
       this.$parent.$parent.$parent.$parent.createDbDialog = false
     },
@@ -97,7 +104,9 @@ export default {
       try {
         this.loading = true
         this.error = false
-        res = await this.$axios.get('/api/image/')
+        res = await this.$axios.get('/api/image/', {
+          headers: { Authorization: `Bearer ${this.token}` }
+        })
         this.engines = res.data
         console.debug('engines', this.engines)
         this.loading = false
@@ -125,13 +134,22 @@ export default {
           description: this.description,
           repository: this.engine.repository,
           tag: this.engine.tag
+        }, {
+          headers: { Authorization: `Bearer ${this.token}` }
         })
         containerId = res.data.id
         console.debug('created container', res.data)
         this.loading = false
       } catch (err) {
         this.error = true
-        this.$toast.error('Could not create container. Try another name.')
+        this.loading = false
+        if (err.status === 401) {
+          this.$toast.error('Authentication missing')
+          console.error('permission denied', err)
+          return
+        }
+        console.error('failed to create container', err)
+        this.$toast.error('Could not create container.')
         return
       }
 
@@ -139,8 +157,8 @@ export default {
       try {
         this.loading = true
         this.error = false
-        res = await this.$axios.put(`/api/container/${containerId}`, {
-          action: 'START'
+        res = await this.$axios.put(`/api/container/${containerId}`, { action: 'START' }, {
+          headers: { Authorization: `Bearer ${this.token}` }
         })
         console.debug('started container', res.data)
       } catch (err) {
@@ -162,6 +180,8 @@ export default {
             name: this.database,
             description: this.description,
             is_public: this.isPublic
+          }, {
+            headers: { Authorization: `Bearer ${this.token}` }
           })
           console.debug('created database', res)
           break
diff --git a/fda-ui/layouts/default.vue b/fda-ui/layouts/default.vue
index b92bb74530348900293fd5d50f3b62173d23d44e..158dbcb0985784d4a40295a1c3e89307054f17fb 100644
--- a/fda-ui/layouts/default.vue
+++ b/fda-ui/layouts/default.vue
@@ -29,11 +29,19 @@
       <v-toolbar-title v-text="title" />
       <v-spacer />
       <v-btn
+        v-if="!token"
         class="mr-2 white--text"
         color="blue-grey"
         to="/login">
         <v-icon left>mdi-login</v-icon> Login
       </v-btn>
+      <v-btn
+        v-if="!token"
+        class="mr-2 white--text"
+        color="primary"
+        to="/signup">
+        <v-icon left>mdi-account-plus</v-icon> Signup
+      </v-btn>
       <v-menu bottom offset-y left>
         <template v-slot:activator="{ on, attrs }">
           <v-btn
@@ -44,22 +52,16 @@
           </v-btn>
         </template>
         <v-list>
-          <v-list-item to="/signup">
-            <v-list-item-icon>
-              <v-icon left>mdi-account-plus</v-icon>
-            </v-list-item-icon>
-            <v-list-item-title>Create Account</v-list-item-title>
+          <v-list-item
+            v-for="locale in availableLocales"
+            :key="locale.code"
+            :to="switchLocalePath(locale.code)">
+            <v-list-item-title>{{ locale.name }}</v-list-item-title>
+          </v-list-item>
+          <v-list-item
+            @click="switchTheme()">
+            {{ nextTheme }} Theme
           </v-list-item>
-          <!--          <v-list-item-->
-          <!--            v-for="locale in availableLocales"-->
-          <!--            :key="locale.code"-->
-          <!--            :to="switchLocalePath(locale.code)">-->
-          <!--            <v-list-item-title>{{ locale.name }}</v-list-item-title>-->
-          <!--          </v-list-item>-->
-          <!--          <v-list-item-->
-          <!--            @click="switchTheme()">-->
-          <!--            {{ nextTheme }} Theme-->
-          <!--          </v-list-item>-->
         </v-list>
       </v-menu>
     </v-app-bar>
@@ -68,14 +70,14 @@
         <nuxt />
       </v-container>
     </v-main>
-    <v-footer v-if="sandbox" padless>
+    <v-footer padless>
       <v-card
         flat
         tile
         width="100%"
-        class="primary text-center">
-        <v-card-text class="white--text">
-          <strong>Sandbox Environment</strong> — <a href="//github.com/fair-data-austria/dbrepo/issues/new" class="white--text">Report a bug</a>
+        class="red lighten-1 text-center">
+        <v-card-text class="black--text">
+          This is a <strong>TEST</strong> environment, do not use production/confidential data! — <a href="//github.com/fair-data-austria/dbrepo/issues/new" class="black--text">Report a bug</a>
         </v-card-text>
       </v-card>
     </v-footer>
@@ -145,8 +147,8 @@ export default {
     availableLocales () {
       return this.$i18n.locales.filter(i => i.code !== this.$i18n.locale)
     },
-    sandbox () {
-      return true
+    token () {
+      return this.$store.state.token
     },
     nextTheme () {
       return this.$vuetify.theme.dark ? 'Light' : 'Dark'
diff --git a/fda-ui/pages/container/index.vue b/fda-ui/pages/container/index.vue
index fe106920f7622f9946aa3eef48a61c2ab23680fb..ed25283940084a74547f640858b6490992b69289 100644
--- a/fda-ui/pages/container/index.vue
+++ b/fda-ui/pages/container/index.vue
@@ -7,7 +7,7 @@
       </v-toolbar-title>
       <v-spacer />
       <v-toolbar-title>
-        <v-btn color="primary" @click.stop="createDbDialog = true">
+        <v-btn v-if="token" color="primary" @click.stop="createDbDialog = true">
           <v-icon left>mdi-plus</v-icon> Database
         </v-btn>
       </v-toolbar-title>
@@ -89,9 +89,7 @@ export default {
       this.createDbDialog = false
       try {
         this.loading = true
-        let res = await this.$axios.get('/api/container/', {
-          headers: { Authorization: `Bearer ${this.token}` }
-        })
+        let res = await this.$axios.get('/api/container/')
         this.containers = res.data
         console.debug('containers', this.containers)
         for (const container of this.containers) {
diff --git a/fda-ui/pages/login.vue b/fda-ui/pages/login.vue
index 2de5fb7c1404e7f8af7835e7ef40c7d58cd11014..f6a07b3f4d4d8bfb32f25efe4abef45501b128b2 100644
--- a/fda-ui/pages/login.vue
+++ b/fda-ui/pages/login.vue
@@ -1,45 +1,53 @@
 <template>
   <div>
-    <v-card>
-      <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
-      <v-card-title>
-        Login
-      </v-card-title>
-      <v-card-text>
-        <v-form ref="form" v-model="valid">
+    <v-form ref="form" v-model="valid" @submit.prevent="submit">
+      <v-card v-if="!token">
+        <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
+        <v-card-title>
+          Login
+        </v-card-title>
+        <v-card-text>
+          <v-alert
+            border="left"
+            color="amber lighten-4 black--text">
+            If you need an account, create one <a @click="signup">here</a>.
+          </v-alert>
           <v-row>
-            <v-col>
+            <v-col cols="6">
               <v-text-field
                 v-model="loginAccount.username"
                 autocomplete="off"
+                required
                 :rules="[v => !!v || $t('Required')]"
                 label="Username *" />
             </v-col>
           </v-row>
           <v-row>
-            <v-col>
+            <v-col cols="6">
               <v-text-field
                 v-model="loginAccount.password"
                 autocomplete="off"
                 type="password"
+                required
                 :rules="[v => !!v || $t('Required')]"
                 label="Password *" />
             </v-col>
           </v-row>
-        </v-form>
-      </v-card-text>
-      <v-card-actions>
-        <v-spacer />
-        <v-btn
-          id="login"
-          class="mb-2"
-          :disabled="!valid"
-          color="primary"
-          @click="login">
-          Login
-        </v-btn>
-      </v-card-actions>
-    </v-card>
+        </v-card-text>
+        <v-card-actions>
+          <v-btn
+            id="login"
+            class="mb-2 ml-2"
+            :disabled="!valid"
+            color="primary"
+            type="submit"
+            @click="login">
+            Login
+          </v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-form>
+    <p v-if="token">Already logged-in</p>
   </div>
 </template>
 
@@ -59,11 +67,17 @@ export default {
   computed: {
     loadingColor () {
       return this.error ? 'red lighten-2' : 'primary'
+    },
+    token () {
+      return this.$store.state.token
     }
   },
   beforeMount () {
   },
   methods: {
+    submit () {
+      this.$refs.form.validate()
+    },
     async login () {
       const url = '/api/auth'
       try {
@@ -72,11 +86,15 @@ export default {
         console.debug('login user', res.data)
         this.$store.commit('SET_TOKEN', res.data.token)
         this.$toast.success('Welcome back!')
+        this.$router.push('/container')
       } catch (err) {
         console.error('login user failed', err)
         this.$toast.error('Failed to login user')
       }
       this.loading = false
+    },
+    signup () {
+      this.$router.push('/signup')
     }
   }
 }
diff --git a/fda-ui/pages/signup.vue b/fda-ui/pages/signup.vue
index 8eecba91341c5f82bf1317ccedb699a00de6aa12..15b318ac8047f07e730ef285f159f250d55487d9 100644
--- a/fda-ui/pages/signup.vue
+++ b/fda-ui/pages/signup.vue
@@ -1,80 +1,87 @@
 <template>
   <div>
-    <v-card>
-      <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
-      <v-card-title>
-        Create Account
-      </v-card-title>
-      <v-card-text>
-        <v-alert
-          border="left"
-          color="amber lighten-4 black--text">
-          Before you can use the repository sandbox, you will need to <i>confirm</i> your email address, make sure to check your spam folder.
-        </v-alert>
-        <v-alert
-          border="left"
-          color="red lighten-1 black--text">
-          This is a <strong>TEST</strong> environment, do not use production/confidential data!
-        </v-alert>
-        <v-form ref="form" v-model="valid">
+    <v-form ref="form" v-model="valid" @submit.prevent="submit">
+      <v-card>
+        <v-progress-linear v-if="loading" :color="loadingColor" :indeterminate="!error" />
+        <v-card-title>
+          Create Account
+        </v-card-title>
+        <v-card-text>
+          <v-alert
+            border="left"
+            color="amber lighten-4 black--text">
+            Before you can use the repository sandbox, you will need to <i>confirm</i> your email address, make sure to check your spam folder.
+          </v-alert>
           <v-row>
-            <v-col>
+            <v-col cols="6">
               <v-text-field
                 v-model="createAccount.email"
                 type="email"
                 autocomplete="off"
+                required
                 :rules="[v => !!v || $t('Required')]"
                 hint="e.g. max.mustermann@work.com"
                 label="Work E-Mail Address *" />
             </v-col>
           </v-row>
           <v-row>
-            <v-col>
+            <v-col cols="6">
               <v-text-field
                 v-model="createAccount.username"
                 autocomplete="off"
+                required
                 :rules="[v => !!v || $t('Required')]"
                 hint="e.g. mmustermann"
                 label="Username *" />
             </v-col>
           </v-row>
           <v-row>
-            <v-col>
+            <v-col cols="6">
               <v-text-field
                 v-model="createAccount.password"
                 autocomplete="off"
+                required
                 :rules="[v => !!v || $t('Required')]"
                 type="password"
                 label="Password *" />
             </v-col>
           </v-row>
           <v-row>
-            <v-col>
+            <v-col cols="6">
               <v-checkbox
                 v-model="consent"
+                required
                 :rules="[v => !!v || $t('Required')]"
                 label="I understand the warning and do not use production data" />
             </v-col>
           </v-row>
-        </v-form>
-      </v-card-text>
-      <v-card-actions>
-        <v-spacer />
-        <v-btn
-          class="mb-2"
-          @click="cancel">
-          Cancel
-        </v-btn>
-        <v-btn
-          id="login"
-          class="mb-2"
-          :disabled="!valid"
-          color="primary"
-          @click="register">
-          Submit
-        </v-btn>
-      </v-card-actions>
-    </v-card>
+          <v-row>
+            <v-col cols="6">
+              <v-checkbox
+                v-model="privacy"
+                required
+                :rules="[v => !!v || $t('Required')]"
+                label="I have read and accept the privacy statement" />
+            </v-col>
+          </v-row>
+        </v-card-text>
+        <v-card-actions>
+          <v-btn
+            class="mb-2 ml-2">
+            Cancel
+          </v-btn>
+          <v-btn
+            id="login"
+            class="mb-2"
+            :disabled="!valid"
+            color="primary"
+            type="submit"
+            @click="register">
+            Submit
+          </v-btn>
+        </v-card-actions>
+      </v-card>
+    </v-form>
   </div>
 </template>
 
@@ -85,6 +92,7 @@ export default {
       loading: false,
       error: false,
       valid: false,
+      privacy: false,
       consent: false,
       createAccount: {
         username: null,
@@ -101,6 +109,9 @@ export default {
   beforeMount () {
   },
   methods: {
+    submit () {
+      this.$refs.form.validate()
+    },
     async register () {
       const url = '/api/user'
       try {
@@ -108,6 +119,7 @@ export default {
         const res = await this.$axios.post(url, this.createAccount)
         console.debug('create user', res.data)
         this.$toast.success('Success. Check your inbox!')
+        this.$router.push('/login')
       } catch (err) {
         console.error('create user failed', err)
         this.$toast.error('Failed to create user')