I have tried to integrate this add-on, but could not get it to run. Upon st

I have tried to integrate this add-on, but could not get it to run. Upon startup I get this with Vaadin 14.4:
Error creating bean with name ‘codecamp.vaadin.security-de.codecamp.vaadin.security.spring.autoconfigure.VaadinSecurityProperties’: Could not bind properties to ‘VaadinSecurityProperties’ : prefix=codecamp.vaadin.security, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is javax.validation.NoProviderFoundException: Unable to create a Configuration, because no Bean Validation provider could be found. Add a provider like Hibernate Validator (RI) to your classpath.

After adding spring-boot-starter-validation as a dependency I am getting this:
Parameter 0 of method setObjectPostProcessor in org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter required a bean of type ‘org.springframework.security.config.annotation.ObjectPostProcessor’ that could not be found.

Unable to create a Configuration, because no Bean Validation provider could be found.

That error message implicates that you don’t have a bean validation provider included in your project configuration: https://vaadin.com/docs/v14/flow/binding-data/tutorial-flow-components-binder-beans.html#using-jsr-303-bean-validation

Yes sure. As I wrote above in the second paragraph, after including a provider I am getting a different error (I have also tried the Hibernate validator - same error message).

Sounds like you might be missing a @Configuration or @Bean annotation somewhere?

Possibly. But the error appears by just including the add-on. I’ve not even started to use it. I also downloaded the demo app and it has the same problem.

The demo had four unneeded classes (some with compile errors) that I removed just now. But with or without them, I can get it to start on two different machines without any changes.

After some experimentation I can say that including my vaadin-security-spring-boot-starter did trigger Spring Boot’s ValidationAutoConfiguration which made an implementation mandatory. With version 0.9.1 (which I just uploaded) you should no longer need to add spring-boot-starter-validation if you don’t already require it for other reasons.

But for your second error after including spring-boot-starter-validation, that seems to be a completely different problem and related to Spring Security and its configuration. That stuff is hard to pinpoint with just an error message.
Just like with spring-boot-starter-security, adding vaadin-security-spring-boot-starter should not make it necessary to immediately add more configuration just to get it to run again. And the demo and my other project seem to confirm that. Can you reproduce the error with the demo?

The demo application runs now and I can also include the add-on and my app will start. I haven’t actually used the Add-on yet, because my app is done with Spring Security / Vaadin in the traditional way. So I have lots of configurations, of which some are now probably obsolete or even incompatible with the Add-on. One thing I found is that my UserDetailsService wasn’t picked up by the Add-on, so I probably need to rewire parts of my application. That’ll take some time, but I’ll report back if I find any concrete issues.

Even report back if everything works out fine :)

My addon is mainly glue between Vaadin and Spring Boot Security and configuring a UserDetailsService should be no different than before.

The UserDetailsService is only automatically picked up as long as Spring Security’s auto-configuration is still active. Once you add your first VaadinSecurityConfigurerAdapter annotated with @EnableWebSecurity, you have to do it/everything manually.

Can you describe what kind of boiler plate code the addon saves me?

I did notice the access control features (which I have implemented manually with org.ilay). But apart from that would I just implement Spring Security as always, except that I need to hook in the VaadinAuthenticationService in the LoginListener?

Ulrich Mayring:
But apart from that would I just implement Spring Security as always, except that I need to hook in the VaadinAuthenticationService in the LoginListener?

Yes, that’s the idea. You basically configure Spring Security as per usual (except that you extend VaadinSecurityConfigurerAdapter instead of WebSecurityConfigurerAdapter) and you use the VaadinAuthenticationService to perform the authentication.

Spring Security doesn’t provide a Java API to programmatically authenticate someone. Sure, you can call authenticate on your AuthenticationManager and stick the result (if successful) into your SecurityContext. But this way you’re going around Spring Security’s filter chain. And everything you could just configure in your Vaadin/WebSecurityConfigurerAdapter, you would now have to do completely manually, like authentication failure handling, properly hooking up Remember Me authentication, etc.

Spring Security’s form-based authentication makes use of the filter chain and has a simple API: you provide username and password and then the user’s properly logged in or not. Functionality-wise that’s exactly what we want. With Vaadin’s LoginForm you can even directly make use of it (setAction(…)). But you’d somewhat leave the Java/Vaadin world and would have to deal with URL-based redirections to you login and on success/failure. You can make it work, but it doesn’t really fit Vaadin.

