Skip to content

docs: deprecate SSO Kit and add a Spring Security migration guide - #5950

Merged
Artur- merged 14 commits into
mainfrom
docs/sso-kit-to-spring-security-migration-guide
Sep 22, 2026
Merged

Artur- merged 14 commits into
mainfrom
docs/sso-kit-to-spring-security-migration-guide

Conversation

@totally-not-ai

@totally-not-ai totally-not-ai Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Summary

SSO Kit won't be available in Vaadin 26, so every application using it has to move to Spring Security's OpenID Connect support first. This marks all SSO Kit pages as deprecated and adds a guide that explains how to make that move.

What changed

Documentation only. No code, no behavior change — but the pages themselves now tell readers that SSO Kit is deprecated, so anyone browsing the SSO Kit docs sees the new warning.

Deprecation marked on every SSO Kit page. Each page gets the same caution banner, a [deprecated:com.vaadin:vaadin@V25.3] title badge, and a shared admonition included from sso/index.adoc. The landing page description and meta description now state the deprecation, so it shows up in navigation and in search results. On the tools overview page, the SSO Kit card is labelled deprecated and points at Spring Security.

New guide: Migrating to Spring Security (articles/tools/sso/migrating-to-spring-security.adoc). It covers:

  • What changes and what doesn't — provider and client registration properties stay as they are, and AuthenticationContext is Vaadin Flow API, not SSO Kit, so views need no change.
  • Three searches to scope the work, including the legacy dev.hilla and @hilla names.
  • A table mapping every kit feature and vaadin.sso.* property to its replacement.
  • Six steps for a Flow application: swap the dependency, keep the provider config, write the security filter chain, then optional steps for back-channel logout, concurrent sessions, and Keycloak role mapping.
  • Hilla steps: expose the user through your own service, replace the SSO context with @vaadin/hilla-react-auth, and protect routes with ViewConfig or protectRoutes().
  • What has no drop-in replacement: client-side logout notification, the Keycloak Lumo login theme, and the Lit client.
  • A final checklist of every feature and its status.

The guide uses [since] badges for the two features ported from SSO Kit into Flow in V25.3 (VaadinExpiredSessionStrategy and KeycloakOidcUserMapper), and keeps the manual approach in a note for earlier versions.

One warning the guide calls out: the starter also contributes a SessionRegistry bean. An application that injects one fails to start once the dependency is removed, so it has to declare its own.

SSO Kit isn't available in Vaadin 26, so every application using it has to
move to Spring Security's OpenID Connect support before upgrading. There was
no documentation for that move.

Marks every SSO Kit page as deprecated using the same banner and admonition
pattern as the other deprecated tools, and adds a migration guide that maps
each kit feature to its replacement, gives the security configuration that
replaces the auto-configuration, and documents the features that have no
drop-in replacement.
@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Preview Deployment

This PR has been deployed for preview.

URL: https://docs-preview-pr-5950.fly.dev

Changed pages

Added content is highlighted in green; removed content is marked in red on each page.

Built from 28c81f7

totally-not-ai Bot and others added 4 commits September 5, 2026 12:08
Uses the future tense "won't be available in Vaadin 26" throughout, since
Vaadin 26 doesn't exist yet, and states the deprecation in the landing page
description as well as the meta description so it shows in navigation and in
search results.

Also labels the SSO Kit card on the tools overview page as deprecated and
mentions that its features are now in Spring Security, so the signal is
visible before anyone opens the section.
The Hilla Lit client section asserted that Hilla with Lit is discontinued,
which isn't documented anywhere. Replaces it with what the Upgrading Guide
actually says: the router Hilla Lit views use is deprecated and no longer
actively maintained, and moving Lit views to React is the recommendation.
…ions

vaadin/flow#25625 adds UidlExpiredSessionStrategy and makes
VaadinSecurityConfigurer install it by default, and vaadin/flow#25627 adds
KeycloakOidcUserMapper behind a keycloakRoleMapping() opt-in. Both were
ported from SSO Kit, so two of the migration gaps close.

Moves the two features out of the gaps section and into the migration steps
that need them, with a since badge for the version they arrive in and the
previous manual approach kept in a note for earlier versions. Updates the
feature mapping table and the checklist to match.
@mshabarov

Copy link
Copy Markdown
Contributor

@totally-not-ai take a look into these comments and fix where you think it makes sense.

