Change default success URL in Spring Security using Vaadin 21 - spring

currently I am playing around with Vaadin 21 and especially with the better integration of Spring Security.
I followed the Spring security tutorial for Vaadin 21 and flow on https://vaadin.com/docs/latest/flow/integrations/spring/view-based-access-control . However I need to change the defaultSuccesUrl/successUrl from "" to "/application", because currently after login I will always get routed to "/" which soes not exist. I already played around a lot but I was not successfully.
This is the configure method of my Security config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.rememberMe().alwaysRemember(false);
// Current
http.authorizeRequests().antMatchers("/VAADIN/**").permitAll();
http.authorizeRequests().antMatchers("/services/**").permitAll();
// Set the login processing url
http.formLogin().loginProcessingUrl(ApplicationUrl.APP_LOGIN_PROCESSING_URL);
// Set the default success Url
http.formLogin().defaultSuccessUrl(ApplicationUrl.APP);
// Set the default failure Url
http.formLogin().failureUrl(ApplicationUrl.APP_LOGIN_FAILURE_URL);
super.configure(http);
// This is important to register your login view to the
// view access checker mechanism:
setLoginView(http, LoginView.class);
}
I already put http.formLogin().loginProcessingUrl(ApplicationUrl.APP_LOGIN_PROCESSING_URL); after super.configure(http) and changed to http.formLogin().successForwardUrl(ApplicationUrl.APP); but nothing worked.
Hopefully someone can give me a hint how to solve this. In Vaadin 14 this was no problem, because there, you must configure it "manually".
Thanks,
Florian

I think this will work for you:
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
setLoginView(http, LoginView.class, LOGOUT_URL);
http.formLogin().defaultSuccessUrl("/foo");
}

Related

Can we load different security configuration based on Mediatype, i.e. One of REST and one for web?

