title: How to implement a simple web service with token-based access using KeyCloak?
body: <p>I want to create a web service that would work in the following way:</p>
  
  <ol>
  <li><p>The client contats KeyCloak and provides user name and password.</p></li>
  <li><p>KeyCloak returns an access token to the client.</p></li>
  <li><p>Using that access token the client access a page protected by KeyCloak.</p></li>
  </ol>
  
  <p>How can I do it?</p>
  
  <p><strong>What I tried</strong></p>
  
  <p><strong>Step 1: The client gets an access token</strong></p>
  
  <pre><code>private String getAccessToken() throws IOException {
      final CloseableHttpClient client = HttpClients.createDefault();
  
      final List&lt;NameValuePair&gt; nameValuePairs = new ArrayList&lt;NameValuePair&gt;(4);
      nameValuePairs.add(new BasicNameValuePair("client_id", "test-app"));
      nameValuePairs.add(new BasicNameValuePair("username", "user1"));
      nameValuePairs.add(new BasicNameValuePair("password", "user1"));
      nameValuePairs.add(new BasicNameValuePair("grant_type", "password"));
  
  
      try {
          final HttpPost post = new HttpPost("http://localhost:8080/auth/realms/myrealm/protocol/openid-connect/token");
          post.setEntity(new UrlEncodedFormEntity(nameValuePairs));
          post.setHeader("Accept", "application/json");
          post.setHeader("Content-type", "application/x-www-form-urlencoded");
  
          final CloseableHttpResponse response = client.execute(post);
  
          final int statusCode = response.getStatusLine().getStatusCode();
  
          System.out.println(String.format("Result: %d", statusCode));
  
          if (statusCode != 200) {
              System.out.println("Something went wrong");
              return null;
          }
  
          final String responseTxt = EntityUtils.toString(response.getEntity());
          final JSONObject json = new JSONObject(responseTxt);
  
          final String accessToken = json.getString("access_token");
          return accessToken;
      } finally {
          try {
              client.close();
          } catch (final IOException exception) {
              exception.printStackTrace();
          }
      }
  }
  </code></pre>
  
  <p>This seems to work as I get a response code 200 and the access token in the body.</p>
  
  <p><strong>Step 2: Access the protected web service</strong></p>
  
  <p>The web service is running at <code>http://127.0.0.1:8090/test</code>.</p>
  
  <p>I'm using the following code to access it (<code>accessToken</code> is the access token from previous step):</p>
  
  <pre><code>    final String targetUrl = "http://127.0.0.1/test";
      final CloseableHttpClient client = HttpClients.createDefault();
      final HttpGet get = new HttpGet(targetUrl);
      get.setHeader("Authorization", String.format("Bearer%s", accessToken));
      final CloseableHttpResponse response = client.execute(get);
      final int statusCode = response.getStatusLine().getStatusCode();
      System.out.println(String.format("Result: %d", statusCode));
      client.close();
  </code></pre>
  
  <p>When I do this, I get the login page of KeyCloak as a response, not the response of the web service.</p>
  
  <p><strong>How is the web service configured?</strong></p>
  
  <p>Here is the actual web service:</p>
  
  <pre><code>@RestController
  public class SampleRestController {
      @RequestMapping("/test")
      public String test() {
          return "Hello, world!";
      }
  }
  </code></pre>
  
  <p>Security configuration:</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
  public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
      @Autowired
      public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception {
  
          KeycloakAuthenticationProvider keycloakAuthenticationProvider
                  = keycloakAuthenticationProvider();
          keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(
                  new SimpleAuthorityMapper());
          auth.authenticationProvider(keycloakAuthenticationProvider);
      }
      @Bean
      public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
          return new KeycloakSpringBootConfigResolver();
      }
  
  
      @Bean
      @Override
      protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
          return new RegisterSessionAuthenticationStrategy(
                  new SessionRegistryImpl());
      }
  
      @Override
      public void configure(HttpSecurity http) throws Exception {
          super.configure(http);
          http.authorizeRequests()
                  .antMatchers("/test*")
                  .hasRole("user")
                  .anyRequest()
                  .permitAll();
      }
  }
  </code></pre>
  
  <p><code>application.properties</code>:</p>
  
  <pre><code>server.port = 8090
  
  spring.main.allow-bean-definition-overriding=true
  
  
  keycloak.realm = myrealm 
  keycloak.auth-server-url = http://127.0.0.1:8080/auth
  keycloak.ssl-required = external
  keycloak.resource = test-app
  keycloak.public-client=true
  keycloak.security-constraints[0].authRoles[0]=user
  keycloak.security-constraints[0].securityCollections[0].patterns[0]=/test/*
  </code></pre>
  
  <p>What do I need to change in order to get "Hello, world!" response when I send a request with the access token in the header?</p>
  
  <p><strong>Update 1:</strong> I found one part of the problem -- wrong configuration of the client. It should be <code>bearer only</code>.</p>
  
  <p><a href="https://i.stack.imgur.com/LlKwT.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/LlKwT.png" alt="Screenshot"></a></p>
  
  <p>But now I'm getting the response <code>Bearer-only applications are not allowed to initiate browser login</code>.</p>
  
  <p><strong>Update 2:</strong> With the following service configuration, it works.</p>
  
  <pre><code>server.port = 8090
  spring.main.allow-bean-definition-overriding=true
  keycloak.realm = myrealm
  keycloak.resource = test-app
  keycloak.auth-server-url = http://127.0.0.1:8080/auth
  keycloak.bearer-only = true
  keycloak.ssl-required = external
  keycloak.principal-attribute = preferred_username
  </code></pre>