title: How to enable Bearer authentication on Spring Boot application?
body: <p>What I am trying to achieve is:</p>
  
  <ul>
  <li>users, authorities, clients and access tokens stored in a database (i.e. MySQL) accessed via jdbc</li>
  <li>API exposes endpoints for you to ask "can I have an OAuth2 bearer token? I know the client ID and secret"</li>
  <li>API lets you access MVC endpoints if you supply a Bearer token in your request header</li>
  </ul>
  
  <p>I got pretty far with this — the first two points are working.</p>
  
  <p>I was not able to use a completely default OAuth2 setup for my Spring Boot application, because the standard table names are already in-use in my database (I have a "users" table already, for example).</p>
  
  <p>I constructed my own instances of JdbcTokenStore, JdbcClientDetailsService, and JdbcAuthorizationCodeServices manually, configured them to use the custom table names from my database, and set up my application to use these instances.</p>
  
  <hr>
  
  <p>So, here's what I have so far. I can ask for a Bearer token:</p>
  
  <pre class="lang-bash prettyprint-override"><code># The `-u` switch provides the client ID &amp; secret over HTTP Basic Auth 
  curl -u8fc9d384-619a-11e7-9fe6-246798c61721:9397ce6c-619a-11e7-9fe6-246798c61721 \
  'http://localhost:8080/oauth/token' \
  -d grant_type=password \
  -d username=bob \
  -d password=tom
  </code></pre>
  
  <p>I receive a response; nice!</p>
  
  <pre class="lang-json prettyprint-override"><code>{"access_token":"1ee9b381-e71a-4e2f-8782-54ab1ce4d140","token_type":"bearer","refresh_token":"8db897c7-03c6-4fc3-bf13-8b0296b41776","expires_in":26321,"scope":"read write"}
  </code></pre>
  
  <p>Now I try to <em>use</em> that token:</p>
  
  <pre class="lang-bash prettyprint-override"><code>curl 'http://localhost:8080/test' \
  -H "Authorization: Bearer 1ee9b381-e71a-4e2f-8782-54ab1ce4d140"
  </code></pre>
  
  <p>Alas:</p>
  
  <pre class="lang-json prettyprint-override"><code>{
     "timestamp":1499452163373,
     "status":401,
     "error":"Unauthorized",
     "message":"Full authentication is required to access this resource",
     "path":"/test"
  }
  </code></pre>
  
  <p>This means (in this particular case) that it has fallen back to <em>anonymous</em> authentication. You can see the <em>real</em> error if I add <code>.anonymous().disable()</code> to my HttpSecurity:</p>
  
  <pre class="lang-json prettyprint-override"><code>{
     "timestamp":1499452555312,
     "status":401,
     "error":"Unauthorized",
     "message":"An Authentication object was not found in the SecurityContext",
     "path":"/test"
  }
  </code></pre>
  
  <hr>
  
  <p>I investigated this more deeply by increasing the logging verbosity:</p>
  
  <pre class="lang-yaml prettyprint-override"><code>logging.level:
      org.springframework:
        security: DEBUG
  </code></pre>
  
  <p>This reveals the 10 filters through which my request travels:</p>
  
  <pre><code>o.s.security.web.FilterChainProxy        : /test at position 1 of 10 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
  o.s.security.web.FilterChainProxy        : /test at position 2 of 10 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
  w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
  w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
  o.s.security.web.FilterChainProxy        : /test at position 3 of 10 in additional filter chain; firing Filter: 'HeaderWriterFilter'
  o.s.security.web.FilterChainProxy        : /test at position 4 of 10 in additional filter chain; firing Filter: 'LogoutFilter'
  o.s.security.web.FilterChainProxy        : /test at position 5 of 10 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
  o.s.security.web.FilterChainProxy        : /test at position 6 of 10 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
  o.s.security.web.FilterChainProxy        : /test at position 7 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
  o.s.security.web.FilterChainProxy        : /test at position 8 of 10 in additional filter chain; firing Filter: 'SessionManagementFilter'
  o.s.security.web.FilterChainProxy        : /test at position 9 of 10 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
  o.s.security.web.FilterChainProxy        : /test at position 10 of 10 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
  o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /test; Attributes: [authenticated]
  o.s.s.w.a.ExceptionTranslationFilter     : Authentication exception occurred; redirecting to authentication entry point
  
  org.springframework.security.authentication.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext
      at org.springframework.security.access.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:379) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  </code></pre>
  
  <p>That's what it looks like if Anonymous users are <em>disabled</em>. If they're <em>enabled</em>: <code>AnonymousAuthenticationFilter</code> is added into the filter chain just after <code>SecurityContextHolderAwareRequestFilter</code>, and the sequence ends more like this:</p>
  
  <pre><code>o.s.security.web.FilterChainProxy        : /test at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
  o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /test; Attributes: [authenticated]
  o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
  o.s.s.access.vote.AffirmativeBased       : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@5ff24abf, returned: -1
  o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is anonymous); redirecting to authentication entry point
  
  org.springframework.security.access.AccessDeniedException: Access is denied
      at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
  </code></pre>
  
  <p>Either way: no good.</p>
  
  <p><strong>Essentially it indicates to me that we are missing some step in the filter chain. We need a filter that would read the header of the ServletRequest, then populate the security context's authentication:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>SecurityContextHolder.getContext().setAuthentication(request: HttpServletRequest);
  </code></pre>
  
  <p>I wonder how to get such a filter?</p>
  
  <hr>
  
  <p>This is what my application looks like. It's Kotlin, but hopefully it should make sense to the Java eye.</p>
  
  <p><strong>Application.kt:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>@SpringBootApplication(scanBasePackageClasses=arrayOf(
          com.example.domain.Package::class,
          com.example.service.Package::class,
          com.example.web.Package::class
  ))
  class MyApplication
  
  fun main(args: Array&lt;String&gt;) {
      SpringApplication.run(MyApplication::class.java, *args)
  }
  </code></pre>
  
  <p><strong>TestController:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>@RestController
  class TestController {
      @RequestMapping("/test")
      fun Test(): String {
          return "hey there"
      }
  }
  </code></pre>
  
  <p><strong>MyWebSecurityConfigurerAdapter:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>@Configuration
  @EnableWebSecurity
  /**
   * Based on:
   * https://stackoverflow.com/questions/25383286/spring-security-custom-userdetailsservice-and-custom-user-class
   *
   * Password encoder:
   * http://www.baeldung.com/spring-security-authentication-with-a-database
   */
  class MyWebSecurityConfigurerAdapter(
          val userDetailsService: MyUserDetailsService
  ) : WebSecurityConfigurerAdapter() {
  
      private val passwordEncoder = BCryptPasswordEncoder()
  
      override fun userDetailsService() : UserDetailsService {
          return userDetailsService
      }
  
      override fun configure(auth: AuthenticationManagerBuilder) {
          auth
                  .authenticationProvider(authenticationProvider())
      }
  
      @Bean
      fun authenticationProvider() : AuthenticationProvider {
          val authProvider = DaoAuthenticationProvider()
          authProvider.setUserDetailsService(userDetailsService())
          authProvider.setPasswordEncoder(passwordEncoder)
          return authProvider
      }
  
      override fun configure(http: HttpSecurity?) {
          http!!
                  .anonymous().disable()
                  .authenticationProvider(authenticationProvider())
                  .authorizeRequests()
                      .anyRequest().authenticated()
                  .and()
                  .httpBasic()
                  .and()
                  .csrf().disable()
      }
  }
  </code></pre>
  
  <p><strong>MyAuthorizationServerConfigurerAdapter:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>/**
   * Based on:
   * https://github.com/spring-projects/spring-security-oauth/blob/master/tests/annotation/jdbc/src/main/java/demo/Application.java#L68
   */
  @Configuration
  @EnableAuthorizationServer
  class MyAuthorizationServerConfigurerAdapter(
          val auth : AuthenticationManager,
          val dataSource: DataSource,
          val userDetailsService: UserDetailsService
  
  ) : AuthorizationServerConfigurerAdapter() {
  
      private val passwordEncoder = BCryptPasswordEncoder()
  
      @Bean
      fun tokenStore(): JdbcTokenStore {
          val tokenStore = JdbcTokenStore(dataSource)
          val oauthAccessTokenTable = "auth_schema.oauth_access_token"
          val oauthRefreshTokenTable = "auth_schema.oauth_refresh_token"
          tokenStore.setDeleteAccessTokenFromRefreshTokenSql("delete from ${oauthAccessTokenTable} where refresh_token = ?")
          tokenStore.setDeleteAccessTokenSql("delete from ${oauthAccessTokenTable} where token_id = ?")
          tokenStore.setDeleteRefreshTokenSql("delete from ${oauthRefreshTokenTable} where token_id = ?")
          tokenStore.setInsertAccessTokenSql("insert into ${oauthAccessTokenTable} (token_id, token, authentication_id, " +
                  "user_name, client_id, authentication, refresh_token) values (?, ?, ?, ?, ?, ?, ?)")
          tokenStore.setInsertRefreshTokenSql("insert into ${oauthRefreshTokenTable} (token_id, token, authentication) values (?, ?, ?)")
          tokenStore.setSelectAccessTokenAuthenticationSql("select token_id, authentication from ${oauthAccessTokenTable} where token_id = ?")
          tokenStore.setSelectAccessTokenFromAuthenticationSql("select token_id, token from ${oauthAccessTokenTable} where authentication_id = ?")
          tokenStore.setSelectAccessTokenSql("select token_id, token from ${oauthAccessTokenTable} where token_id = ?")
          tokenStore.setSelectAccessTokensFromClientIdSql("select token_id, token from ${oauthAccessTokenTable} where client_id = ?")
          tokenStore.setSelectAccessTokensFromUserNameAndClientIdSql("select token_id, token from ${oauthAccessTokenTable} where user_name = ? and client_id = ?")
          tokenStore.setSelectAccessTokensFromUserNameSql("select token_id, token from ${oauthAccessTokenTable} where user_name = ?")
          tokenStore.setSelectRefreshTokenAuthenticationSql("select token_id, authentication from ${oauthRefreshTokenTable} where token_id = ?")
          tokenStore.setSelectRefreshTokenSql("select token_id, token from ${oauthRefreshTokenTable} where token_id = ?")
          return tokenStore
      }
  
      override fun configure(security: AuthorizationServerSecurityConfigurer?) {
          security!!.passwordEncoder(passwordEncoder)
      }
  
      override fun configure(clients: ClientDetailsServiceConfigurer?) {
          val clientDetailsService = JdbcClientDetailsService(dataSource)
          clientDetailsService.setPasswordEncoder(passwordEncoder)
  
          val clientDetailsTable = "auth_schema.oauth_client_details"
          val CLIENT_FIELDS_FOR_UPDATE = "resource_ids, scope, " +
                  "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, " +
                  "refresh_token_validity, additional_information, autoapprove"
          val CLIENT_FIELDS = "client_secret, ${CLIENT_FIELDS_FOR_UPDATE}"
          val BASE_FIND_STATEMENT = "select client_id, ${CLIENT_FIELDS} from ${clientDetailsTable}"
  
          clientDetailsService.setFindClientDetailsSql("${BASE_FIND_STATEMENT} order by client_id")
          clientDetailsService.setDeleteClientDetailsSql("delete from ${clientDetailsTable} where client_id = ?")
          clientDetailsService.setInsertClientDetailsSql("insert into ${clientDetailsTable} (${CLIENT_FIELDS}," +
                  " client_id) values (?,?,?,?,?,?,?,?,?,?,?)")
          clientDetailsService.setSelectClientDetailsSql("${BASE_FIND_STATEMENT} where client_id = ?")
          clientDetailsService.setUpdateClientDetailsSql("update ${clientDetailsTable} set " +
                  "${CLIENT_FIELDS_FOR_UPDATE.replace(", ", "=?, ")}=? where client_id = ?")
          clientDetailsService.setUpdateClientSecretSql("update ${clientDetailsTable} set client_secret = ? where client_id = ?")
          clients!!.withClientDetails(clientDetailsService)
      }
  
      override fun configure(endpoints: AuthorizationServerEndpointsConfigurer?) {
          endpoints!!
                  .authorizationCodeServices(authorizationCodeServices())
                  .authenticationManager(auth)
                  .tokenStore(tokenStore())
                  .approvalStoreDisabled()
                  .userDetailsService(userDetailsService)
      }
  
      @Bean
      protected fun authorizationCodeServices() : AuthorizationCodeServices {
          val codeServices = JdbcAuthorizationCodeServices(dataSource)
          val oauthCodeTable = "auth_schema.oauth_code"
          codeServices.setSelectAuthenticationSql("select code, authentication from ${oauthCodeTable} where code = ?")
          codeServices.setInsertAuthenticationSql("insert into ${oauthCodeTable} (code, authentication) values (?, ?)")
          codeServices.setDeleteAuthenticationSql("delete from ${oauthCodeTable} where code = ?")
          return codeServices
      }
  }
  </code></pre>
  
  <p><strong>MyAuthorizationServerConfigurerAdapter:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>@Service
  class MyUserDetailsService(
          val theDataSource: DataSource
  ) : JdbcUserDetailsManager() {
      @PostConstruct
      fun init() {
          dataSource = theDataSource
  
          val usersTable = "auth_schema.users"
          val authoritiesTable = "auth_schema.authorities"
  
          setChangePasswordSql("update ${usersTable} set password = ? where username = ?")
          setCreateAuthoritySql("insert into ${authoritiesTable} (username, authority) values (?,?)")
          setCreateUserSql("insert into ${usersTable} (username, password, enabled) values (?,?,?)")
          setDeleteUserAuthoritiesSql("delete from ${authoritiesTable} where username = ?")
          setDeleteUserSql("delete from ${usersTable} where username = ?")
          setUpdateUserSql("update ${usersTable} set password = ?, enabled = ? where username = ?")
          setUserExistsSql("select username from ${usersTable} where username = ?")
  
          setAuthoritiesByUsernameQuery("select username,authority from ${authoritiesTable} where username = ?")
          setUsersByUsernameQuery("select username,password,enabled from ${usersTable} " + "where username = ?")
      }
  }
  </code></pre>
  
  <hr>
  
  <p>Any ideas? <strong>Could it be that I need to somehow install the <code>OAuth2AuthenticationProcessingFilter</code> into my filter chain?</strong></p>
  
  <p>I do get such messages on startup… could these be related to the problem?</p>
  
  <pre><code>u.c.c.h.s.auth.MyUserDetailsService      : No authentication manager set. Reauthentication of users when changing passwords will not be performed.
  s.c.a.w.c.WebSecurityConfigurerAdapter$3 : No authenticationProviders and no parentAuthenticationManager defined. Returning null.
  </code></pre>
  
  <hr>
  
  <p><strong>EDIT:</strong></p>
  
  <p>It looks like installing <code>OAuth2AuthenticationProcessingFilter</code> is the job of a <code>ResourceServerConfigurerAdapter</code>. I have added the following class:</p>
  
  <p><strong>MyResourceServerConfigurerAdapter:</strong></p>
  
  <pre class="lang-kotlin prettyprint-override"><code>@Configuration
  @EnableResourceServer
  class MyResourceServerConfigurerAdapter : ResourceServerConfigurerAdapter()
  </code></pre>
  
  <p>And I confirm in the debugger that this causes <code>ResourceServerSecurityConfigurer</code> to enter its <code>configure(http: HttpSecurity)</code> method, which <em>does</em> look like it tries to install a <code>OAuth2AuthenticationProcessingFilter</code> into the filter chain.</p>
  
  <p>But it doesn't look like it succeeded. According to Spring Security's debug output: I still have the same number of filters in my filter chain. <code>OAuth2AuthenticationProcessingFilter</code> is not in there. What's going on?</p>
  
  <hr>
  
  <p><strong>EDIT2</strong>: I wonder if the problem is that I have <em>two</em> classes (<code>WebSecurityConfigurerAdapter</code>, <code>ResourceServerConfigurerAdapter</code>) trying to configure HttpSecurity. Is it mutually exclusive?</p>