I have developed a regular spring mvc application, and want to add some rest controller for developing mobile application. I have written rest controller, and multi spring security configurations.
Problem is, they are in precedence, hence both are loaded at once, and whole application breaks down.I want to use one based upon what type of request it is getting, for example, If I am requesting from Postman, Rest API security configuration should work and if we are using web, web security configuration should work.
Here is my implementation, I don't know how to achieve that, Please suggest what is the right way to doing this. As separating whole Thymeleaf and MVC controller , and moving altogether with Angular is not possible at this stage.
Please note that, we have all rest api defined in /v1/ap1/** and all other mvc part is in /**
Any comments, suggestions would be much appreciated, it is killing my days since 3 days. Thanks in advance
#Configuration
#EnableWebSecurity
public class SecurityConfig {
// ... other codes
#Configuration
#Order(1)
public static class RestAPISecurity extends WebSecurityConfigurerAdapter {
//.. other codes
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/signin/**").permitAll()
.antMatchers("/api/v1/**").hasAnyAuthority("ADMIN", "USER")
.antMatchers("/api/users/**").hasAuthority("ADMIN")
.antMatchers("/api/v1/**").authenticated()
.antMatchers("/login", "/logout", "/register", "/j_spring_security_check").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(customAuthenticationEntryPoint).accessDeniedHandler(new CustomAccessDeniedHandler());
}
// .. other codes
#Configuration
#Order(2)
public static class MVCSecurityConfiguration extends WebSecurityConfigurerAdapter {
//.. other codes
// form login and other MVC stuffs
}
}
You can add a request matcher for the first spring security filter chain and every thing else goes to second chain
protected void configure(HttpSecurity http) throws Exception {
http.requestMatcher(httpServletRequest -> {
String userAgent = httpServletRequest.getHeader("User-Agent");
//If you want to check based on content type
String contentType = httpServletRequest.getContentType();
return userAgent.contains("....")
//check what value postman sends as user agent and use it
})
.sessionManagement()
....
}

SM_USER for every requests from SIteminder (Static requests as well)

Siteminder sending SM_USER (userId) back to application for all requests including static resource requests. we dont need userId in every request header except for specified Url.
Can anyone help how can avoid this in Spring boot+Siteminder configuration?
below using Siteminder filter,
#Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(siteminderFilter(), RequestHeaderAuthenticationFilter.class)
......
......
}
#Bean
public RequestHeaderAuthenticationFilter siteminderFilter() throws Exception {
RequestHeaderAuthenticationFilter filter = new RequestHeaderAuthenticationFilter();
filter.setPrincipalRequestHeader(smEmpID);
filter.setAuthenticationManager(authenticationManagerBean());
filter.setCheckForPrincipalChanges(true);
filter.setExceptionIfHeaderMissing(false);
return filter;
Thanks.
You can set DisableUserNameVars=No in your ACO and it will stop sending SM_USER
For the urls you need userid you can setup custom header with userid like HTTP_SM_USER.
Please note, as per documentation, using SM_USER inside the application is not advisable.
For few other applications (like integrating with SAP or other apps) you must have SM_USER, so there you have no escape.

Spring boot security - Actuator

I am trying to configure my application to always expose actuator end points and if config is set to say security is required then apply it to my end points for websocket connectivity
As it stands i was under the impression that ant matchers matched in order - meaning that
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/health", "/actuator", "actuator/health").permitAll();
if (authenticationRequired) {
http.authorizeRequests().antMatchers("/**").authenticated().and().httpBasic();
}
}
the above code should permit the actuator end points ALWAYS
It seems as though however this is not the case. Please can someone help describe what is wrong with my approach here.
/health and /actuator to me should be governed by permitAll()
I Fixed this using the following matchers
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/health", "/actuator/**").permitAll();
if (authenticationRequired) {
http.authorizeRequests().antMatchers("/**").authenticated().and().httpBasic();
}
}
I was missing a leading /

Spring boot security block non RestController endpoints

I have an app that is exposing a bunch of endpoints that I did not expect. For example localhost:8080/app/ returns a list of URL that among other things exposes information related to the hibernate entities.
I DO NOT want basic auth enabled as I have my own authentication configured.
But if the URL is not one that is represented by a RestController I have written then I want it to an existing forbidden page that I have.
Here is my current config but it does not prevent the unwanted endpoints:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/**").antMatchers("/v2/**").antMatchers("/webjars/**").antMatchers("/swagger-resources/**")
.antMatchers("/swagger-ui.html");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.httpBasic().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
http.authenticationProvider(new CustomAuthenticationProvider()).authorizeRequests().anyRequest().authenticated()
.antMatchers("/v2/**").permitAll().antMatchers("/webjars/**").permitAll().antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/health").permitAll();
http.rememberMe().rememberMeServices(rememberMeService).useSecureCookie(useSecureCookie);
//Show 403 on denied access
http.exceptionHandling().authenticationEntryPoint(new Forbidden());
}
So in this case localhost:8080/app/api/SearchControler/{var} should work but localhost:8080/app/ should go to my Forbidden entry point. Instead localhost:8080/app/ is going to the spring username and password page.
First off I don't know why these endpoints are even showing up when there is no RestController for them and second why is redirecting to a 403 page so difficult.
I'm not sure what config I am missing.
* EDIT *
I have also tried:
http.formLogin().and().httpBasic().disabled();
as well as:
#EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
and nothing seems to stop spring from taking over and doing whatever it feels like doing.
Try again after removing super.configure(http); in your configure(HttpSecurity http) method.
Documentation
Override this method to configure the {#link HttpSecurity}. Typically
subclasses * should not invoke this method by calling super as it
may override their * configuration. The default configuration is:
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
I think there is more configuration which you didn't show to as, but anyway:
#Override
public void configure(WebSecurity web) throws Exception {
//this is only for ignoring static resources in your app, sth that is never changed (you can cash it) and public (available for any user on the internet (ex. /js /css - sth else static img etc)
web.ignoring().antMatchers("/webjars/**").antMatchers("/swagger-resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http); this call the default configuration, if you implement this method you shouldn't call the default one
http.httpBasic().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
http.authenticationProvider(new CustomAuthenticationProvider())
.authorizeRequests() // the order is matter here, if antMatchers() will match the request the others after him will not be checked, anyRequest() will match any request, so it should be at the end
//.permitAll().antMatchers("/webjars/**").permitAll().antMatchers("/swagger-resources/**").permitAll() - there is no need to duplicate what is in web.ignoring() - such requests will not reach this point
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/health").permitAll()
.anyRequest().authenticated()
http.rememberMe().rememberMeServices(rememberMeService).useSecureCookie(useSecureCookie);
//Show 403 on denied access
http.exceptionHandling().authenticationEntryPoint(new Forbidden());
}
This issue is completely related to transitive dependencies. After removing some dependencies and adding excludes to others the core problem has been solved.

#EnableOAuth2Sso - How to protect / unprotect resources?

I’m trying to use the #EnableOAuth2Sso feature in Spring Cloud Security. Specifically, I’m attempting to protect some resources with OAuth2 while leaving others publicly accessible. I've managed to get this working, but I'm looking at the resulting code and wondering if there is a cleaner way.
I’m following the documentation here: https://github.com/spring-cloud/spring-cloud-security/blob/master/src/main/asciidoc/spring-cloud-security.adoc AND similar guidance from the Spring Boot reference. I have a tiny code example that illustrates my dilemma: https://github.com/kennyk65/oAuthSsoExample.
In a nutshell, I want the localhost:8080/unprotected resource to be publicly available, and I want the localhost:8080/protected resource to require OAuth2 (via github, as configured). I’m able to get the basic OAuth2 behavior to work just fine, but causing /unprotected to be publicly available is problematic.
First, The docs indicate that you can just use the OAuth2SsoConfigurer’s match() method to specify the resources to protect. I've found this doesn't work; when I try I get an IllegalStateException saying that at least one mapping is required. This appears to be referring to the unimplemented configure(HttpSecurity) method.
Next, I’ve tried to specify a mapping in configure(HttpSecurity) that states that the ‘unprotected’ resources should be unprotected. However, this results in Http basic security being applied to that resource. Curiously, this results in the ‘protected’ resource being completely public!
// This results in “unprotected” being protected by HTTP Basic
// and “protected” being completely open!
#Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/unprotected/**").permitAll();
}
}
On a whim I tried deliberately adding that the protected resource should be authenticated. This resulted in the protected resource getting OAuth2 protection (hurrah!) but the unprotected resource got http basic security applied (huh?).
// This results in “protected” being protected by OAuth 2
// and “unprotected” being protected by HTTP Basic, even though we say permitAll():
#Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/protected/**”).authenticated();
.antMatchers("/unprotected/**").permitAll();
}
}
At wit’s end to try to find the magic combination, I tried simply switching HTTP basic authentication off using security.basic.enabled: false. This worked (hurrah!), though I’m still a bit puzzled what the issue is with the mappings.
So I guess my question is, is this correct? What is the best way to protect some resources with OAuth 2 and leave others alone?
If you match on /protected/** then it makes no sense to then add an access rule to /unprotected/** (the path doesn't match so the rule will never be applied). You either need another filter chain for your "unprotected" resources, or a wider match for the SSO one. In the former case, the default one that you get from Spring Security will do if you don't mind switching off the security it is providing. E.g.
#Configuration
protected static class OauthConfig extends OAuth2SsoConfigurerAdapter {
#Override
public void match(RequestMatchers matchers) {
matchers.antMatchers("/protected/**");
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**”).authenticated();
}
}
and set security.basic.enabled=false.

Resources