title: Spring Security with REST API
body: <p>I am trying to create an application that will primarily access a REST API using Spring, and am trying to configure the security side. Trying to present the actual structure of the application using this picture:
  <a href="https://i.stack.imgur.com/M9afo.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/M9afo.png" alt="enter image description here"></a></p>
  
  <ol>
  <li>Request can come from any platform to "abc.com/rest_api/"</li>
  <li>Request will be send to point 3 or point 5. If user has already authenticated by username and password then request will be verified against Token else will be redirected to database.</li>
  <li>If username and password will have to be authenticated by database then a token will be generated and send back in response.</li>
  <li>After that only token based authentication will work.</li>
  </ol>
  
  <p>I have tried to create a basic structure and I think must be making a minor mistake due to which it's not working as expected.</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableWebMvcSecurity
  @EnableGlobalMethodSecurity(securedEnabled=true, prePostEnabled=true)
  public class UserDetailsSecurityConfig extends WebSecurityConfigurerAdapter {
      @Autowired
      private NSecurityContextHolder securityContextHolder;
  
      @Autowired
      private NHttpServletRequestBinder&lt;Authentication&gt; authenticationBinder;
  
      public static final String DEF_USERS_BY_USERNAME_QUERY
              = "SELECT user ";
  
  
  public static final String GROUPS_BY_USERNAME_QUERY =
          "SELECT groups by user";
  public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY =
          "SELECT  authorities";
  
  
  @Autowired
  public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  
          auth.jdbcAuthentication().dataSource(getDataSourceFromJndi())
                  .usersByUsernameQuery(DEF_USERS_BY_USERNAME_QUERY).
                  authoritiesByUsernameQuery(DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY).
                  groupAuthoritiesByUsername(GROUPS_BY_USERNAME_QUERY);
  
  
      }
        private DataSource getDataSourceFromJndi() {
          try {
  
  
               DataSource dataSource = (DataSource) new InitialContext().lookup("DS");
              return dataSource;
  
          } catch (Exception e) {
              e.printStackTrace();
              return null;
          }
      }
  
        @Bean
      @Override
      public AuthenticationManager authenticationManagerBean() throws Exception {
          return super.authenticationManagerBean();
      }
  
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.jdbcAuthentication().dataSource(getDataSourceFromJndi())
                  .usersByUsernameQuery(DEF_USERS_BY_USERNAME_QUERY).
                  authoritiesByUsernameQuery(DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY).
                  groupAuthoritiesByUsername(GROUPS_BY_USERNAME_QUERY);
  
      }
  
  
        @Override
      protected void configure(HttpSecurity http) throws Exception {
  
  
                  // The http.formLogin().defaultSuccessUrl("/path/") method is required when using stateless Spring Security
          // because the session cannot be used to redirect to the page that was requested while signed out. Unfortunately
          // using this configuration method will cause our custom success handler (below) to be overridden with the
          // default success handler. So to replicate the defaultSuccessUrl("/path/") configuration we will instead
          // correctly configure and delegate to the default success handler.
          final SimpleUrlAuthenticationSuccessHandler delegate = new SimpleUrlAuthenticationSuccessHandler();
          delegate.setDefaultTargetUrl("/api/");
            // Make Spring Security stateless. This means no session will be created by Spring Security, nor will it use any
          // previously existing session.
          http.sessionManagement().sessionCreationPolicy(STATELESS);
          // Disable the CSRF prevention because it requires the session, which of course is not available in a
          // stateless application. It also greatly complicates the requirements for the sign in POST request.
          http.csrf().disable();
          // Viewing any page requires authentication.
          http.authorizeRequests().anyRequest().authenticated();
          http
            .formLogin().loginPage("http://localhost/web/ui/#access/signin")
            .permitAll()
              // Override the sign in success handler with our stateless implementation. This will update the response
              // with any headers and cookies that are required for subsequent authenticated requests.
              .successHandler(new NStatelessAuthenticationSuccessHandler(authenticationBinder, delegate));
          http.logout().logoutUrl("http://localhost/web/ui/#access/signin").logoutSuccessUrl("http://localhost/web/ui/#access/signin");
          // Add our stateless authentication filter before the default sign in filter. The default sign in filter is
          // still used for the initial sign in, but if a user is authenticated we need to acknowledge this before it is
          // reached.
          http.addFilterBefore(
              new StatelessAuthenticationFilter(authenticationBinder, securityContextHolder),
              UsernamePasswordAuthenticationFilter.class
          );
  
  } 
  
  }
  </code></pre>
  
  <p>And I have two types of authenticationBinder i.e. TokenBased and UserNameBased.</p>
  
  <p><strong>TokenBased:</strong></p>
  
  <pre><code>@Component
  public class NXAuthTokenHttpServletRequestBinder implements NHttpServletRequestBinder&lt;String&gt; {
  
      private static final String X_AUTH_TOKEN = "X-AUTH-TOKEN";
      private final NTokenFactory tokenFactory;
  
      @Autowired
      public NXAuthTokenHttpServletRequestBinder(NTokenFactory tokenFactory) {
          this.tokenFactory = tokenFactory;
      }
  
      @Override
      public void add(HttpServletResponse response, String username) {
  
          final String token = tokenFactory.create(username);
  
          response.addHeader(X_AUTH_TOKEN, token);
          response.addCookie(new Cookie(X_AUTH_TOKEN, token));
      }
  
      @Override
      public String retrieve(HttpServletRequest request) {
  
          final String cookieToken = findToken(request);
  
          if (cookieToken != null) {
              return tokenFactory.parseUsername(cookieToken);
          }
  
          return null;
      }
  
      private static String findToken(HttpServletRequest request) {
          Enumeration&lt;String&gt; it = request.getHeaderNames();
          while(it.hasMoreElements()){
              System.out.println(it.nextElement());
          }
          final String headerToken = request.getHeader(X_AUTH_TOKEN);
  
          if (headerToken != null) {
              return headerToken;
          }
  
          final Cookie[] cookies = request.getCookies();
  
          if (cookies != null) {
              for (Cookie cookie : cookies) {
                  if (X_AUTH_TOKEN.equals(cookie.getName())) {
                      return cookie.getValue();
                  }
              }
          }
  
          return null;
      }
  }
  </code></pre>
  
  <p><strong>UserBased:</strong></p>
  
  <pre><code>@Component
  @Primary
  public class NUserAuthenticationFactory implements NHttpServletRequestBinder&lt;Authentication&gt; {
  
      private final NHttpServletRequestBinder&lt;String&gt; httpServletRequestBinder;
  
      @Autowired
  
      public NUserAuthenticationFactory(NHttpServletRequestBinder&lt;String&gt; httpServletRequestBinder) {
          this.httpServletRequestBinder = httpServletRequestBinder;
      }
  
      @Override
      public void add(HttpServletResponse response, Authentication authentication) {
          httpServletRequestBinder.add(response, authentication.getName());
      }
  
      @Override
      public UserAuthentication retrieve(HttpServletRequest request) {
  
          final String username = httpServletRequestBinder.retrieve(request);
  
          if (username != null) {
  
              return new UserAuthentication(new CustomJDBCDaoImpl().loadUserByUsername(username));
          }
  
          return null;
      }
  }
  </code></pre>
  
  <p><strong>Problem</strong>
  Whenever I load my application it comes into UserBased Authentication and then try to fetch the username from token instead of validating it from database. But, by that time no token was there as it's the first post request I make from the UI. And it redirects me back to the same Login Page.</p>
  
  <p><strong>Logs:</strong></p>
  
  <blockquote>
    <p>Fine:   / at position 1 of 12 in additional filter chain; firing
    Filter: 'WebAsyncManagerIntegrationFilter' Fine:   / at position 2 of
    12 in additional filter chain; firing Filter:
    'SecurityContextPersistenceFilter' Fine:   / at position 3 of 12 in
    additional filter chain; firing Filter: 'HeaderWriterFilter' Fine:<br>
    Not injecting HSTS header since it did not match the requestMatcher
    org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@a837508
    Fine:   / at position 4 of 12 in additional filter chain; firing
    Filter: 'LogoutFilter' Fine:   Checking match of request : '/';
    against '<a href="http://localhost/web/ui/#access/signin" rel="nofollow noreferrer">http://localhost/web/ui/#access/signin</a>' Fine:   / at position
    5 of 12 in additional filter chain; firing Filter:
    'StatelessAuthenticationFilter' Fine:   / at position 6 of 12 in
    additional filter chain; firing Filter:
    'UsernamePasswordAuthenticationFilter' Fine:   Request 'GET /' doesn't
    match 'POST <a href="http://localhost/web/ui/#access/signin" rel="nofollow noreferrer">http://localhost/web/ui/#access/signin</a> Fine:   / at
    position 7 of 12 in additional filter chain; firing Filter:
    'RequestCacheAwareFilter' Fine:   / at position 8 of 12 in additional
    filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
    Fine:   / at position 9 of 12 in additional filter chain; firing
    Filter: 'AnonymousAuthenticationFilter' Fine:   Populated
    SecurityContextHolder with anonymous token:
    'org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6:
    Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated:
    true; Details:
    org.springframework.security.web.authentication.WebAuthenticationDetails@957e:
    RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities:
    ROLE_ANONYMOUS' Fine:   / at position 10 of 12 in additional filter
    chain; firing Filter: 'SessionManagementFilter' Fine:   Requested
    session ID 3e2c15a2a427bf47e51496d2a186 is invalid. Fine:   / at
    position 11 of 12 in additional filter chain; firing Filter:
    'ExceptionTranslationFilter' Fine:   / at position 12 of 12 in
    additional filter chain; firing Filter: 'FilterSecurityInterceptor'
    Fine:   Secure object: FilterInvocation: URL: /; Attributes:
    [authenticated] Fine:   Previously Authenticated:
    org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6:
    Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated:
    true; Details:
    org.springframework.security.web.authentication.WebAuthenticationDetails@957e:
    RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities:
    ROLE_ANONYMOUS Fine:   Voter:
    org.springframework.security.web.access.expression.WebExpressionVoter@2ac71565,
    returned: -1 Fine:   Access is denied (user is anonymous); redirecting
    to authentication entry point
    org.springframework.security.access.AccessDeniedException: Access is
    denied</p>
  </blockquote>