My VaadinAuthenticationService now basically wraps the form-based authentication endpoint in a nice Java API and allows you to stay inside Vaadin. E.g. the redirect to the login view is route-based and not URL-based. I.e. you’re navigating within your Vaadin UI and not creating a new one. On authentication failure you can just update your login view instead of having it reloaded and parsing an error parameter from the URL.

Well, I hope this explanation was useful and not TMI ;)

Well, this was very useful, but definitely not TMI. In fact, I need to know more :)

The first thing is that I can’t configure my Httpecurity like this:

protected void configure(HttpSecurity http) throws Exception {
	super.configure(http);
	// do my own stuff

Spring tells me “Can’t configure requestMatchers after anyRequest”, so I suppose anyRequest happens somewhere in super.configure(). If I get rid of the call to super, then Login fails (I assume the UserDetailsService isn’t picked up). If I get rid of my own stuff and only call to super, then Login works, but there is no redirection after login from /login to /. You said that I need to define that with a Route, but how?

Without knowing any specifics: Have you tried doing your stuff and then calling super? You only mention doing one or the other.

You can change some routes / URLs in your application.properties with the prefix codecamp.vaadin.security.locations.. STS should provide auto-completion. The only ones you might have to mess with are login-route, main-route and ui-root-url.
If you get redirected to the login view, you should be redirected back to where you came from after a successful login. If that information is not available, you get redirected to main-route. The default is /. (Technically it’s the empty string, because Vaadin’s routes don’t have the leading slash.) So it should already work like you want it.

What requestMatchers are you trying to configure?

If I put the call to super after my stuff, I get “Can’t configure anyRequest after itself”. My Config:

http.csrf().disable()
	.requestCache().requestCache(new CustomRequestCache())
	.and().authorizeRequests()
	.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
	.anyRequest().authenticated();

Removing the last line fixes the problem, so I suppose that is already included in super? But I am not entirely happy with the call to super being the last line, that seems weird.
As for the routing, I am being routed back to “” as per the URL shown in the browser’s navigation bar, but the Login Dialog does not go away. I need to manually reload the page.

I’d say, you don’t need anything of that. VaadinSecurityConfigurerAdapter takes care of everything you’re trying to do here :)

Not sure though, why the redirection still doesn’t work. You can refer to the demo to see that it should work.
And that Vaadin changes the URL from “/login” back to “/” without changing the content (if I understand you correctly), sounds really strange. Is there maybe some code left that reroutes to the login view when authentication is missing?
(In Vaadin a reroute goes to a different location without updating the URL. A forward also updates the URL.)

I removed everything except the CustomRequestCache, which is not in VaadinSecurityConfigurerAdapter, and I left this code in to ignore irrelevant URLs:

public void configure(WebSecurity web) throws Exception {
	super.configure(web);
	web.ignoring().antMatchers(
		"/VAADIN/**",
		"/favicon.ico",
		"/robots.txt",
		"/manifest.webmanifest",
		"/sw.js",
		"/offline-page.html",
		"/icons/**",
		"/images/**",
		"/frontend/**",
		"/webjars/**",
		"/h2-console/**",
		"/frontend-es5/**", "/frontend-es6/**");
}

That seems to do the trick with startup and I can also call to super() in the first line.

However, the problem with redirection may be from this class:

/**
 * We have to secure Router navigation by registering a before navigation listener that checks for
 * permissions. This is very important as Spring Security is not aware of the single page application
 * behavior of a Vaadin application. That means AJAX requests as they are done during navigation via
 * Router links are not protected by the default Spring Security filters.
 * 
 * @see https://vaadin.com/learn/tutorials/securing-your-app-with-spring-security/setting-up-spring-security#_secure_router_navigation
 */
@Component
public class ConfigureUIServiceInitListener implements VaadinServiceInitListener {
	@Override
	public void serviceInit(ServiceInitEvent event) {
		event.getSource().addUIInitListener(uiEvent -> {
			final UI ui = uiEvent.getUI();
			ui.addBeforeEnterListener(this::beforeEnter);
		});
	}

	/**
	 * Reroutes the user if (s)he is not authorized to access the view.
	 */
	private void beforeEnter(BeforeEnterEvent event) {
		if (!LoginView.class.equals(event.getNavigationTarget()) && !SecurityUtils.isUserLoggedIn()) {
			event.rerouteTo(LoginView.class);
		}
	}
}

