At least one mapping is required erro in Spring - spring

Here's a problem: I would like to protect a URI until authorized with some third-party OAuth2. Based on http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/config/annotation/web/configuration/EnableOAuth2Client.html, I have these:
#Configuration
#EnableOAuth2Client
public class OAuth2Client extends OAuth2ClientConfiguration {
#Bean
public Filter filter() {
DelegatingFilterProxy f = new DelegatingFilterProxy();
f.setTargetBeanName("oauth2ClientContextFilter");
return f;
}
#Resource
#Qualifier("oauth2ClientContextFilter")
private OAuth2ClientContextFilter oauth2ClientContextFilter;
#Resource
#Qualifier("accessTokenRequest")
private AccessTokenRequest accessTokenRequest;
#Bean
public OAuth2ProtectedResourceDetails remote() {
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
details.setUserAuthorizationUri("http://localhost2/oauth/authorize");
return details;
}
#Bean
public OAuth2RestOperations restTemplate() {
return new OAuth2RestTemplate(remote(), new DefaultOAuth2ClientContext(
accessTokenRequest));
}
}
And
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
// Empty for now...
}
And finally
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
super.configure(auth);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers().antMatchers("/protectedUri").and()
.authorizeRequests().requestMatchers()
.hasRole("#oauth2.hasScope('read')");
}
}
But this gives:
java.lang.IllegalStateException: At least one mapping is required
(i.e. authorizeRequests().anyRequest.authenticated())
I've tried quite a few combinations of the HttpSecurity builder to no avail - any help, or is this approach entirely off base?

is this approach entirely off base?
Yes. An empty ResourceServerConfigurerAdapter isn't going to help you. You should configure the protected paths, e.g.
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/protectedUri").authenticated();
}
(and leave out your WebSecurityConfigurerAdapter).
The client configuration at the top looks wrong too, but it's not relevant to the protected resource (start a new question if you want to know how to configure the client).

Related

Spring Security does not intercept requests

I have a legacy application in which I have added Spring Web MVC libraries in order to expose a new Rest API.
I am struggling integrating spring-security in order to intercept the incoming requests. I have set up a security configuration class
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
and a security application initializer
public class SecurityWebApplicationInitializer extends
AbstractSecurityWebApplicationInitializer {
}
following relevant guides.
Using debugger I verified that during initializing my configuration class is loaded. My problem is that my requests are not intercepted as expected.
Since you're already using Spring MVC, go to your class that initializes your application. If you're using Java Config, it most likely extends AbstractAnnotationConfigDispatcherServletInitializer.
Add your SecurityConfig to its "root config classes":
public class MySpringMmvcInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
...
#Override
protected abstract Class<?>[] getRootConfigClasses() {
return new Class[] { ..., SecurityConfig.class};
}
}
I think you forgot the #configuration annotation, try this
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}

PrincipalExtractor and AuthoritiesExtractor doesn't hit

