Reputation: 69
I've been trying to grasp Keycloak over the last weeks, so I can implement a way to authenticate users using a legacy provider (which is Oracle-based, with table of sessions and all sort of bizarre stuff). We plan to get rid of this in a near future, but for now we have to deal with it, so the idea is to use Keycloak on the front line - leveraging the main benefits it provides, like SSO - omitting the legacy auth provider from the apps that need authentication.
I read a little about building custom OIDC Identity Providers but it looks cumbersome for such a simple auth method exchange.
Is there a simpler way (rather than a new OIDC provider) of building a custom authentication provider using Keycloak? If so, could you give me an example or at least a deeper explanation? I found the Keycloak documentation very weak in terms of live examples, added to my lack of knowledge of Auth Protocols in general (which I'm already working on).
Thanks in advance.
Upvotes: 1
Views: 3828
Reputation: 3837
This is something my organization took on as well. It's tricky at best.
This user storage SPI is the route we took. We implemented a basic approach at first, by reading from the remote database via API calls. In our case we had two databases to connect through and our SPI implementation would call both and unify any data they provided on the user.
https://www.keycloak.org/docs/latest/server_development/index.html#_user-storage-spi
You can use the User Storage SPI to write extensions to Keycloak to connect to external user databases and credential stores. The built-in LDAP and ActiveDirectory support is an implementation of this SPI in action. Out of the box, Keycloak uses its local database to create, update, and look up users and validate credentials. Often though, organizations have existing external proprietary user databases that they cannot migrate to Keycloak’s data model. For those situations, application developers can write implementations of the User Storage SPI to bridge the external user store and the internal user object model that Keycloak uses to log in users and manage them.
And then in this section: https://www.keycloak.org/docs/latest/server_development/index.html#provider-capability-interfaces
If you have examined the UserStorageProvider interface closely you might notice that it does not define any methods for locating or managing users. These methods are actually defined in other capability interfaces depending on what scope of capabilities your external user store can provide and execute on. For example, some external stores are read-only and can only do simple queries and credential validation. You will only be required to implement the capability interfaces for the features you are able to. You can implement these interfaces:
What follows on that page is a listing of various other interfaces that you can implement based on your needs to provide the behavior you want.
org.keycloak.storage.user.UserLookupProvider
This interface is required if you want to be able to log in with users from this external store. Most (all?) providers implement this interface.
org.keycloak.storage.user.UserQueryProvider
Defines complex queries that are used to locate one or more users. You must implement this interface if you want to view and manage users from the administration console.
org.keycloak.storage.user.UserRegistrationProvider
Implement this interface if your provider supports adding and removing users.
org.keycloak.storage.user.UserBulkUpdateProvider
Implement this interface if your provider supports bulk update of a set of users.
org.keycloak.credential.CredentialInputValidator
Implement this interface if your provider can validate one or more different credential types (for example, if your provider can validate a password).
org.keycloak.credential.CredentialInputUpdater
Implement this interface if your provider supports updating one or more different credential types.
Recommendation: Clone the keycloak source code from their github repo for a better understanding of their code and how your implementation will interact with their existing framework. Primarily this is useful when debugging or figuring out "what the hell is happening that my code doesn't work the way I think it should". Usually it's because the way your implementation is used is different or you haven't taken caching into account. Cloning the source code is good because it also provides valuable examples of some basic implementations you can find in the examples folder.
That's the best advice I can offer right now. Here is the native LDAP provider implementation:
You can use that as reference.
Disclaimer: We undertook this effort with version 3.4 of Keycloak. The documentation was a tiny bit different and there was another example at the time of this being done directly in the source. The latest master (version 8) looks similar at the interface level.
At a high level the effort will look like this:
You might not need step 2 if just implementing step 1 gets you want you want. Step 1 abstracts your custom database backend and reads the user information and provides it back to Keycloak as a UserModel
that it'll import into its local database for use later.
Upvotes: 4