title: Keycloak: Failed to load URLs in Spring Boot Application
body: <p>I'm currently trying to develop a Spring Boot Rest Api which is secured with keycloak.</p>
  
  <p>I get an error when I try to call a api which the user has to be identify.</p>
  
  <p>The error message is following:</p>
  
  <pre><code>2020-04-10 16:09:00.324  WARN 44525 --- [nio-8080-exec-7] 
  o.keycloak.adapters.KeycloakDeployment   : Failed to load URLs from 
  https://{{keycloakserver}}.de/auth/realms/{{realm}}/.well-known/openid-configuration
  
  java.lang.RuntimeException: java.lang.RuntimeException: Stub!
  at org.keycloak.adapters.KeycloakDeployment.getClient(KeycloakDeployment.java:327) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.KeycloakDeployment.getOidcConfiguration(KeycloakDeployment.java:219) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.KeycloakDeployment.resolveUrls(KeycloakDeployment.java:178) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.KeycloakDeployment.getRealmInfoUrl(KeycloakDeployment.java:232) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.rotation.AdapterTokenVerifier.createVerifier(AdapterTokenVerifier.java:107) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.rotation.AdapterTokenVerifier.verifyToken(AdapterTokenVerifier.java:47) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticateToken(BearerTokenRequestAuthenticator.java:103) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.BearerTokenRequestAuthenticator.authenticate(BearerTokenRequestAuthenticator.java:88) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:67) [keycloak-adapter-core-9.0.2.jar:9.0.2]
  at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter.attemptAuthentication(KeycloakAuthenticationProcessingFilter.java:154) [keycloak-spring-security-adapter-9.0.2.jar:9.0.2]
  at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:212) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.java:96) [keycloak-spring-security-adapter-9.0.2.jar:9.0.2]
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:97) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.10.RELEASE.jar:5.1.10.RELEASE]
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) [spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
  </code></pre>
  
  <p>I don't know what <code>Failed to load URLs from</code> means. I can access this side when I click on the link and the configuration file is shown.</p>
  
  <p><strong>Setup</strong></p>
  
  <p>Keycloak:</p>
  
  <p>Keycloak Server is in the web, so no localhost.</p>
  
  <p>I have a realm (test-realm) created<br /> 
  I have a client (test-client) created<br />
  I have a user (test-user) created<br />
  I have a role in the client (ADMIN) created<br />
  I have assigned the role (ADMIN) to the user (test-user)<br /></p>
  
  <p>The client protocol for the client is <code>openid-connect</code> and the access type is <code>confidental</code>.</p>
  
  <p>Spring Boot:</p>
  
  <p>The Spring Boot rest application is running on localhost:8080.</p>
  
  <p>I added in the <code>applications.properties</code> following keycloak configs.</p>
  
  <pre><code>keycloak.realm={{test-realm}}
  keycloak.auth-server-url = https://{{keycloakserver}}.de/auth
  keycloak.resource = {{test-client}}
  keycloak.ssl-required=external
  keycloak.bearer-only=true
  keycloak.principal-attribute=preferred_username
  keycloak.use-resource-role-mappings = true
  </code></pre>
  
  <p>To make sure the test-user can only access one api call I use following config.</p>
  
  <pre><code> @Override
      protected void configure(HttpSecurity http) throws Exception {
          super.configure(http);
          http.authorizeRequests()
                  .antMatchers("/getTest")
                  .hasRole("ADMIN")
                  .anyRequest()
                  .authenticated();
      }
  </code></pre>
  
  <p><strong>Tests</strong></p>
  
  <p>When I call <code>http://localhost:8080/getTest</code> with Postman I get a correct <code>401 Unauthorized</code>.</p>
  
  <p>Then I called the same URL with <code>Authorization</code> and the access token of the logged in <code>test-user</code>.</p>
  
  <p>With this second call I get the error message above.</p>
  
  <p>Does anybody know anything about this?
  If I missed a config value that you need to know, just ask.</p>
  
  <p>Thanks for your help.</p>
  
  <p>Edit:</p>
  
  <p>SecurityConfig.java</p>
  
  <pre><code>import org.keycloak.adapters.KeycloakConfigResolver;
  import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
  import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
  import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
  import org.keycloak.adapters.springsecurity.KeycloakSecurityComponents;
  import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
  import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.ComponentScan;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.context.annotation.Primary;
  import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
  import org.springframework.security.core.session.SessionRegistryImpl;
  import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
  import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
  
  /**
   * Created by johannes on 07.04.20 for test App.
   */
  @EnableWebSecurity
  @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
  @Configuration
  @KeycloakConfiguration
  public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
  
      @Autowired
      public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
          KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
          auth.authenticationProvider(keycloakAuthenticationProvider);
      }
  
      @Bean
      @Override
      protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
          return new RegisterSessionAuthenticationStrategy(
                  new SessionRegistryImpl());
      }
  
      @Bean
      @Primary
      public KeycloakConfigResolver keycloakConfigResolver(KeycloakSpringBootProperties properties) {
          return new CustomKeycloakSpringBootConfigResolver(properties);
      }
  
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          super.configure(http);
          http.authorizeRequests()
                  .antMatchers("/getTest")
                  .hasRole("ADMIN")
                  .anyRequest()
                  .authenticated();
      }
  }
  </code></pre>
  
  <p>CustomKeycloakSpringBootConfigResolver:</p>
  
  <pre><code>import org.keycloak.adapters.KeycloakDeployment;
  import org.keycloak.adapters.KeycloakDeploymentBuilder;
  import org.keycloak.adapters.spi.HttpFacade;
  import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
  import org.keycloak.adapters.springboot.KeycloakSpringBootProperties;
  import org.springframework.context.annotation.Configuration;
  
  /**
   * Created by johannes on 10.04.20 for test App.*/
  @Configuration
  public class CustomKeycloakSpringBootConfigResolver extends KeycloakSpringBootConfigResolver {
          private final KeycloakDeployment keycloakDeployment;
      public CustomKeycloakSpringBootConfigResolver(KeycloakSpringBootProperties properties) {
  
          keycloakDeployment = KeycloakDeploymentBuilder.build(properties);
      }
  
      @Override
      public KeycloakDeployment resolve(HttpFacade.Request facade) {
          return keycloakDeployment;
      }
  }
  </code></pre>
  
  <p>TestController.java (this is just the test getter):</p>
  
  <pre><code>  @GetMapping("/getTest")
      public @ResponseBody ResponseEntity getTest() {
  
          return ResponseEntity.status(ResponseValues.ITEMDELETEFAILED.getResponseCode()).body(ResponseValues.ITEMDELETEFAILED.getResponseMessage());
  
      }
  </code></pre>
  
  <p>Request was made with postman, this is the code:</p>
  
  <pre><code>curl --location --request GET 'http://localhost:8080/getTest' \
  --header 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUI...' \
  --header 'Cookie: JSESSIONID=41E8E82178FA181817...'
  </code></pre>