Content gaps

  1. The Lit section understates the deadline. articles/upgrading/index.adoc:246 says Vaadin Router is removed in Vaadin 26 — the same release that drops SSO Kit. The page only says "deprecated and no longer actively maintained" and frames the React move as optional ("if that move is planned anyway"). It should say outright that a Lit auth context built now dies in the same upgrade.
  2. protectRoutes() from @vaadin/hilla-react-auth is missing. The package exports protectRoute()/protectRoutes(routes, redirectPath?) with AccessProps { loginRequired, rolesAllowed } — a near 1:1 replacement for the kit's protectRoutes(). Presenting ViewConfig as the only option forces apps with a hand-written routes.tsx into a file-based-routing migration the SSO change doesn't require.
  3. Beans that disappear with the starter aren't mentioned. SingleSignOnDefaultBeans supplied a SessionRegistry bean unconditionally. An application that injects SessionRegistry fails to start after Step 1. Worth one line in "Before Migrating".
  4. vaadin.sso.auto-configure is absent from the feature-mapping table. It's a real property (AbstractSingleSignOnProperties#isAutoConfigure); apps that set it to false already own their filter chain and migrate trivially.
  5. "Scope the Work" greps miss the legacy names. @hilla/sso-kit-client-* (the kit's own getting-started page still shows npm install --save @hilla/sso-kit-client-react at getting-started/hilla.adoc:199,208) and dev.hilla:sso-kit-starter.
  6. UserLogoutEvent → SessionDestroyEvent is presented as equivalent, and isn't. UserLogoutEvent is published only by the kit's BackChannelLogoutFilter, i.e. back-channel logout only; SessionDestroyEvent fires on every session destruction, including timeout and ordinary logout. The difference needs stating.

Code

  1. UserInfoService won't typecheck on the client. The record has no @nonnull, so Hilla generates roles?: Array<string | undefined>, while AuthConfig.getRoles(user) must return readonly string[] — getRoles: (userInfo) => userInfo.roles fails. The house example at articles/building-apps/react/security.adoc:56-62 annotates with @nonnull for exactly this reason.
  2. The gap-logout-notification snippet doesn't compile. sessionRegistry is never declared, and it can't simply be injected: the default InMemoryOidcSessionRegistry is created as a shared object, not a bean (OAuth2ClientConfigurerUtils.getOidcSessionRegistry). The example needs an explicit @bean OidcSessionRegistry, and the handler should be built once rather than per invocation.
  3. Import blocks are inconsistent. Steps 1/3/4 show imports; UserInfoService, the GrantedAuthoritiesMapper example and the earlier-versions VaadinExpiredSessionStrategy don't.

Nit

  1. order: 4 breaks the section's 10/20/30 scale (getting-started 10, theming 20, integrations 30).

- Note that the starter's SessionRegistry bean disappears with it, so an
  application that injects one fails to start after Step 1.
- Add the legacy dev.hilla and @hilla names to the searches, and the
  deprecated auto-configure property to the mapping table.
- Document protectRoutes() from @vaadin/hilla-react-auth for applications
  with a hand-written route list, so route protection no longer implies a
  move to file-based routing.
- Separate UserLogoutEvent from SessionDestroyEvent, which also fires on
  logout and timeout.
- State that Vaadin Router is removed in Vaadin 26, so a Lit auth context
  written now lasts one release.
- Fix the code: @nonnull on the UserInfo record, an OidcSessionRegistry
  bean and a single handler instance in the logout example, and imports in
  the three snippets that lacked them.
Name the second starter bean for what it is, an OidcUserService, and drop
the sessionConcurrency() escape hatch: Spring Security takes a
SessionRegistry bean when one exists but otherwise keeps its instance in
the filter chain, so it never satisfies an injection point.

Keep name and email nullable in the UserInfo record, since both claims are
optional in OpenID Connect; only roles needs the annotations.
@totally-not-ai

Copy link
Copy Markdown
Contributor Author

@mshabarov Went through the list; all of it landed except one point, where the underlying claim didn't hold up. Details per item:

3. Lit deadline. The paragraph now says outright that @vaadin/router is removed in Vaadin 26 -- the same release that drops SSO Kit -- together with the vaadin.react.enable=false fallback, and links the Vaadin Router Deprecation section of the Upgrading Guide. A Lit authentication context written for this migration survives one release, so the two moves belong in the same change.

4. protectRoutes(). Added as a first-class option: @vaadin/hilla-react-auth exports protectRoute()/protectRoutes(routes, redirectPath?), and the access properties (loginRequired, rolesAllowed) live in the route's handle. The section now splits by routing style -- ViewConfig for file-based routing, protectRoutes() for a hand-written [filename]routes.tsx -- with a note that the default redirect path is /login instead of the kit's /ssologin. The checklist row follows.

5. Lost beans. "Before Migrating" now warns that SingleSignOnDefaultBeans contributes the SessionRegistry (and, in the versions that have the keycloak-roles property, an OidcUserService for the role mapping), so an application that injects SessionRegistry fails to start after Step 1. The only fix offered is declaring a SessionRegistryImpl bean: sessionConcurrency() takes a bean when one exists but otherwise keeps its registry inside the filter chain, so it never satisfies the injection point.

6. auto-configure. Added to the mapping table, but not as "those apps migrate trivially": the property has been deprecated and without effect since SSO Kit 2.1 -- isAutoConfigure() always returns true and the setter does nothing -- and the supported way to switch the auto-configuration off is spring.autoconfigure.exclude. The row says that, and that an application which did switch it off already has the Step 3 filter chain.

7. Legacy names. "Scope the Work" now also lists the pre-Vaadin-24.4 names: dev.hilla:sso-kit-starter with the dev.hilla.sso package, and @hilla/sso-kit-client-react / @hilla/sso-kit-client-lit.

8. UserLogoutEvent. No longer presented as equivalent. A new entry under "Smaller Differences" explains that the kit's event comes only from its back-channel logout filter, while SessionDestroyEvent fires on every session destruction including timeout and ordinary logout, and that the event carries no reason to tell them apart. The mapping table and the checklist point at it.

9. UserInfoService. roles is now annotated inside and out (@NonNull List<@NonNull String>), with a callout explaining that getRoles() has to return readonly string[]. name and email stay nullable on purpose: both claims are optional in OpenID Connect, so getFullName() and getEmail() can return null, and hiding that behind @NonNull would only move the surprise to the client.

10. Logout notification snippet. Rewritten so it compiles: an explicit @Bean OidcSessionRegistry (an InMemoryOidcSessionRegistry), the registry injected into the filter chain bean, and one OidcBackChannelLogoutHandler built outside the lambda instead of per request. Callouts say why the bean is needed.

11. Imports. Added to the three snippets that lacked them: UserInfoService, the GrantedAuthoritiesMapper example, and the earlier-versions VaadinExpiredSessionStrategy.

12. Order. order: 4 is now order: 40, after getting-started (10), theming (20) and integrations (30).

@Artur-

Artur- commented Sep 22, 2026

Copy link
Copy Markdown
Member

Check that this is up to date with especially vaadin/flow#25627 and vaadin/flow#25625, both since 25.4

@totally-not-ai

Copy link
Copy Markdown
Contributor Author

@Artur- Checked both against the merged code in vaadin-spring on main, method by method.

vaadin/flow#25625 (expired session handling) was already covered and still matches: Step 5 says VaadinSecurityConfigurer installs VaadinExpiredSessionStrategy whenever the application has session management configured, describes the pass-through (the expired request reaches the servlet, so a UIDL request gets Flow's session expired message and a heartbeat a 403), and names both escape hatches, expiredSessionStrategy(...) and enableSessionManagementConfiguration(false). The feature table points at com.vaadin.flow.spring.security.VaadinExpiredSessionStrategy.

vaadin/flow#25627 (Keycloak role mapping) was covered as keycloakRoleMapping() plus the KeycloakOidcUserMapper row in the feature table, but two things from it were missing, so Step 6 now adds them:

  • The mapper can be used directly, which is what an application that already declares an OidcUserService should do -- setOidcUserConverter(new KeycloakOidcUserMapper()), with the switch left off. There's a snippet for it.
  • The role prefix follows the prefix configured for the application rather than a hardcoded ROLE_, which is the one behavior difference from the kit's mapper, and roles that resource_access grants to other clients are ignored.

Both features are marked [since:com.vaadin:vaadin@V25.4] on the page, matching the release they merged for.

main now documents the feature in the OAuth2 Authentication page, with an
anchor of its own. Step 6 no longer repeats what the switch grants, why it
needs an OAuth2 login page, or how to install the mapper on a user service
the application builds itself, and links that section instead, so the two
can't drift apart. What stays is the part that belongs to a migration: the
property this replaces, and the two behaviour differences from the kit's
own mapper.

Also fixes three style checks in text added earlier on the branch: a
spelling error, an undefined abbreviation, and a cliche.
@Artur-
Artur- merged commit 95f2d77 into main Sep 22, 2026
10 checks passed
@Artur-
Artur- deleted the docs/sso-kit-to-spring-security-migration-guide branch September 22, 2026 11:21
@github-project-automation github-project-automation Bot moved this from 🔎Iteration reviews to Done in Vaadin Flow | Hilla | Kits ongoing work Sep 22, 2026
Artur- added a commit that referenced this pull request Sep 22, 2026
) (CP: v25.3) (#6129)

Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com>
Co-authored-by: Artur Signell <artur@vaadin.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-picked-v25.3 target/v25.3 Automatically cherry-pick to the v25.3 branch

Projects

Development

Successfully merging this pull request may close these issues.

4 participants