[keycloak-dev] sync/federation requirements/ideas

Bill Burke bburke at redhat.com
Thu Jul 10 09:47:27 EDT 2014



On 7/10/2014 7:41 AM, Marek Posolda wrote:
>
> That's why I would prefer "sync" among "federation" approach.

Which is exactly what I'm proposing.  Except it allows for syncs/imports 
into Keycloak on demand.  You already use AuthenticationProvider in this 
manner!

My impression of a sync model is that Keycloak works with user data in 
local Keycloak storage.  User metadata is imported from external storage 
(either on demand or at startp and periodically synced).  Keycloak can 
manage/modify/augment this imported user data locally.  The changelog is 
obtained from the Sync API and updates sent back to the external storage.


> In
> shortcut with "sync" approach will be users (and eventually their role
> mappings) synced from external store into Keycloak and most of the
> UserProvider methods would deal just with "local" provider. Only
> exception are authentication related methods, and also "update" methods,
> which will need to update local user and also "external" users. But
> SyncProvider won't need to implement methods like getUsers(),
> searchFor**, getUserBy** etc as all users will be available locally.
>

The problem with this approach is that new users don't get imported into 
Keycloak until the sync gets invoked.  Syncing more than once per day, 
or even once per week may not be feasible.  If the external storage does 
not have a changelog, syncing would involve iterating through each and 
every user in external storage and syncing it with the keycloak 
database.  A full sync could take hours.


>
>
>
> In details, I can imagine to have things working this way:
>
> * There will be Sync SPI configured per realm, which will allow to sync
> users from "external store" to Keycloak.
>

+1

> * It will be possible to configure when to sync users. For example it
> can be full sync from LDAP at server startup or triggered from admin
> console. Then some periodic sync (triggered for example once per day).
>

+1

> * I am not sure if we need full sync from Keycloak to "external
> provider" but probably not. Once user, role or user credential will be
> updated in Keycloak, it will be also immediatelly synced to external
> provider (if provider is not read-only).
>

If you don't implement through the UserProvider/UserModel interface then 
you would need an Event model for which the SyncProvider listens to so 
that it can sync the user on demand.

> * It depends on SyncProvider implementation, what user data are synced.
> For example in case of LDAP it will be just email+first,lastName and
> eventually role mappings.
>
> * SyncProvider may also support roles + role mappings from external
> store. SyncProvider will be able to import roles into RealmProvider and
> then particular role mappings into UserProvider.
>
> * Users synced from "external provider" will have link to this provider
> similarly like it's now. In case that provider is read-write, then all
> newly created users in Keycloak will be synced into "external provider"
> immediatelly also with the credential (if syncProvider supports
> particular credential)
>
> I would propose the interface like this to handle both
> sync/authentication (not sure if "SyncProvider" is good name, maybe
> rather "ExternalUserProvider"). I can imagine something like this:
>
>
> public interface SyncProvider {
>

I think your SyncProvider interface is very limiting and even unusable. 
  For example, getAllUsers() is completely unfeasible if there is a 
large user database.


IMO it would be something like this:

public interface ChronJob {

    void invoke(KeycloakSessionFactory factory);
}

ChronJob would be scheduled to run at boot time and/or periodically by 
the admin console.  Periodic and boot time syncs would be implemented 
here.  The sync operation needs to have full control of when 
transactions begin and end so updates/creates/deletes can be executed in 
batches.

On demand syncing would be done through an implementation of 
UserProvider as I proposed earlier.  On-demand syncing is:

* Importing a user on demand
* Updating external storage on demand.

We would also have an event changelog that would be implemented as, or 
act like a persistent JMS Topic.  This event topic shouldn't be used to 
implement on-demand sync, but rather for when the external storage is 
read only.:

interface ChangeEvent {
    enum EventType {
        CREATE, UPDATE, DELETE
    }



    long getTimestamp();
    EventType getEventType();
    String getItemId();
    String getItemType(); // UserModel, RoleModel
}

EventListeners could perform the syncs on demand.  Or, a ChronJob could 
be something like a persistence JMS Topic subscriber and replay change 
events.

We could decide that we don't support user updates for read-only stores. 
  Then, in that case, IMO, we don't need a changelog event queue.




-- 
Bill Burke
JBoss, a division of Red Hat
http://bill.burkecentral.com


More information about the keycloak-dev mailing list