Anonymised client work

Five applications, five ways to sign in

Each application had grown its own login and its own user store, at a different time, for a reason that made sense then.

A joiner meant creating five accounts. A leaver meant remembering all five, and remembering them was a person's job rather than a system's. The support queue filled with password resets that no single team owned.

You did not build that estate. You are expected to end it, and you have already said out loud, with the CTO in the room, roughly what it would take. Both halves of that sentence are now yours. If the cutover locks a team out on a Monday morning, your phone rings, and there is no vendor incident review to stand behind. So the rest of this is the mechanism, in the order it was actually done, and what it cost afterwards.

The estate before and after

  • Centralised login platforms

    Before5

    After1

  • Shared identity providers to operate

    Beforenone

    AfteroneSomebody patches it, watches it and carries a pager for it. The estate now runs a shared identity service of its own, and it did not exist before.

What it costs to keep is set out further down, in the same detail as what it saved.

Two rows, because two things are countable. Five centralised login platforms became one. The second row moves the wrong way, and it belongs here because it is true.

Onboarding meant five accounts. Be exact about what consolidation changed there: it changed where a person is authenticated, not necessarily where they are created. Federation leaves the underlying stores in place, so a joiner may still be created in more than one of them.

Offboarding is the other half, and it is reported rather than counted, so it is not put in the table as a third measurement. Revoking access used to be a checklist nobody trusted. It became one action that can be proven.

Five stores existed. A shared service did not.

The credentials never moved

  1. Verify

    Against the store that already holds the credential

    Nothing is copied. The provider answers as one issuer before any application moves. We federated the existing user stores into the provider instead of migrating them in one move.

    Keycloak Server Administration Guide, LDAP storage mode
    password validation always occurs on the directory server
  2. Re-encode

    On sign-in, under the realm's current policy

    The upgrade happens as people sign in, so nobody is asked to reset anything. The only moment the plaintext exists is the moment of a successful sign-in, and that moment is spent either way.

    Keycloak source, PasswordCredentialProvider.java
    rehashPasswordIfRequired
  3. Retire

    When accounts that never sign in are handled

    Only then does the legacy verifier come out of service. That is what sets the decommission date. Not a plan, and not a date you can pick in advance.

    Keycloak source, rehashPasswordIfRequired
    the catch block logs and carries on

Keycloak's administration guide is direct about why that is the shape of the answer. It imports users from a directory into its own database, and it states that it never imports passwords, because password validation always happens on the directory server. The same guide says that existing data storage typically cannot be migrated into a Keycloak deployment, which is exactly why federation exists, and that a store it does not speak natively can be reached through the User Storage SPI.

The upgrade to the current hashing policy then happens on a sign-in rather than inside a window. Keycloak's own source file for password credentials, services/src/main/java/org/keycloak/credential/PasswordCredentialProvider.java, reads the algorithm off the stored credential in isValid, verifies with the hash provider that owns it, and on success re-encodes the password the person just typed under the realm's current policy.

The honest half is in that same file, in rehashPasswordIfRequired. Keycloak's own comment says the re-encode runs in a different transaction and must not fail on a model exception caused by concurrent logins, and the catch block logs and carries on. A sign-in can succeed while the upgrade quietly does not happen. An account that never signs in never converts at all, so the old verifier stays deployed until you deal with that tail on purpose, by reset or by expiry.

How five applications moved, one at a time

Each step is here because the one after it cannot hold without it

  1. The stores go first

    Behind the provider, because nothing can integrate against one issuer until one issuer exists. Federated, verifying where the credentials already lived.

  2. One application integrates next

    Because the mechanism has to be proven somewhere before it is trusted anywhere. Against the provider, once, starting where a failure costs least.

  3. The old login path is demoted rather than removed

    Because rollback cannot be live if the path it rolls back to is gone. It becomes one of the provider identity sources, not a switched-off system.

  4. The rest follow in ascending order of what a failure would cost

    Because the expensive case should not be the one that tests the mechanism. Each application carrying its own cutover and its own live rollback.

  5. The legacy paths come out last

    Because a path still serving one application cannot be retired for any of them. Retirement waits on the last application rather than on a date.

No change freeze. A freeze is a cost every other team in the business pays for a decision only one team made, so the order was the plan.

The property that makes it safe is in Keycloak's brokering documentation: an application integrated against the provider cannot see how the identity behind it is validated, and an identity source only has to know about the provider. An application therefore integrates once and never again, however much moves behind it afterwards. The legacy login was not switched off at all. It was demoted to being one of the provider's own identity sources, and which path a request took was a per-client switch, which is what made rollback a live thing rather than a paragraph in a runbook.

Risk ascending. The application whose failure would cost most moved once the mechanism had already held on the ones where it costs least. That was the ordering rationale, and it is the only one stated here, because there is no published rule about which application should go first and we are not going to invent one.

What signing out actually delivers, per application

How each logout mechanism behaves across the five applications
MechanismWhat it delivers
Front-channel logoutOne iframe per application in the browser.
Back-channel logoutthe default hereServer to server, no browser dependency.
Neither registeredNothing at all, and silently.

Single sign-on is the easy half. What single sign-out guarantees is less than the phrase suggests. The session at the provider ends. Everything past that is a notification, and no part of the chain promises delivery. Keycloak's administration guide sets out the front-channel limits above and recommends back-channel logout instead. The Back-Channel Logout specification, section 2.5, then permits a delayed retransmission only where the provider suspects the previous attempt failed for a recoverable reason, such as a network outage or a temporary interruption at either end, and says it should not retransmit in any other case. There is no queue and no acknowledgement, and an application that is down for some other reason is not owed another attempt.

