About
Side Projects
Blog
2026-08-20

Haiku Depot Server - SSO and Web UI

Terminology

Background

Back in 2013 when the Haiku Depot Server project started, the Haiku project didn’t have an SSO option deployed so, I created a home-grown user management system within HDS itself. Not long after HDS was in production, the Haiku admin team deployed KeyCloak identity platform (SSO) so that Haiku community users could use the various online services with one login and identity. Despite being desirable to integrate HDS with the new Haiku SSO, it was – and still is – more challenging than it looks to unwind the home-grown login system. Ideally though, HDS would no longer manage users and would instead delegate this responsibility to the SSO.

The web user interface for HDS was build back then with the AngularJS framework. The AngularJS technology was advanced for the early 2010s, but by the mid 2010s was dropped in favor of Angular framework. Don’t be fooled by the similar name; getting from AngularJS to Angular, in practical terms, meant a re-write. For this reason, given limited resources, HDS has stuck with AngularJS which hasn’t been a bad decision because has been working well all this time. The problem is that it’s been unsupported for some years and is not trivial to learn.

This article is about a plan to introduce SSO integration and, at the same time, replace the AngularJS web UI in a combined strategy.

Goals

Understanding what the objective is, helps to gain clarity about the undertaking; especially when time is limited and, it’s likely to be drawn out.

SSO Goals

Web UI Goals

Approach with Limited Resources

Although hopefully not unattractive, the UI that will result from this effort is unlikely to be highly polished at first. In the first instance, effort will be directed into the achieving the technical goals above. Developer resources are likely to be limited, and it may take some time to achieve. Once the goals are achieved then it will be possible to look at refinement. This might not be universally appreciated.

Strategy

Starting state

Before the project starts, the system has the following architectural structure;

Phase Before

As well as the single page application (SPA) written with AngularJS technology, HDS also supports a server side rendered (SSR) interface as well. This was built in early 2010s to support browsers that did not have an advanced JavaScript interpreter. For this reason, the SSR interface is currently called a “simplified interface”. Internally this is called the “multi-page” interface.

Proxies

This SSR interface uses SpringMVC within the backend and currently uses Thymeleaf templating.

Phase 1

After phase 1, the system has the following architectural form with changes highlighted in red;

Phase 1

Thymeleaf is somewhat complex and functions through dynamic interpretation with no build-time type safety. A newer SSR page-render technology called Java Template Engine (JTE) is available with a less complex syntax and using a compile-time approach providing type-safety. There also exists a plugin for JTE that works with the Intelli-J IDE which speeds up development.

This phase would see the existing SSR interface switch from Thymeleaf to JTE. The current limited “simplified interface” functionality will be extended slowly to cover the entire application’s functions. The JTE, CSS, JavaScript and localization infrastrucure setup would be part of this phase.

New SpringMVC controllers will be created for the SSR that use the HDS external RPC-API interfaces. This will be faster to implement because the API logic is already tuned to support the existing UI functionality. In the future, should the JTE templating library be no longer viable, the same controllers should be able to be used with a different templating library.

The very first release will be knowingly unlocalized. It may be prudent to wait for any issues with the new UI to settle before investing in localization although, it could, in theory start at this point. The localization will be re-started in a new file in the HDS application server. The new file is multipagemessages_<language-id>.properties and will need to be setup in Polygot. I recognize that restarting the localization from scratch will be a larger job for the translators but, I can see doing otherwise (have tried) is going to be difficult. With the new SSR technology, the full Java built-in message localization system is used which means that proper language-specific pluralization is now possible.

As I can read German, it would be helpful to maintain parity between German and English to help with catching any cases where the new UI elements are not localizable; hopefully Humdinger can still help out with this!

It would be possible for a parallel flow to occur at this point to implement all the remaining “logged out” pages. See phase 4 for a list of these. It would also be possible to carry on with any styling improvements of the pages.

Phase 2

After this phase, the system has the following form with changes highlighted in red;

Phase 2

In this phase, the system will implement Spring Session using the Postgres database as a means of persisting the sessions. Other storage mechanisms could be used such as Redis but this would make the HDS deployment more complex with additional elements to deploy.

Only authenticated users will obtain a session. The session will be tracked using a browser cookie. Logged-out users will remain stateless. Authentication will progress through a new SSR page and, in this phase, will use the existing legacy user management system.

