Can I have both public and protected vaadin paths in a plain java war?

I have an ear with multiple wars, some vaadin and some not.
In each, I have some paths that require authentication and some that are public.

I’ve set up web.xml so that /app requires authentication, and the vaadin service receives that url pattern:

    <servlet>
        <servlet-name>web</servlet-name>
        <servlet-class>com.vaadin.flow.server.VaadinServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>web</servlet-name>
        <url-pattern>/app/*</url-pattern>
        <url-pattern>/VAADIN/*</url-pattern>
    </servlet-mapping>
    ...
    <security-constraint>
         <web-resource-collection>
             <url-pattern>/app/*</url-pattern>
             ....
         </web-resource-collection>
    </security-constraint>

So far so good; If I create “@Route public class PersonView” it is accessible as “/<contextRoot>/app/person” and requires logon.
Any resource in webapp is handled by the webserver, is publicly available and requires no logon.

Now the problem: What if I also want to have a publicly available Vaadin page?
Say a “NewUserView”, and I want it to have url “/<contextRoot>/public/newUser”

I can add <url-pattern>/public/* to <servlet-mapping>, but that only means that all routes are available over both /app and /public.

I assume I can’t add two vaadin servlets either, because both of them would presumably find and add all @Routes

I’ve worked around this by creating a separate public.war and put NewUserView there, but I wondered if there is a better way to do it.

You can use Vaadin built-in security feature and use annotations to define routes protection level.
Assuming your application is not based on Spring (and Spring Security), you can take a look at the Securing Plain Java App documentation.

Ah, I assumed that only worked with Spring Boot, so I’ve never investigated. Thanks.

Skimming the documentation it does leave me feeling a bit uneasy; I assume it would mean leaving Vaadin completely open from the web server’s point of view, and trusting that there is no bugs in Vaadin’s security code or my own setup of it.

I’ll have to let the idea sink in a bit before deciding :slight_smile:

Relying on protecting URLs for the security of Vaadin applications can be risky; I believe this five-year blog post is still valid reading: The dangers of using the wrong abstraction for Vaadin access control | Vaadin

Yes, but we don’t secure individual URLs. We secure everything that goes to vaadin, which I think should be OK.
That means the web server only guarantees that the user is authenticated within the required security realm.

We handle the internal access ourselves.
We can’t do something like " @RolesAllowed(Receptionist), since the roles are not static. Our customers define them.

But, this might explain why I can’t expect there to (safely) be two entrypoints to vaadin, one secure and one public, in the same war.

More food for thought

If annotations check doesn’t work for you, you may consider implementing a custom navigation access checker https://vaadin.com/docs/latest/flow/security/advanced-topics/navigation-access-control

1 Like

If you’re OK with Vaadin handling the security, maybe the “Vaadin Simple Security” framework can help; take a look at the example app and see if you like the approach: GitHub - mvysny/vaadin-simple-security-example: Example app for the Vaadin Simple Security library

However, if you want the web server to handle the authentication, then this framework most probably won’t work for you.

2 Likes