I have a project with Spring security and Oauth2.
On the resource server I have the following configuration:
#Configuration
public class SecurityConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(final HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests().antMatchers("/info", "/health", "/h2-console/**").permitAll()
.anyRequest().authenticated()
.and().headers().frameOptions().disable();
}
}
I have the following extractors:
#Component
public class InsurancePrincipalExtractor implements PrincipalExtractor {
#Override
public Object extractPrincipal(Map<String, Object> map) {
return map.get("username");
}
}
#Component
public class InsuranceAuthoritiesExtractor implements AuthoritiesExtractor {
#Override
public List<GrantedAuthority> extractAuthorities(Map<String, Object> map) {
//Logic
}
I set the user-info-uri: http://localhost:8081/uaa/v1/me
The problem is that it does not hit my extractor methods at runtime, so nothing happens. As I know I just need to annotate it with the #Component and the Spring boot and will use it auto.
UPDATE:
Solution founded.
I had to add this to my configuration as well:
#Bean
protected ResourceServerTokenServices resourceServerTokenServices(ResourceServerProperties sso,
OAuth2ClientContext oauth2ClientContext,
UserInfoRestTemplateFactory restTemplateFactory) {
UserInfoTokenServices services = new UserInfoTokenServices(sso.getUserInfoUri(), sso.getClientId());
services.setRestTemplate(restTemplateFactory.getUserInfoRestTemplate());
services.setTokenType(sso.getTokenType());
return services;
}

Spring Security OAuth2 Protected Resource not actually protected... Filters Not Working?

Literally able to hit the endpoint: http://localhost:8080/oauth2-password/helloworld and still get the String "Hello World!".. Check out my configurations below and please tell me why. This is extremely frustrating.
AUTHORIZATION SERVER
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
#Autowired
AuthenticationManager authenticationManager;
#Primary
#Bean
InMemoryTokenStore tokenStore() {
return new InMemoryTokenStore();
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(this.authenticationManager).tokenStore(this.tokenStore());
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.checkTokenAccess("isAuthenticated()");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.resourceIds("app")
.authorizedGrantTypes("password")
.scopes("read", "write", "trust")
.refreshTokenValiditySeconds(20000)
.accessTokenValiditySeconds(600);
}
}
RESOURCE SERVER
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
#Autowired
AuthenticationManager authManager;
#Autowired
TokenStore tokenStore;
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/helloworld/**").authenticated();
}
#Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("app").tokenStore(this.tokenStore).authenticationManager(this.authManager);
}
}
WEB SECURITY CONFIG
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Wow, surprised no one was able to catch this one. Extremely poorly documented but found the answer after days of searching.
For anyone who comes this way and finds they are configuring the ResourceServer, AuthorizationServer, and WebSecurityConfigurerAdapter correctly yet you are still hitting the endpoint perfectly fine as if the freaking filter weren't even alive, here is the answer:
Add an #Configuration annotated class in your classpath that implements AbstractSecurityWebApplicationInitializer. Call the class SecurityWebAppInitializer or whatever you would like that makes senes. Make sure to override all the methods and just leave them as their default implementations. Make sure you register this class into your Spring context (along with the other config classes).
Re-compile, re-start the server etc...
Boom. Works, just like that. Hit an endpoint and was unauthorized with a 401.
What this Abstract class does is register the DelegatingFilterProxy to use the springSecurityFilterChain before any other registered Filter. UGH. Something done so easily in XML when you register springSecurityFilterChain.

Spring security form logging and outh2 in same app

I have written a sample spring application which have some rest services protected using spring-security-oauth2. Now I want to move these services to the original application which uses spring security form login.
In the original application I want rest services to be protected from spring-security-oauth2 and other spring controllers to be protected using a form login. What I want to know is, is this approach is right or wrong, if right, how could I complete this action.
This is Sample app codes, which uses ouath2,
#Configuration
#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService; // Is this really needed?
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
#Configuration
public class OAuth2ServerConfiguration {
private static final String RESOURCE_ID = "restservice";
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
// #formatter:off
resources.resourceId(RESOURCE_ID);
// #formatter:on
}
#Override
public void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests().antMatchers("/test").not().permitAll();
http.authorizeRequests().antMatchers("/test").authenticated();
}
}
#Configuration
#EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private TokenStore tokenStore = new InMemoryTokenStore();
#Autowired
// #Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// #formatter:off
endpoints.tokenStore(this.tokenStore).authenticationManager(this.authenticationManager);
// #formatter:on
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// #formatter:off
clients.inMemory().withClient("clientapp").authorizedGrantTypes("password", "refresh_token").authorities("USER")
.scopes("read", "write").resourceIds(RESOURCE_ID).secret("123456");
// #formatter:on
}
#Bean
#Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setSupportRefreshToken(true);
tokenServices.setTokenStore(this.tokenStore);
return tokenServices;
}
}
}
Here is a part of the original app configuration.
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class MyStaysureSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.inMemoryAuthentication().withUser("mycompany").password("mypsswd").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/rest/*", "/api-docs/**").permitAll().antMatchers("/**").authenticated().and().formLogin().defaultSuccessUrl("/dashboard").and().csrf().disable();
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
Spring Security is built on an ordered list of filter chains, and for each request the first one with a matching path handles the authentication. You have 3 filter chains in your combined app, one created by #EnableAuthorizationServer (with default order=0), one created by #EnableResourceServer (with default order=3), and one created by your MyStaysureSecurityConfiguration (also with order=0). You aren't allowed to have 2 filters with the same order so you need to re-arrange them and give them request matchers that make sense for your use case. Maybe you didn't need the #EnableAuthorizationServer anyway (it was unclear from the question)? In any case it is pretty simple - you have 2 choices (roughly):
exclude the oauth2 resources from the request matchers in your MyStaysureSecurityConfiguration and allow them to be handled by the resource server filter.
re-order the resource server filter to a lower order and give it a request matcher that only matches the oauth2 resources.

Spring Security PreAuthorize Custom Method Bean resolver is not registered?

Im just learning Spring, going through tutorials and testing possibilities. One of my goals is to secure a Service Method using a Custom Method and the PreAuthorize annotation. Unfortunaly the Bean holding the custom Method cannot be resolved and I dont know why. Maybe someone can see the error at first sight.
Bean holding the custom Method:
#Component("mySecurityService")
public class MySecurityService {
public boolean hasPermission() {
return true; //simple implementation just to look if has permission is called
}
}
Service to be Secured:
public interface OrderService {
#PreAuthorize("#mySecurityService.hasPermission()")
public AllOrdersEvent requestAllOrders(RequestAllOrdersEvent requestAllCurrentOrdersEvent);
public OrderDetailsEvent requestOrderDetails(RequestOrderDetailsEvent requestOrderDetailsEvent);
public OrderStatusEvent requestOrderStatus(RequestOrderStatusEvent requestOrderStatusEvent);
public OrderCreatedEvent createOrder(CreateOrderEvent event);
public OrderUpdatedEvent setOrderPayment(SetOrderPaymentEvent setOrderPaymentEvent);
public OrderDeletedEvent deleteOrder(DeleteOrderEvent deleteOrderEvent);
}
Java Security Config:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("letsnosh").password("noshing").roles("USER");
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Bean(name = "mySecurityService")
MySecurityService createSecurityService(){return new MySecurityService();}
#Override
protected void configure(HttpSecurity http) throws Exception {
/*
http.authorizeUrls()
.antMatchers("/aggregators*//**//**").hasRole("USER")
.anyRequest().anonymous()
.and()
.httpBasic();
*/
}
}
Error:
No bean resolver registered in the context to resolve access to bean 'mySecurityService'
Hello I solved the problem. It was connected to the Version of Spring Security.
I got the Version from the official Spring Rest Tutotrial : 3.2.0.M2
In this version I had to declare the Security Context as follows:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("letsnosh").password("noshing").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeUrls()
.antMatchers("/aggregators/**").hasRole("USER")
.anyRequest().anonymous()
.and()
.httpBasic();
}
}
Here the error was thrown.
But using a newer Version of Spring Security: 3.2.5.RELEASE
I could declare the Config this way:
#EnableWebSecurity
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeUrls()
.antMatchers("/aggregators*//**//**").hasRole("USER")
.anyRequest().anonymous()
.and()
.httpBasic();
}
And the bean could be resolved, using either #Component Annotaions directly on the MySecurityService class or #Bean annotations on a config class method which returns a MySecurityService instance.

Resources