How to exclude a URL when usinf PCF SSO service with EnableOAuth2Sso annotation? - spring-boot

I am using Angular and Spring Boot to build a Single Page app with Rest API. Here is my configuration:
#SpringBootApplication
#EnableOAuth2Sso
public class AppConfig extends SpringBootServletInitializer implements ApplicationContextAware {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AppConfig.class);
}
public static void main(String[] args) {
ApplicationContext appContext = SpringApplication.run(AppConfig.class);
context = appContext;
}
#Configuration
protected static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/healthcheck", "/").permitAll()
.antMatchers("/api/**").authenticated()
.anyRequest().authenticated();
}
}
}
The SSO service I am using is provided by Pivotal Cloud Foundry[PCF]. Everything was fine before I included
SecurityConfig
class. As soon as the app is loaded, user is redirected to the SSO login page and then redirected back to the app. But I need to exclude the "healthcheck" URL from authentication. That is why I included the SecurityConfig class. But now the SSO Authentication is not working at all. I could only reach /healthcheck.
I followed this example https://spring.io/guides/tutorials/spring-boot-oauth2/
Can someone please let me know what is wrong with my code?
Thanks.

I figured it out. I had to move my EnableOAuth2Sso to the WebSecurityConfigurerAdapter. Like this:
#SpringBootApplication
public class AppConfig extends SpringBootServletInitializer implements ApplicationContextAware {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(AppConfig.class);
}
public static void main(String[] args) {
ApplicationContext appContext = SpringApplication.run(AppConfig.class);
context = appContext;
}
#Configuration
#EnableOAuth2Sso
protected static class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/healthcheck", "/").permitAll()
.antMatchers("/api/**").authenticated()
.anyRequest().authenticated();
}
}
}

Related

Couldn't access jpg file under resources/static folder

I couldn't access the image under the resources/static folder. I'm using Spring Boot version 2.112.
I also tried adding spring.resources.static-locations in the properties file but still can't access the .jpg file from the resources/static/image folder. Any reason why?
#Configuration
public class WebConfiguration extends WebMvcConfigurationSupport {
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/", "classpath:/image/");
}
Well, you may try https://stackoverflow.com/a/66361120/15215155. Most of time is about spring boot default security configuration.
Edit: Little edit here since it would be too much for comments.
Tackling the problem from another angle. Is there any specific feature you need from WebMvcConfigurationSupport?? If not, why not trying WebSecurityConfigurer for the resources handlers and WebSecurityConfigurerAdapter for the security config?.
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**", "/js/**")
.addResourceLocations("classpath:/static/", "classpath:/resources/static/");
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/static/images/");
}
}
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/css/**", "/js/**", "/image/**"").permitAll()
}
}

url based custom mutiple auth providers calls always one provider only

I have configured multiple custom auth providers,using auth2 and spring boot, but it always executes the CustomInternalAuthenticationProvider only.can you please explain the how to apply ant matcher rules in order?i have used two WebSecurityConfigurerAdapter classes and one is orderded and one is default.guide me on how to handle the antmatcher rules properly?
#EnableResourceServer
#EnableWebSecurity
public class WebSecurityConfig{
#Autowired
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("#order");
http.antMatcher("/../main/**")
.requestMatchers()
.antMatchers("/","/login*", "/oauth/authorize**","/exit","**/logout")
.and().authenticationProvider(daoInternalAuthenticationProvider())
.formLogin().loginPage("/login")
;
}
#Bean
public AuthenticationProvider daoInternalAuthenticationProvider() throws Exception {
return new CustomInternalAuthenticationProvider();
}
}
#Configuration
public static class ApiTokenSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("default");
http.antMatcher("/../user/**")
.requestMatchers()
.antMatchers("/","/login*", "/oauth/authorize**","/exit","**/logout")
.and() .authenticationProvider(daoExternalAuthenticationProvider())
.formLogin().loginPage("/login")
;
}
#Bean
public AuthenticationProvider daoExternalAuthenticationProvider() throws Exception {
return new CustomExternalAuthonticationProvider();
}
}

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();
}
}

How to configure oAuth2 when Authorization Server is also the Resource server

