diff --git a/.gitlab-common-ci.yml b/.gitlab-common-ci.yml
index 83a16b5f02426ff136b4d2bf673a3da65dcc5daa..f5b1aa5c9254d0921c438e047364e4e3e7c8ca29 100644
--- a/.gitlab-common-ci.yml
+++ b/.gitlab-common-ci.yml
@@ -35,10 +35,10 @@ stages:
     - cd $PROJECT_FOLDER
   script:
     - ./mvnw -B -Pprod,swagger verify
-    - awk -F"," '{ branches += $6 + $7; covered += $7 } END { print covered, "/", branches, "branches covered"; print 100*covered/branches, "%covered" }' target/jacoco-aggregate/index.csv
+    - awk -F"," '{ branches += $6 + $7; covered += $7 } END { print covered, "/", branches, "branches covered"; print 100*covered/branches, "%covered" }' target/jacoco-aggregate/jacoco.csv
   artifacts:
     reports:
-      junit: $PROJECT_FOLDER/target/test-results/TEST-*.xml
+      junit: $PROJECT_FOLDER/target/test-results/**/TEST-*.xml
     paths:
       - $PROJECT_FOLDER/target/jacoco-aggregate
     expire_in: 1 day
diff --git a/borestop/pom.xml b/borestop/pom.xml
index 304e1901b7137ad0735b4b0e70dc288f001ec9e2..e984eed49a3d26ad914397b329e2f126ea9277aa 100644
--- a/borestop/pom.xml
+++ b/borestop/pom.xml
@@ -55,6 +55,7 @@
     <validation-api.version>2.0.1.Final</validation-api.version>
     <jaxb-runtime.version>2.3.3</jaxb-runtime.version>
     <mapstruct.version>1.3.1.Final</mapstruct.version>
+    <cucumber.version>6.4.0</cucumber.version>
     <!-- Plugin versions -->
     <maven-clean-plugin.version>3.1.0</maven-clean-plugin.version>
     <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
@@ -280,6 +281,30 @@
       <artifactId>metrics-core</artifactId>
     </dependency>
     <!-- jhipster-needle-maven-add-dependency -->