Across five applications that is three different states, and the third one is silent.

Can be blocked by a content security policy, and closing the browser first can leave sessions alive. No acknowledgement comes back.

Delivery is still not guaranteed: retransmission is permitted only where the provider suspects a recoverable failure, and an application unreachable for any other reason is not owed another attempt. Needs a server-side session store, because the call carries none of the user cookies.

Back-channel is the default here, and it carries a cost the specification states in its opening section. The logout call arrives server to server and carries none of the person's cookies. An application whose session is a self-contained signed cookie has nothing to invalidate. It has to acquire a server-side session store, or a revocation list keyed on the session id, before back-channel logout can do anything at all. Working out which of your applications is in that position comes before the plan, not during it. That is the step that turns a five-application consolidation from configuration into software engineering.

The account that survives

  • Access lingers in a store nobody owns

    It is forgotten. What changes is the number of places a revocation has to happen.

    What we commit to

    Revocation becomes one action in one place, because there is one place. What consolidating identity changes is the shape of that answer.

  • Evidence has to be assembled from five consoles

    Five consoles means five owners and five answers to assemble under time pressure. This follows from five becoming one.

    What we commit to

    One provider, one record of what was cut and when. The exposure is what made the work fundable, and it is not an engineering argument.

  • Reading any of this as an audit credential

    We do not hold SOC 2, GDPR, or HIPAA certifications ourselves. It says nothing about any audit outcome.

    What we commit to

    We engineer systems that pass your audits. To be plain: nothing here says we closed an audit finding for this client. We are not going to imply it either.

Five login systems is five places an account can survive a departure, and an account like that is usually not left on purpose. Two published SOC 2 readiness guides, from bastion.tech and screenata.com, list deprovisioning among the exceptions they see most often. The test is concrete. An auditor picks a handful of people who left, and asks for timestamped evidence that their access was revoked inside the window you told the auditor about.

Revocation becomes one action instead of a checklist across five systems, and that follows from five becoming one rather than from anything we can claim about an audit.

Show data table
Both figures come from the same consolidated estate. The 40 percent is licence and development cost together, and is not a licence saving on its own.
Item Value
Auth-related support tickets 70 percent reduction
Licence and development cost, combined 40 percent reduction
What fell in this estate after it ran on one login Both figures come from the same consolidated estate. The 40 percent is licence and development cost together, and is not a licence saving on its own. Figures for this consolidated estate after cutover.

Two numbers came out of this estate. Auth-related support tickets fell by 70 percent. Licence and development cost fell by 40 percent, counted together as one figure.

Nothing else is plotted beside them. There is no industry baseline for either that we would stand behind, and a borrowed number sitting next to ours would read as proof of ours.

What these numbers do not cover

  • Five or more applications, each with its own user store

  • A joiner or leaver process that spans several consoles

Where we are the wrong call

Take both figures with their edges showing. The 70 percent is a reduction in one estate's auth-related tickets. What those tickets were decides what a 70 percent cut is worth, and that arithmetic is yours, because what we hold is a reduction and not a volume. The 40 percent is licence and development cost together. Read as a licence saving it will build a business case that does not survive its first review.

Neither figure carries a period, and neither carries a timeline. This page establishes no elapsed time, no duration and no measurement window for either percentage, and it establishes no schedule, no concurrency and nothing about the order in which any of the work actually happened. The steps above are set out by what each one depends on, not by when it ran. So payback timing is not a question these two numbers can answer, and anyone modelling one is modelling their own assumption.

Five applications is the size of this estate, and a larger one has more of the hard parts rather than the same amount of them. The tail of accounts that never sign in gets longer too.

An estate in either of those two positions does not need a consolidation of this shape, and a single legacy protocol is often best left federated and said out loud rather than counted as covered. Consolidating identity while each application keeps deciding its own permissions is a finished architecture, not a half-done one. If that is your estate, the work is smaller than this and worth doing without us.

Thousands of monthly active users sign in through one provider. That is a floor rather than a rounded figure, and a login path carrying that many people is tier zero. What that costs to run is a property of this technology rather than of anyone's estate.

Key rotation is an obligation the shared provider introduces. Keycloak documents active and passive key pairs so keys can rotate without cutting existing sessions, and puts a best practice of new keys every three to six months in writing. It also documents how to break offline access by removing old keys too early, which is a thing you only do once.

Realm configuration has to live somewhere reviewed. Keycloak's own guide says the import and export process has limitations to be used as a backup and restore mechanism, so a console export is not the copy anyone should be relying on. Configuration as code, reviewed like code, is the only version of that which survives a bad afternoon.

The integration layer is a standing budget line too. Keycloak deprecated its own client adapters, announced in 2022 and restated in 2023, and 24.0.0 was the last major release to ship them. An integration layer now sits on third-party libraries with their own release cadence, so a provider major upgrade can force a code change in every application behind it.

Send us the estate

Send the list. What each application is, what it authenticates against today, and which store nobody wants to touch. That is what the first conversation is about: which of those stores can be federated as they are, which cannot and why, and which application would be the hard one. Finding that application is what the exercise is for, because it decides whether the rest of the plan is worth writing.

The other good outcome is real. Some estates read this, work out that the job is smaller than they feared, and do it themselves. That is a fine result, and we would rather you reached it than paid somebody to tell you the same thing.

The senior software engineer who replies to enquiries
Tirth BodawalaSenior software engineer
  • Scope is agreed in writing before anything starts

Start the estate conversation

You'll speak directly to a senior software engineer who's led dozens of real-world builds.

How we handle what you send is set out in our privacy notice.