flow
flow copied to clipboard
AuthenticationContext.logout() throws NPE if invoked from VaadinSession.access()
Description of the bug
I have a "Logout" button and when I press it Vaadin throws an NPE.
Here's the stack trace:
java.util.concurrent.ExecutionException: java.lang.NullPointerException: Cannot invoke "com.vaadin.flow.component.UI.getPushConfiguration()" because "ui" is null
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:124) ~[?:?]
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:193) ~[?:?]
at com.vaadin.flow.server.FutureAccess.get(FutureAccess.java:62) [flow-server-24.7.5.jar:24.7.5]
at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:2176) [flow-server-24.7.5.jar:24.7.5]
[... lots of frames elided...]
Caused by: java.lang.NullPointerException: Cannot invoke "com.vaadin.flow.component.UI.getPushConfiguration()" because "ui" is null
at com.vaadin.flow.spring.security.AuthenticationContext.logout(AuthenticationContext.java:135) ~[vaadin-spring-24.7.5.jar:?]
at com.example.MyApp.security.SecurityService.logout(SecurityService.java:78) ~[ccom-1.0.0.jar:1.0.0]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:545) ~[?:?]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:328) ~[?:?]
at com.vaadin.flow.server.VaadinService.runPendingAccessTasks(VaadinService.java:2173) ~[flow-server-24.7.5.jar:24.7.5]
... 148 more
The problem is that AuthenticationContext.logout() assumes there is a current UI. Obviously this won't be the case if it is invoked from VaadinSession.access().
So which of the following is true?
AuthenticationContext.logout()is only guaranteed to work if there is a currentUIAuthenticationContext.logout()doesn't need a currentUI, it only needs a currentVaadinSession(but if there is also a currentUIthen that's OK too)
If 2 is true, then there is a bug here - straightforward.
If 1 is true, then there's an important missing feature here. It should be possible for a background task to invalidate the authentication in any user's session. For example, an admin may need to forcibly logout someone, or an enterprise app may always automatically logout someone after some timeout, whenever their rights & privileges are changed, etc.
Even if you don't agree that this should work, where is it documented that a current UI is required? I only see this:
Initiates the logout process of the current authenticated user by invalidating the local session and then notifying LogoutHandler.
Or as a minimal workaround, if AuthenticationContext.logout() is invoked with only a current VaadinSession then instead of throwing an exception it should just invalidate the session. Throwing an exception means the logout may not actually happen, which is a security hole.
Expected behavior
No NullPointerException and a successful logout.
Minimal reproducible example
Add a button to your app:
final VaadinSession session = VaadinSession.getCurrent();
layout.add(new Button("Logout",
e -> session.access(this.authenticationContext::logout));
Login, then press the button.
Versions
- Vaadin / Flow version:
vaadin-spring-24.7.5.jar - Java version: 25-ea
- OS version: Mac OS