The SPA will switch from being stateless over to using the same cookie-based session; it will stop sending JWT tokens back to HDS to identity the user and will instead rely on the browser cookies. The SPA will use the new SSR page and SpringMVC controller for authentication, redirecting back to the SPA once authentication succeeds.

The same session system will support the legacy SPA and SSR UIs and will simply carry an HDS authentication token.

A new endpoint will be provided to support logout.

The user usage agreement will need to be updated to explain the changes because browser cookies will be used to track sessions.

The HaikuDepot desktop application will remain as-is for this phase and will continue to use the existing authentication mechanics.

Phase 3

After this phase, the system has the following form with changes highlighted in red;

Phase 3

This phase is a significant transition that is “big bang” in nature where a smooth rollback will be challenging.

Keycloak

Two new KeyCloak clients will be required. One client will need to be configured for HDS and another for the Haiku Depot desktop application. The HDS one will use code-flow. The Haiku Depot desktop application one will use device-flow. Instructions for setting up a development instance of KeyCloak will need to be written. The instructions will need to include configuration guidance for attaining an analogous setup to the Haiku SSO system.

The KeyCloak access token will need to carry a JWT structure.

HDS

The user table in the HDS database will gain another string column sso_identifier which will carry the SSO user identifier which, in the case of KeyCloak, is a UUID. This field will be NOT NULL.

At the time of writing, there’s approximately 40 users who are connected to data in the system.

SELECT COUNT(DISTINCT u.id)
FROM haikudepot.user u
WHERE (1 = 0
    OR EXISTS (SELECT pup1.id FROM haikudepot.permission_user_pkg pup1 WHERE pup1.user_id = u.id)
    OR EXISTS (SELECT psm1.id FROM haikudepot.pkg_supplement_modification psm1 WHERE psm1.user_id = u.id)
    OR EXISTS (SELECT ur1.id FROM haikudepot.user_rating ur1 WHERE ur1.user_id = u.id)
    OR u.is_root = true
    OR u.
    )
  AND u.active = true;

This limited group of users will have their user record manually linked to their SSO identifier. Remaining users will be deleted as they will effectively serve no purpose after SSO is integrated.

The authentications will start at HDS but will no longer progress through the HDS user management system. Instead, users will be directed to the Haiku SSO service to authenticate using Open-ID protocol. The Haiku SSO service will redirect the user back to the HDS web UI.

On re-entry to HDS, if absent, a user record in the HDS database will be created and linked to the SSO identifier along with the nickname and email. If the user already exists then the nickname and email will be updated. The email is only copied so that later, the HDS system is able to contact the user for some administrative purpose if necessary. These fields are correlated on every authentication.

The session carries the SSO user data. No other additional structure is necessary in this phase.

There exists APIs and SPA UI in the HDS system for servicing user authentication, creation and editing. The APIs in this area should be marked as deprecated and should return errors. The UI should be removed and also removed from any navigation paths. The Captcha system within HDS can also be removed.

HDS will continue to accept OpenID access tokens to authenticate individual requests. This would be used from the HaikuDepot desktop application for example. The sub claim on the access token will provide a mechanism to query for a corresponding user record. At the scale HDS is running at, an eventually-consistent in-memory cache of the user record should be sufficient to not cause any major latency.

The OpenID integration supplied by Spring Security is intended to be used to provide the basis for integration with the SSO; hopefully mostly out of the box. HDS already uses Spring Security so this should be a natural extension.

HDS Config Changes

The Spring Security configuration for OpenID will be required. These configuration properties are prefixed with spring.security.oauth2.client.registration.keycloak.

Existing configuration properties prefixed with hds.authentication should be removed from the build-product. Immediately after deployment env-vars should be removed from the K8S Deployment configuration with prefix HDS_AUTHENTICATION.

The API MiscellaneousApiService#getRuntimeInformation should be updated to return false for allowsNicknamePasswordAuthentication which will stop the older HaikuDepot desktop application from supporting legacy authentications. Additionally, this API will supply the information necessary for the desktop application to integrate with SSO; for example the KeyCloak base URL, a URL for sign-up and the client ID.

Immediately after deployment, env-vars should be removed from the K8S Deployment configuration with prefix HDS_AUTHENTICATION.