I tried to leave this class out or comment its content, but when I do that I am getting a NullPointerException upon loading the LoginView. Perhaps the call to SecurityUtils.isUserLoggedIn() should be replaced? What it does is basically check the AuthenticationContext of Spring.

The (Custom)RequestCache is used to store the original HTTP request before redirecting to the login page, so the request can be replayed after a successful login. That doesn’t really work with Vaadin navigation, so my addon just stores the current route in the VaadinSession before forwarding to the login view. In other words, you don’t need the CustomRequestCache.

Regarding the ignored URLs: not really necessary in this case to make the application work, but it doesn’t hurt.

Hah, so I was right with the reroute :) You don’t need the ConfigureUIServiceInitListener anymore. My addon will forward to your login view, when a route is secured and the user isn’t already (fully) authenticated.
You can customize where your login view is with codecamp.vaadin.security.locations.login-route. The default is login.
The default behavior is that every view is unsecured (doesn’t require authentication to access) unless you annotate them accordingly (see demo or instructions in the linked GitLab project).
If you want the opposite (everything requires authentication unless e.g. annotated with @PermitAll), then set codecamp.vaadin.security.deny-unsecured to true.

If I remove the ConfigureUIServiceInitListener, then the rerouting from “/” to “/login” does not work. In fact, I am getting a NPE from loading “/”, which means that this code returns null:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication instanceof AnonymousAuthenticationToken) {
	return null;
}

My basic page layout needs to have the authenticated user in order to display his name (all pages are protected). The ConfigureUIServiceInitListener does its stuff on the beforeEnter event, so the “/” page isn’t even loaded. I would assume that the addon does the rerouting only after the “/” is loaded.

However, after removing the NPE-inducing parts from my page layout, no rerouting to “/login” happens at all and the page is displayed normally. Even though I have secured it with @SecuredRoute("hasRole('USER')")

I’m also using a BeforeEnterListener for access control so your application shouldn’t enter a view before redirecting. It almost sounds like my access control isn’t called at all.
Can you see debug logging from de.codecamp.vaadin.security.spring.access.DefaultVaadinAccessControl?

BTW, you can use VaadinSecurity#getAuthentication() instead of SecurityContextHolder.getContext().getAuthentication(). My method can also provide the Authentication in some non-request threads, e.g. when calling UI#access(…) from a background thread.

Yep, here’s the log output:

2020-10-22 14:10:50.642 DEBUG 29738 --- [  XNIO-1 task-2]
 d.c.v.s.s.a.DefaultVaadinAccessControl   : Checking access to navigation target '' (some.package.HomeView).
2020-10-22 14:10:50.642 DEBUG 29738 --- [  XNIO-1 task-2]
 d.c.v.s.s.a.DefaultVaadinAccessControl   : Forwarding to login route 'login'.
2020-10-22 14:10:50.643 DEBUG 29738 --- [  XNIO-1 task-2]
 d.c.v.s.s.a.DefaultVaadinAccessControl   : Checking access to navigation target '' (com.vaadin.flow.router.InternalServerError).
2020-10-22 14:10:50.643 DEBUG 29738 --- [  XNIO-1 task-2]
 d.c.v.s.s.a.DefaultVaadinAccessControl   : Access granted to error view '' (com.vaadin.flow.router.InternalServerError).
2020-10-22 14:10:50.646 ERROR 29738 --- [  XNIO-1 task-2]
 c.v.flow.router.InternalServerError      : There was an exception while trying to navigate to ''

some.package.HomeView is my View for “/”, which is annotated as such:

@Route(value=HomeView.ROUTE, layout=AppLayout.class)
@SecuredRoute("hasRole('USER')")

The InternalServerError then goes on with a stacktrace pointing to the NPE in my AppLayout class.

So from what I can tell, access to ‘’ is denied and I’m forwarding to ‘login’. Exactly as it should be.

This fails (I assume because of the NPE you mentioned) and Vaadin (not me) tries to show InternalServerError (Vaadin’s version of an error page) for the route ‘’. My addon grants access to this error page (it grants access to all HasErrorParameters). So that’s what you see.

Seems to me that fixing your NPE should fix the problem. Is this still related to accessing the Authentication? I mean, you’re not logged in yet and you ignore AnonymousAuthenticationToken, so you’ll always get null here. That’s my best guess on what you told me, anyway :)