简体   繁体   中英

keycloak (spring boot) Not authenticating REST endpoint

I am trying to play around with open source user management service like keycloak. Building a angularJs app that will be send HTTP request to REST endpoint secured by keycloak. I am using spring boot on the backend. I am able to call the endpoint and get result which should not be possible since it should block request coming from unauthorized source.

These are the two links that I followed

  1. keycloak with angular and spring boot

2. Github link to keycloak example

Controller which consists of REST endpoint that the user will call.

@RequestMapping(value = "/api/getSample")
public test welcome() {
    return new test("sample");
}

@RequestMapping(value = "/check/test")
public test welcome2() {
    return new test("test");
}

Spring boot application with CORS

@SpringBootApplication
public class Application 
{
    public static void main( String[] args )
    {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/api/*", config);

        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

Application properties files for

server.port = 8090

keycloak.realm = demo
keycloak.auth-server-url = http://localhost:8080/auth
keycloak.ssl-required = external
keycloak.resource = tutorial-backend
keycloak.bearer-only = true
keycloak.credentials.secret = 111-1111-111-111
keycloak.use-resource-role-mappings = true
keycloak.cors= true

keycloak.securityConstraints[0].securityCollections[0].name = spring secured api
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /api

keycloak.securityConstraints[0].securityCollections[1].name = insecure stuff
keycloak.securityConstraints[0].securityCollections[1].authRoles[0] = user
keycloak.securityConstraints[0].securityCollections[1].patterns[0] = /check

There are two test case

  1. Making REST call without logging in. In this case I am able to get the result back. This should not be the case, I get should blocked(get 401 error).

  2. Making REST call when logged in. I am able to call the api/getSample and this is the correct behavior. However when I call check/test I get XMLHttpRequest cannot load http://localhost:8090/check/test. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 403. XMLHttpRequest cannot load http://localhost:8090/check/test. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 403.

1)

I don't know how exactly your test looks like, but maybe the system thinks that you are still logged in? You could try to delete your cookies to make sure that there's no access token saved.

Another Option could be that Spring Boot doesn't recognize the Keycloak Adapter and therefore doesn't secure the access. You mainly configure the Adapter by adding the keycloak-spring-boot-adapter and keycloak-tomcat8-adapter dependencies ( more details here ).

2)

It looks like the CORS is not configured properly. You could consider this implementation for the configuration ( more details here ):

@Bean
FilterRegistrationBean corsFilter(
        @Value("${tagit.origin:http://localhost:9000}") String origin) {
    return new FilterRegistrationBean(new Filter() {
        public void doFilter(ServletRequest req, ServletResponse res,
                             FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;
            String method = request.getMethod();
            // this origin value could just as easily have come from a database
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Methods",
                    "POST,GET,PUT,DELETE");
            response.setHeader("Access-Control-Max-Age", Long.toString(60 * 60));
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader(
                    "Access-Control-Allow-Headers",
                    "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization");
            if ("OPTIONS".equals(method)) {
                response.setStatus(HttpStatus.OK.value());
            }
            else {
                chain.doFilter(req, res);
            }
        }

        public void init(FilterConfig filterConfig) {
        }

        public void destroy() {
        }
    });
}

You haven't added the Spring Boot Keycloak Adapter dependency in your pom.xml.

For 2. You haven't configured CORS for /check (only for /api)

 <dependency>
      <groupId>org.keycloak</groupId>
      <artifactId>keycloak-spring-boot-adapter</artifactId>
      <version>${keycloak.version}</version>
  </dependency>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM