4

I'm working on Spring Boot application with configured SSO/OAuth2 security. Authentication works fine for my rest controllers and now I need to secure my Apache Camel route with a rest endpoint.

As I understand there are several ways how to do it:

  1. By adding auth processor to my route
  2. By adding policy (SpringSecurityAuthorizationPolicy) to my route
  3. By handlers option to jetty endpoint

I'm trying to do it by adding new auth processor to my rest endpoint but I stuck on this exception:

org.springframework.security.oauth2.common.exceptions.OAuth2Exception: No AuthenticationProvider found for org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken

During debugging I see that org.springframework.security.authentication.ProviderManager.getProviders() contains only one provider AnonymousAuthenticationProvider so probably I have to register appropriate provider...

Can someone help me to find the right way to solve this problem please?

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().authorizeRequests().anyRequest().permitAll();
  }

  @Configuration
  @EnableResourceServer
  protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Value("${oauth2.token.endpoint}")
    private String tokenEndpoint;

    @Bean
    public ResourceServerTokenServices tokenService() {
      RemoteTokenServices tokenServices = new RemoteTokenServices();
      tokenServices.setClientId("clientId");
      tokenServices.setClientSecret("clientSecret");
      tokenServices.setCheckTokenEndpointUrl(tokenEndpoint);
      return tokenServices;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
      http.authorizeRequests().anyRequest().authenticated();
    }
  }

}

@Configuration
public class EmbeddedServerRoute {
  @Bean
  public RoutesBuilder embeddedServer() {
    return new RouteBuilder() {
      @Override
      public void configure() throws Exception {
        restConfiguration().component("jetty").port("8081").bindingMode(RestBindingMode.json);
      }
    };
  }
}


@Component
public class RestTestRoute extends RouteBuilder {

  @Autowired
  private AuthProcessor authProcessor;

  @Override
  public void configure() throws Exception {
    from("rest:get:/test").process(authProcessor).to("mock:end").end();
  }
}


@Component
public class AuthProcessor implements Processor {

  @Autowired
  private AuthenticationManager authenticationManager;

  private TokenExtractor tokenExtractor = new BearerTokenExtractor();

  private AuthenticationDetailsSource<HttpServletRequest, ?> authenticationDetailsSource = new OAuth2AuthenticationDetailsSource();

  @Override
  public void process(Exchange exchange) throws Exception {
    HttpServletRequest request = exchange.getIn().getBody(HttpServletRequest.class);
    Subject subject = new Subject();
    Authentication auth = getAuth(request);
    subject.getPrincipals().add(auth);
    exchange.getIn().setHeader(Exchange.AUTHENTICATION, subject);
  }

  private Authentication getAuth(HttpServletRequest request) throws OAuth2Exception {
    Authentication authentication = null;
    try {
      authentication = tokenExtractor.extract(request);
      if (authentication != null) {
        request.setAttribute(OAuth2AuthenticationDetails.ACCESS_TOKEN_VALUE, authentication.getPrincipal());

        if (authentication instanceof AbstractAuthenticationToken) {
          AbstractAuthenticationToken needsDetails = (AbstractAuthenticationToken) authentication;
          needsDetails.setDetails(authenticationDetailsSource.buildDetails(request));
        }
        return authenticationManager.authenticate(authentication);
      }
    } catch (Exception e) {
      throw new OAuth2Exception(e.getMessage());
    }
    throw new OAuth2Exception("Not Authorized to view resource");
  }

}

1 Answer 1

3

As a final solution I decided to use Spring Boot embedded servlet container instead of Apache Camel rest component. So it could be easily secured by Spring Security. This could be done by creating additional beans:

  @Bean
  public ServletRegistrationBean servletRegistrationBean() {
    SpringServerServlet serverServlet = new SpringServerServlet();
    ServletRegistrationBean regBean = new ServletRegistrationBean(serverServlet, "/camel/*");
    Map<String, String> params = new HashMap<>();
    params.put("org.restlet.component", "restletComponent");
    regBean.setInitParameters(params);
    return regBean;
  }

  @Bean
  public Component restletComponent() {
    return new Component();
  }

  @Bean
  public RestletComponent restletComponentService() {
    return new RestletComponent(restletComponent());
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.