The user usage conditions should be updated at this time to cover the new arrangements.

HDS Testing

Significant work will need to be carried out so that the automated testing for HDS can proceed using the new SSO-based authentication mechanism. It’s currently unclear how this will work but a simulated SSO system could be used or Test-containers KeyCloak may also be an option.

Haiku Depot Desktop Application

The desktop application will likewise need some major changes that will have to be coupled with the changes above. The desktop application will drop its own authentication path and will instead use OpenID device-flow. The client logic for OpenID should be made re-usable within the application sources to allow for later re-use.

HDS will provide on the getRuntimeInformation API the SSO’s OpenID base URL, a client ID as well as a URL for signup. Using the base URL, the desktop application can use the well-known URL path to obtain the standard OpenID configuration data. For example;

https://sso.haiku-os.org/realms/haiku/.well-known/openid-configuration

The Haiku installation would ideally have a web browser to progress the device-flow authentication but, it would also be possible to display the URL or QR code for use on another device. The desktop application will poll the SSO system to detect the completed authentication; once it is completed, the desktop application is able to obtain an access token to use with HDS APIs and a renewal token to refresh the access token from the SSO when the access token expires.

An authentication representing a user who has never previously interacted with HDS will trigger HDS to create a new user database record and associate it with the SSO user.

These changes will be patched into master as well as the R1B6 branches. Much older Haiku Desktop installations will simply fail to authenticate because the APIs will error. Newer installations will detect the allowsNicknamePasswordAuthentication value queried at application start tim e from the getRuntimeInformation API and will hide the authentication options in the desktop application’s UI. Catering for older clients’ authentication is not worthwhile.

On the desktop application, a successful authentication with the SSO should delete any username / password credentials persisted to the local key-store (see IdentityAndAccessUtils.cpp). The OpenID access token and renewal token will be retained in-memory. The renewal token will be persisted to the key-store. On start, the desktop application will be able to communicate to the SSO server to acquire a new access token using the renewal token.

A logout from the desktop application will terminate the SSO session with the renewal token and the renewal token will be removed from the key-store.

The Haiku-native user authentication flow will be removed.

Haiku Native Authentication

The Haiku-native create-user flow within the desktop application will be removed. When the user opts to create a new user, they will redirect to the SSO user signup interface. Given the amount of work involved, the extra effort of writing a Haiku-native user-signup interface for KeyCloak is not worthwhile; at least not in the first instance. It is also possible that the Haiku sys-admins may wish to introduce MFA or other authentication challenges such as email-verification; implementing a Haiku-native interface for those more complex interactions will be time-consuming and could become a blocker for administrative goals.

Haiku Native Create User

The desktop application’s version should be incremented to keep track of compatibility for disabling older clients incapable of OpenID authentication in the following years.

Phase 4

After this phase, the system has the following form;

Phase 4

Phase 4 is about completing the UI migration to the full server-side rendered UI and dropping the SPA UI.

The remainder of the logged out pages are to be completed first;

Unlike phase 1 where the pages were unauthenticated and largely search-and-display, most of the rest of the system is administration-related. Early on it wasn’t clear how frequently many admin operations would be required and, I’d implemented most admin workflows in SPA UI. It seems like the time investment to achieve this again with the new UI will be high but many of the admin operations are very infrequently activated. There is a ranking;

Once the “must have” items are completed, it will be possible to drop or disable the SPI interface and slowly work on the remaining pages.

Phase 5

After this phase, the system has the following form with changes highlighted in red;

Phase 5

Phase 5 is about splitting the new SSR UI out from the main HDS application so that there is a true backend application server and a true frontend application server. This wasn’t possible to do from the offset because the SPI and the SSR UIs shared the same web session and, it would have been complex to maintain the two systems.

The advantage of this approach is that the backend exposes an API which is cleanly used by the frontend SSR application. This is akin to how the SPA application is currently working.

Other options considered

Other options and technology options considered;

Summary and Considerations

The need to slowly replace the Web UI technology is clear. Combining this effort with moving to SSO seems like it will less work overall; or at least will be complimentary. The project looks to be quite large and may take a long time to complete however there is no rush. A practical approach will be taken to achieve the key goals and then refocus on time-consuming aesthetics later.