Pretty much a year ago, I wrote an ode to WebAuthn and Passkeys. This year, we have Spring Security support for these technologies, and I wanted to give it a try.
I started with a “normal Vaadin app stub” from start.vaadin.com, specifically one with “form-based authentication using users saved in a DB with JPA,” built with Spring Security. On top of that, I created an example path to show how you can get rid of your current username-password authentication in your existing app ![]()
The solution uses standard Spring Security components and some Vaadin “optimisations”. For example, the passkey registration only utilizes the server-side APIs and some of the JS utilities, bypassing the default HTML pages and HTTP request handling provided by Spring Security filters. It should be pretty much production-ready, although you need to configure the PublicKeyCredentialRpEntity for your domain/app (and maybe provide a different version for development).
Since Spring Security’s solution seems to require that passkeys can only be registered when already logged in, you’ll likely need an alternative authentication method—even if you plan to completely ditch username-password logins. Partly for this reason, my first step was to add OTT (aka “forgot your password link”) based login.
I can’t say I’m entirely in love with all the API design decisions of Spring Security/WebAuthn4J (like introducing the cumbersome Bytes instead of just using raw byte[]). The official docs are also quite limited (not mentioning what you really need for a production-ready solution), but hey, at least it’s proven to work now
. It would be hard to avoid using this existing infrastructure if you’re already using Spring Security anyway.
I’ll write some article(s) on the subject at some point, but for now, the commit timeline is probably decent documentation—at least if you already know something about passkeys & Spring Security.
For the example itself, I might still configure that one OTT page to be Vaadin-native, now it has “different theme” that the rest of the app which is Vaadin & Lumo theme. I might also create a branch where the passkey authentication happens more in a Vaadin/SPA manner rather than relying on Spring Security’s filter (now the Vaadin page initiates the login, but JS makes post request and then redirects). That would provide smoother UX and require less custom Spring Security config (e.g., CSRF prevention is disabled for WebAuthn login requests so they can be directly made from a Vaadin-based login form. Shouldn’t affect security much since there’s not much to steal for a non-authenticated user
).
Check it out and share your thoughts! I also plan to create an example that uses EclipseStore for persistence—I’d expect that to be much easier since, for me, the hardest part here was persisting the CredentialRecord(s) (and their Bytes) with JPA and properly configuring Postgres/Hibernate for byte[].