Migrate to Keycloak with Zero Downtime

Scott Rossillo
Universal Language
Published in
5 min readJan 14, 2016

--

Keycloak / Red Hat Single Sign-On is an excellent Single Sign-On and identity management server, implementing both OpenID Connect 1.0 (OIDC) and SAML 2.0 specifications. It provides an Authorization Server and adapters for Java clients, including a Spring Security implementation. Since Keycloak implements the standard OIDC protocol, it works great with applications developed in other languages as well.

Migrating your users from one identity management system to another is something that requires careful upfront planning. You’re probably focused on the new features the new software will give you to build out your product. However, it’s important to plan and test your strategy for moving your users from your legacy system to your new identity management system, since a failed user migration process will cause headaches for your users and support team.

Some questions you should ask yourself when planning your new identity management implementation include:

1. Can users be migrated to the new system without them having to reset their passwords?
2. Can the new login system be turned on without downtime?
3. If something totally unexpected goes wrong with your new system launch, can it be rolled back?

When implementing Keycloak, the answer to all three questions is yes. The solution lies in Keycloak’s User Federation SPI, an interface allowing users to be imported from a legacy system into Keycloak’s local storage the first time they log into your application using Keycloak. This is called an on demand migration.

To help Keycloak implementers with user migration, we’ve open sourced our user federation provider. It can be used to perform an on demand migration to Keycloak. Below, we’ll take a dive into the code to understand how the user migration process works.

Our user federation provider will:

1. Confirm on demand if a user exists in our legacy user system.
2. Validate on demand if the password being typed into Keycloak’s login page matches their password in our legacy user system.
3. Import the user into Keycloak’s local storage and make Keycloak the system of record for the imported user after their first successful login.

Since we’re implementing Keycloak to support a service oriented architecture, our federation provider will use a RESTful API to request information about our users from the legacy system. This approach is very flexible because it supports a legacy user service written in any language and it provides a clear separation of concerns between Keycloak and the legacy system during the migration process.

Using our custom provider, we’ll be able address two of our migration concerns with minimal effort. Since we can validate user information and passwords on demand, we can migrate user accounts without users resetting their passwords and without downtime. Additionally, because the system of record remains our legacy system until a user logs in and we haven’t forced a password change, we can migrate back to our legacy system if something unexpected happens with our Keycloak implementation. Using an on demand approach to user migration mitigates the risk of a catastrophic failure rippling out of control.

We migrate our users to Keycloak in two steps via our federation provider. During login, we confirm that the user exists in our legacy system and import the user and any metadata, such as roles and custom attributes, into Keycloak. Secondly, we confirm the password entered on the Keycloak login screen matches the password in the legacy system and break the federation link. After these steps are complete, Keycloak will become the system of record for the user.

Writing our on demand migration provider starts by implementing the UserFederationProvider and UserFederationProviderFactory interfaces. The UserFederationProviderFactory
tells Keycloak what properties need to be set for the UserFederationProvider to work. Since we’re using a RESTful API in our federation provider, we just need to set the base URI to our legacy identity server.

The actual work is done by our custom user federation provider. By implementing a few key methods:

UserModel getUserByUsername(RealmModel realm, String username); UserModel getUserByEmail(RealmModel realm, String email); boolean isValid(RealmModel realm, UserModel local); boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);

In getUserByUsername() and getUserByEmail(), we call our legacy user system to request a JSON representation of the user to be migrated. Using this information we create a Keycloak user model, populate it with the information from our legacy system, and return the model to Keycloak for storage. Additionally, we set a federation link between the Keycloak user and our migration provider. This allows us to validate the user’s password with our legacy user system in a future API call.

Our isValid() method simply makes a request to our legacy user system to check if a user exists. Keycloak calls this method to verify that we want to proceed with credential validation.
A successful response means the user exists.

In our migration process, implementing a real check in isValid() may seem redundant, but it’s important. If a user has been created in Keycloak but fails to provide a correct password, the user will remain in Keycloak with a federation link to our migration provider. We need to be able to communicate to Keycloak if the user is still valid for migration if they return to login again hours or even days later.

Our validCredentials() implementation is also pretty simple. We send the username and password the user entered into the Keycloak login form over to our legacy system for validation. A successful response means the password validates; any other response means the entered password is incorrect. Upon successful validation, we save the password the user entered in the login form into Keycloak’s storage and remove the federation link between the Keycloak user and our migration provider. Keycloak is now the system of record for this user.

Our open sourced user federation provider comes with two sample applications. A sample legacy user service and a demo portal that can be used to prompt a Keycloak login and thus an on demand migration. Give it a try and hit us up in the comments below if you have any questions!

Originally published at tech.smartling.com on January 14, 2016.

--

--

Full stack software engineer, architect, and team lead with extensive experience building client and server software.