+    <!-- Cucumber -->
+    <dependency>
+      <groupId>io.cucumber</groupId>
+      <artifactId>cucumber-java</artifactId>
+      <version>${cucumber.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.cucumber</groupId>
+      <artifactId>cucumber-junit</artifactId>
+      <version>${cucumber.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>io.cucumber</groupId>
+      <artifactId>cucumber-spring</artifactId>
+      <version>${cucumber.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.vintage</groupId>
+      <artifactId>junit-vintage-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -778,6 +803,7 @@
             <excludes>
               <exclude>**/*IT*</exclude>
               <exclude>**/*IntTest*</exclude>
+              <exclude>**/*CucumberTest*</exclude>
             </excludes>
           </configuration>
         </plugin>
@@ -795,6 +821,7 @@
             <includes>
               <include>**/*IT*</include>
               <include>**/*IntTest*</include>
+              <include>**/*CucumberTest*</include>
             </includes>
           </configuration>
           <executions>
diff --git a/borestop/src/main/java/com/ippon/borestop/config/SecurityConfiguration.java b/borestop/src/main/java/com/ippon/borestop/config/SecurityConfiguration.java
index 48042231fe4163b056f386e8bf9aa80c8dcd293c..156106b65ffecb84db26038f3767bd453c8fd560 100644
--- a/borestop/src/main/java/com/ippon/borestop/config/SecurityConfiguration.java
+++ b/borestop/src/main/java/com/ippon/borestop/config/SecurityConfiguration.java
@@ -1,8 +1,9 @@
 package com.ippon.borestop.config;
 
 import com.ippon.borestop.common.infrastructure.Generated;
-import com.ippon.borestop.security.*;
-import com.ippon.borestop.security.jwt.*;
+import com.ippon.borestop.security.AuthoritiesConstants;
+import com.ippon.borestop.security.jwt.JWTConfigurer;
+import com.ippon.borestop.security.jwt.TokenProvider;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Import;
 import org.springframework.http.HttpMethod;
@@ -15,6 +16,10 @@ import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
+import org.springframework.security.web.context.SecurityContextRepository;
+import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
+import org.springframework.security.web.csrf.CsrfTokenRepository;
 import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
 import org.springframework.web.filter.CorsFilter;
 import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
@@ -58,6 +63,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
     // @formatter:off
         http
             .csrf()
+            .csrfTokenRepository(csrfTokenRepository())
             .disable()
             .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
             .exceptionHandling()
@@ -91,10 +97,23 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
         .and()
             .httpBasic()
         .and()
-            .apply(securityConfigurerAdapter());
+            .apply(securityConfigurerAdapter())
+        .and()
+            .securityContext()
+                .securityContextRepository(securityContextRepository());
   // @formatter:on
   }
 
+  @Bean
+  public SecurityContextRepository securityContextRepository() {
+    return new HttpSessionSecurityContextRepository();
+  }
+
+  @Bean
+  public CsrfTokenRepository csrfTokenRepository() {
+    return CookieCsrfTokenRepository.withHttpOnlyFalse();
+  }
+
   private JWTConfigurer securityConfigurerAdapter() {
     return new JWTConfigurer(tokenProvider);
   }
diff --git a/borestop/src/test/features/jhipster/account.feature b/borestop/src/test/features/jhipster/account.feature
new file mode 100644
index 0000000000000000000000000000000000000000..5abae8a05fe8d2e9a822eaf1fe9a29ad1a466069
--- /dev/null
+++ b/borestop/src/test/features/jhipster/account.feature
@@ -0,0 +1,12 @@
+Feature: Accounts management
+
+  Scenario: Can't get authentication for not authenticated user
+    Given I am not logged in
+    When I get my account information
+    Then I should not be authorized
+    
+  Scenario: Get account informations
+    Given I am logged in as "admin"
+    When I get my account information
+    Then My login should be "admin"
+    And My email should be "admin@localhost"
\ No newline at end of file
diff --git a/borestop/src/test/java/com/ippon/borestop/cucumber/CucumberConfiguration.java b/borestop/src/test/java/com/ippon/borestop/cucumber/CucumberConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..093a704514541ef933d5043c97517ee7b60c6c14
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/cucumber/CucumberConfiguration.java
@@ -0,0 +1,79 @@
+package com.ippon.borestop.cucumber;
+
+import com.ippon.borestop.BorestopApp;
+import com.ippon.borestop.cucumber.CucumberConfiguration.CucumberSecurityContextConfiguration;
+import com.ippon.borestop.infrastructure.primay.CucumberTestContext;
+import io.cucumber.java.Before;
+import io.cucumber.spring.CucumberContextConfiguration;
+import io.github.jhipster.config.JHipsterConstants;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.boot.test.context.TestConfiguration;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.client.BufferingClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.http.converter.StringHttpMessageConverter;
+import org.springframework.security.web.context.SecurityContextRepository;
+import org.springframework.security.web.csrf.CsrfTokenRepository;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.web.client.RestTemplate;
+
+@CucumberContextConfiguration
+@ActiveProfiles(JHipsterConstants.SPRING_PROFILE_TEST)
+@SpringBootTest(classes = { BorestopApp.class, CucumberSecurityContextConfiguration.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
+public class CucumberConfiguration {
+  @Autowired
+  private TestRestTemplate rest;
+
+  @Before
+  public void loadInterceptors() {
+    ClientHttpRequestFactory requestFactory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
+
+    RestTemplate template = rest.getRestTemplate();
+    template.setRequestFactory(requestFactory);
+    template.setInterceptors(List.of(mockedCsrfTokenInterceptor(), saveLastResultInterceptor()));
+    template.getMessageConverters().add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
+  }
+
+  private ClientHttpRequestInterceptor mockedCsrfTokenInterceptor() {
+    return (request, body, execution) -> {
+      request.getHeaders().add("mocked-csrf-token", "MockedToken");
+
+      return execution.execute(request, body);
+    };
+  }
+
+  private ClientHttpRequestInterceptor saveLastResultInterceptor() {
+    return (request, body, execution) -> {
+      ClientHttpResponse response = execution.execute(request, body);
+
+      CucumberTestContext.addResponse(request, response);
+
+      return response;
+    };
+  }
+
+  @TestConfiguration
+  public static class CucumberSecurityContextConfiguration {
+
+    @Bean
+    @Primary
+    public SecurityContextRepository securityContextRepository() {
+      return new MockedSecurityContextRepository();
+    }
+
+    @Bean
+    @Primary
+    public CsrfTokenRepository csrfTokenRepository() {
+      return new MockedCsrfTokenRepository();
+    }
+  }
+}
diff --git a/borestop/src/test/java/com/ippon/borestop/cucumber/CucumberTest.java b/borestop/src/test/java/com/ippon/borestop/cucumber/CucumberTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..71d535be7bf3e2f37cb618f43df9447673397e49
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/cucumber/CucumberTest.java
@@ -0,0 +1,13 @@
+package com.ippon.borestop.cucumber;
+
+import io.cucumber.junit.Cucumber;
+import io.cucumber.junit.CucumberOptions;
+import org.junit.runner.RunWith;
+
+@RunWith(Cucumber.class)
+@CucumberOptions(
+  glue = "com.ippon.borestop",
+  plugin = { "pretty", "json:target/cucumber/cucumber.json", "html:target/cucumber/cucumber.htm" },
+  features = "src/test/features"
+)
+public class CucumberTest {}
diff --git a/borestop/src/test/java/com/ippon/borestop/cucumber/HttpSteps.java b/borestop/src/test/java/com/ippon/borestop/cucumber/HttpSteps.java
new file mode 100644
index 0000000000000000000000000000000000000000..20dd152e4282f3718009751b95f6acb798a6a1c7
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/cucumber/HttpSteps.java
@@ -0,0 +1,20 @@
+package com.ippon.borestop.cucumber;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ippon.borestop.infrastructure.primay.CucumberTestContext;
+import io.cucumber.java.en.Then;
+import org.springframework.http.HttpStatus;
+
+public class HttpSteps {
+
+  @Then("I can't find document")
+  public void shouldGetNotFoundResult() {
+    assertThat(CucumberTestContext.getStatus()).isEqualTo(HttpStatus.NOT_FOUND);
+  }
+
+  @Then("I should not be authorized")
+  public void shouldNotBeAuthorized() {
+    assertThat(CucumberTestContext.getStatus()).isIn(HttpStatus.UNAUTHORIZED, HttpStatus.FORBIDDEN);
+  }
+}
diff --git a/borestop/src/test/java/com/ippon/borestop/cucumber/MockedCsrfTokenRepository.java b/borestop/src/test/java/com/ippon/borestop/cucumber/MockedCsrfTokenRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..12de4b68bbecf035030b0b2d78114a454f4d9d2c
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/cucumber/MockedCsrfTokenRepository.java
@@ -0,0 +1,35 @@
+package com.ippon.borestop.cucumber;
+
+import static org.mockito.Mockito.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.web.csrf.CsrfToken;
+import org.springframework.security.web.csrf.CsrfTokenRepository;
+
+public class MockedCsrfTokenRepository implements CsrfTokenRepository {
+  private static final CsrfToken TOKEN = buildCsrfToken();
+
+  private static CsrfToken buildCsrfToken() {
+    CsrfToken token = mock(CsrfToken.class);
+
+    when(token.getHeaderName()).thenReturn("mocked-csrf-token");
+    when(token.getParameterName()).thenReturn("mocked-csrf-token");
+    when(token.getToken()).thenReturn("MockedToken");
+
+    return token;
+  }
+
+  @Override
+  public CsrfToken generateToken(HttpServletRequest request) {
+    return TOKEN;
+  }
+
+  @Override
+  public void saveToken(CsrfToken token, HttpServletRequest request, HttpServletResponse response) {}
+
+  @Override
+  public CsrfToken loadToken(HttpServletRequest request) {
+    return TOKEN;
+  }
+}
diff --git a/borestop/src/test/java/com/ippon/borestop/cucumber/MockedSecurityContextRepository.java b/borestop/src/test/java/com/ippon/borestop/cucumber/MockedSecurityContextRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..6454a5613dd68ea7163c26f9729a4194059ebe75
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/cucumber/MockedSecurityContextRepository.java
@@ -0,0 +1,30 @@
+package com.ippon.borestop.cucumber;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextImpl;
+import org.springframework.security.web.context.HttpRequestResponseHolder;
+import org.springframework.security.web.context.SecurityContextRepository;
+
+public class MockedSecurityContextRepository implements SecurityContextRepository {
+  private Authentication authentication;
+
+  public void authentication(Authentication authentication) {
+    this.authentication = authentication;
+  }
+
+  @Override
+  public boolean containsContext(HttpServletRequest request) {
+    return authentication != null;
+  }
+
+  @Override
+  public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
+    return new SecurityContextImpl(authentication);
+  }
+
+  @Override
+  public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {}
+}
diff --git a/borestop/src/test/java/com/ippon/borestop/infrastructure/primay/AuthenticationSteps.java b/borestop/src/test/java/com/ippon/borestop/infrastructure/primay/AuthenticationSteps.java
new file mode 100644
index 0000000000000000000000000000000000000000..cce5c375771d687e979e97e73c61744ffa56b786
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/infrastructure/primay/AuthenticationSteps.java
@@ -0,0 +1,44 @@
+package com.ippon.borestop.infrastructure.primay;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ippon.borestop.cucumber.MockedSecurityContextRepository;
+import com.ippon.borestop.security.AuthoritiesConstants;
+import io.cucumber.java.en.Given;
+import io.cucumber.java.en.Then;
+import java.util.Map;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.TestingAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+public class AuthenticationSteps {
+  @Autowired
+  private MockedSecurityContextRepository contexts;
+
+  private static final Map<String, Authentication> USERS = Map.of(
+    "admin",
+    new TestingAuthenticationToken("admin", "N/A", AuthorityUtils.createAuthorityList(AuthoritiesConstants.ADMIN))
+  );
+
+  @Given("I am logged in as {string}")
+  public void authenticateUser(String username) {
+    Authentication authentication = USERS.get(username);
+    SecurityContextHolder.getContext().setAuthentication(authentication);
+
+    contexts.authentication(authentication);
+  }
+
+  @Given("I logout")
+  @Given("I am not logged in")
+  public void logout() {
+    contexts.authentication(null);
+  }
+
+  @Then("I should get an authorization error")
+  public void authorizationError() {
+    assertThat(CucumberTestContext.getStatus()).isEqualTo(HttpStatus.FORBIDDEN);
+  }
+}
diff --git a/borestop/src/test/java/com/ippon/borestop/infrastructure/primay/CucumberTestContext.java b/borestop/src/test/java/com/ippon/borestop/infrastructure/primay/CucumberTestContext.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b015bc72a0a822c3da743a9b5a08c9307702e32
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/infrastructure/primay/CucumberTestContext.java
@@ -0,0 +1,111 @@
+package com.ippon.borestop.infrastructure.primay;
+
+import com.jayway.jsonpath.Configuration;
+import com.jayway.jsonpath.JsonPath;
+import com.jayway.jsonpath.spi.json.JsonProvider;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.Deque;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentLinkedDeque;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import net.minidev.json.JSONArray;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.util.StreamUtils;
+
+public final class CucumberTestContext {
+  private static final Deque<RestQuery> queries = new ConcurrentLinkedDeque<>();
+  private static JsonProvider jsonReader = Configuration.defaultConfiguration().jsonProvider();
+
+  private CucumberTestContext() {}
+
+  public static void addResponse(HttpRequest request, ClientHttpResponse response) {
+    queries.addFirst(new RestQuery(request, response));
+  }
+
+  public static HttpStatus getStatus() {
+    return queries.getFirst().getStatus();
+  }
+
+  public static <T> T getResponse(Class<T> responseClass) {
+    return queries.getFirst().getResponse().map(response -> TestJson.readFromJson(response, responseClass)).orElse(null);
+  }
+
+  public static Object getElement(String jsonPath) {
+    return queries.getFirst().getResponse().map(toElement(jsonPath)).orElse(null);
+  }
+
+  public static Object getElement(String uri, String jsonPath) {
+    return queries
+      .stream()
+      .filter(query -> query.forUri(uri))
+      .findFirst()
+      .flatMap(response -> response.response.map(toElement(jsonPath)))
+      .orElse(null);
+  }
+
+  private static Function<String, Object> toElement(String jsonPath) {
+    return response -> {
+      Object element = JsonPath.read(jsonReader.parse(response), jsonPath);
+
+      if (element instanceof JSONArray) {
+        JSONArray elements = (JSONArray) element;
+
+        if (elements.size() == 0) {
+          return null;
+        }
+
+        return elements.stream().map(Object::toString).collect(Collectors.joining(", "));
+      }
+
+      return element;
+    };
+  }
+
+  public static String getCreatedWorkingFolderId() {
+    return (String) CucumberTestContext.getElement("working-folders", "$.id");
+  }
+
+  public static void reset() {
+    queries.clear();
+  }
+
+  private static class RestQuery {
+    private final String uri;
+    private final HttpStatus status;
+    private final Optional<String> response;
+
+    public RestQuery(HttpRequest request, ClientHttpResponse response) {
+      uri = request.getURI().toString();
+      try {
+        status = response.getStatusCode();
+        this.response = readResponse(response);
+      } catch (IOException e) {
+        throw new AssertionError(e.getMessage(), e);
+      }
+    }
+
+    private Optional<String> readResponse(ClientHttpResponse response) throws IOException {
+      try {
+        return Optional.of(StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
+      } catch (Exception e) {
+        return Optional.empty();
+      }
+    }
+
+    private boolean forUri(String uri) {
+      return this.uri.contains(uri);
+    }
+
+    private HttpStatus getStatus() {
+      return status;
+    }
+
+    private Optional<String> getResponse() {
+      return response;
+    }
+  }
+}
diff --git a/borestop/src/test/java/com/ippon/borestop/web/rest/AccountsSteps.java b/borestop/src/test/java/com/ippon/borestop/web/rest/AccountsSteps.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea9274f83b21ab17fcc8b3cd40cfb6c1234bacc4
--- /dev/null
+++ b/borestop/src/test/java/com/ippon/borestop/web/rest/AccountsSteps.java
@@ -0,0 +1,29 @@
+package com.ippon.borestop.web.rest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.ippon.borestop.infrastructure.primay.CucumberTestContext;
+import io.cucumber.java.en.Then;
+import io.cucumber.java.en.When;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.web.client.TestRestTemplate;
+
+public class AccountsSteps {
+  @Autowired
+  private TestRestTemplate rest;
+
+  @When("I get my account information")
+  public void getAccountInforamtion() {
+    rest.getForEntity("/api/account", Void.class);
+  }
+
+  @Then("My login should be {string}")
+  public void shouldHaveLogin(String login) {
+    assertThat(CucumberTestContext.getElement("$.login")).isEqualTo(login);
+  }
+
+  @Then("My email should be {string}")
+  public void shouldHaveEmail(String email) {
+    assertThat(CucumberTestContext.getElement("$.email")).isEqualTo(email);
+  }
+}