I'm trying to setup a very basic oAuth2 authentication in spring boot 2.x.x using either authorization code grant or implicit grant but I can't seem to access the Resource server (which resides in the same spring boot app as the Authorization server) after the token is obtained.
Following is the configuration of WebSecurityConfigurerAdapter
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private static final String[] IGNORE_URIS = {
"/swagger-resources/**",
"/swagger-ui.html",
"/v2/api-docs",
"/webjars/**",
"/resources/**",
"/h2-console/**",
"/common/**",
"/configuration/ui",
"/configuration/security",
"/error"
};
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers(IGNORE_URIS);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/product/**")
.hasAnyRole("ADMIN").and()
.httpBasic().and().formLogin().and().authorizeRequests().anyRequest().authenticated();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("{noop}admin").roles("ADMIN");
}
#Bean
public PasswordEncoder bCrypt() {
return new BCryptPasswordEncoder();
}
And the AuthorizationServerConfigurerAdapter
#Configuration
#EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
private final AuthenticationManager authenticationManager;
#Autowired
public AuthorizationServerConfiguration(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager();
}
#Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("my-client-id")
.authorizedGrantTypes("authorization_code", "implicit")
.authorities("ADMIN")
.scopes("all")
.resourceIds("product_api")
.secret("{noop}secret").redirectUris("https://google.com").accessTokenValiditySeconds(0);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("permitAll()");
}
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}
So far so good. I am able to reach the default Spring login page by typing the following Url in the browser.
http://localhost:8080/oauth/authorize?response_type=token&client_id=my-client-id&redirect_uri=https://google.com
Then The login page shows up and I enter my credentials.
After I log in I can then grant access to "my-client-id" app.
Eventually after I approve the app I can see the newly generated access token in the URL bar of the browser which is something like this.
https://www.google.com/#access_token=f2153498-6a26-42c6-93f0-80825ef03b16&token_type=bearer&scope=all
My question is that All of this flow won't work when I also configure a Resource Server.
#EnableResourceServer
#Configuration
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId("product_api");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.antMatchers("/**")
.and().authorizeRequests()
.antMatchers("/**").permitAll();
}
}
What am I doing wrong? When I try to access the oauth/authorize url as before I get the following:
Why? How can one access the login page and retrieve the token? What Am I missing?
You need to use
#Order
Annotation to specify order for WebMvc and ResourceServer classes
#EnableWebSecurity
#Configuration
#Order(1)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
...
}
and for Resource Server
#EnableResourceServer
#Configuration
#Order(2)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
...
}
If you want to see workable example, you can check it here https://github.com/alex-petrov81/stackoverflow-answers/tree/master/auth-server-also-resource
I've created it from your code example.

Spring OAuth #EnableResourceServer preventing login page from OAuth server

Browser Response for localhost:9999/uaa/oauth/authorize?response_type=code&client_id=acme&redirect_uri=http://example.com is 302 Found, but response for localhost:9999/uaa/login is 401 Unauthorized.
I could get the login token prior to adding the #EnableResourceServer. I am using Spring boot and extending WebSecurityConfigurerAdapter to use authentication Manager with data source. When I tried to add a ResourceServerConfigurerAdapter it wouldn't build. What is the easiest way to allow the login page?
#SpringBootApplication
#RestController
#EnableResourceServer
public class OAuthSvcApplication extends WebMvcConfigurerAdapter {
private static final Logger log = LoggerFactory.getLogger(OAuthSvcApplication.class);
#RequestMapping("/user")
public Principal user(Principal user) {
return user;
}
public static void main(String[] args) {
SpringApplication.run(OAuthSvcApplication.class, args);
}
}
#Configuration
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureAuth(AuthenticationManagerBuilder auth,DataSource dataSource, Environment env)
throws Exception {
auth.jdbcAuthentication().dataSource(dataSource);
}
#Configuration
#EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private DataSource dataSource;
#Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception {
endpoints.authenticationManager(authenticationManager);
}
#Override
public void configure(AuthorizationServerSecurityConfigurer security)
throws Exception {
security.checkTokenAccess("hasAuthority('USER')");
}
#Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()
.withClient("acme")
.secret("acmesecret")
.authorizedGrantTypes("authorization_code",
"refresh_token", "password").scopes("openid");
}
}
}
SpringSecurityFilterChain should always be ordered before other filters.
If you want to add your own authentication for all or some endpoints the best thing to do is add your own WebSecurityConfigurerAdapter with lower order. Modifying the WebSecurityConfigurerAdapter subclass as follows allows the ResourceServer to work with a jdbc authentication mgr:
#Configuration
#Order(-10)
protected static class LoginConfig extends WebSecurityConfigurerAdapter {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private DataSource dataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.formLogin().loginPage("/login").permitAll()
.and()
.requestMatchers().antMatchers("/login", "/oauth/authorize", "/oauth/confirm_access")
.and()
.authorizeRequests().anyRequest().authenticated();
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager).jdbcAuthentication().dataSource(dataSource);
}
}

Resources