[keycloak-dev] LDAP integration

Marek Posolda mposolda at redhat.com
Mon Mar 24 19:20:44 EDT 2014


Hi,

I've sent PR https://github.com/keycloak/keycloak/pull/302 with first 
version of Authentication SPI. Some key features:
- Authentication SPI is used for validation of username+password and 
also for password updates. So all existing components like 
AuthenticationManager and AccountService are now calling Authentication 
SPI instead of directly calling realm.validatePassword or 
realm.updateCredentials.

- Currently used just for username+password authentication. TOTP is 
still using RealmModel directly.

- I've added 3 implementations of Authentication SPI.
-- Model - This just delegates to realm.validatePassword and 
realm.updatePassword, so it's defacto the same stuff what we have now. 
This is the default implementation, which is used if no others are 
configured
-- ExternalModel -- This delegates authentication to "external" realm. 
In other words, user will be able to authenticate in RealmA with 
credentials from RealmB.
-- Picketlink -- This delegates authentication to Picketlink 
IdentityManager. I've added another abstraction 
PartitionManagerProvider, so it's possible to obtain Picketlink base 
class PartitionManager from various sources (for example from Picketlink 
subsystem). Default and only implementation of PartitionManagerProvider 
is initializing Picketlink with Ldap Identity store. Configuration of 
Ldap server is obtained from realm.

- Propagation of identities: If user authenticated with Authentication 
SPI doesn't yet exists in realm, he will be "synced" and automatically 
created into realm. So for example if you configure Picketlink 
AuthenticationProvider and corporate LDAP with 5k users and then you 
authenticate with your corporate username/password, your user account is 
automatically created in realm and also all basic attributes (firstName, 
lastName, email) are retrieved from LDAP server, or from external-realm 
or whatever other authentication provider provides.

- For update password, it's possible to configure that password will be 
updated just in some authentication providers. So for example, you can 
have read-only LDAP, which is used just for authentication users, but 
they can't update password here. Instead password might be updated just 
in "model" based Authentication Provider and synced into Keycloak DB, so 
next time user is able to authenticate with this changed password from 
Keycloak DB instead of the Ldap password.

- Configuration looks like this:

"authenticationProviders": [
     {
         "providerName": "model",
     "passwordUpdateSupported": true
     },
     {
         "providerName": "externalModel",
         "passwordUpdateSupported": false,
         "config": {
             "externalRealmId": "trustedRealm"
         }
     },
     {
         "providerName": "picketlink",
         "passwordUpdateSupported": true
     }
],


Picketlink provider doesn't have any configuration as it's currently 
automatically configured with LDAP server, which is configured for realm 
like this:

"ldapServer": {
     "connectionUrl": "ldap://localhost:10389",
     "baseDn": "dc=keycloak,dc=org",
     "userDnSuffix": "ou=People,dc=keycloak,dc=org",
     "bindDn": "uid=admin,ou=system",
     "bindCredential": "secret"
},

LDAP configuration is in separate "ldapServer" element as same LDAP 
config (and same PartitionManager) will be used for Authentication SPI 
and in the future for other things (like Sync SPI)


- Before this, we had just KeycloakSessionFactory as only 
application-scoped component. But with adding Authentication SPI and 
Picketlink+LDAP support, we may need more components (for example IDM 
PartitionManager, which is intended to be application-scoped component). 
Hence I've introduced KeycloakRegistry, which is simple Map of 
application-scoped components. And it's attribute ServletContext instead 
of KeycloakSessionFactory. Currently this registry contains just 
KeycloakSessionFactory and PartitionManagerRegistry (in case that LDAP 
is used). It's quite simple, but sufficient for current needs...

- For LDAP testing, I've reused some stuff from Picketlink+Picketbox and 
added embedded ApacheDS server into unit tests and testsuite.

- If you're ok with everything and merge this, I can follow with adding 
support for configuration Authentication providers and LDAP into admin 
console (right now it's possible just through JSON). And then possibly 
Sync SPI for the batch syncing of stuff from/to Sync providers (like 
LDAP server) or other Beta1 priorities from the wishlist :)

Cheers,
Marek

On 14.3.2014 16:31, Stian Thorgersen wrote:
>
> ----- Original Message -----
>> From: "Bill Burke" <bburke at redhat.com>
>> To: "Stian Thorgersen" <stian at redhat.com>
>> Cc: keycloak-dev at lists.jboss.org
>> Sent: Friday, 14 March, 2014 3:21:08 PM
>> Subject: Re: [keycloak-dev] LDAP integration
>>
>>
>>
>> On 3/14/2014 11:15 AM, Stian Thorgersen wrote:
>>>
>>> ----- Original Message -----
>>>> From: "Bill Burke" <bburke at redhat.com>
>>>> To: keycloak-dev at lists.jboss.org
>>>> Sent: Friday, 14 March, 2014 2:12:20 PM
>>>> Subject: Re: [keycloak-dev] LDAP integration
>>>>
>>>> Don't we need to have LDAP as a user store?  Won't companies have a user
>>>> LDAP store they want to point Keycloak to?  If you have an Auth SPI
>>>> only, then you'll still need to register the users with Keycloak.
>>> The idea with the authentication would be similar to social login. On first
>>> login a user would be created internally in Keycloak, and there would be a
>>> link to the user in LDAP. It would provide us with something relatively
>>> simple without the fuzz. Social login requires registration to be enabled
>>> for new users, but that shouldn't be required to create users that "links"
>>> to an LDAP store.
>>>
>>> We can even investigate allowing multiple authentication providers for a
>>> single realm. For example if a user exist in Keycloak you can check if
>>> there is a LDAP link, if there is authenticate with LDAP, otherwise with
>>> Keycloak. If no user exist, check with the other configured authentication
>>> providers if one exists.
>>>
>>> In the second round we can worry about syncing, or alternatively by using
>>> LDAP directly for users/role-mappings. I'm not 100% convinced, but I
>>> believe the syncing approach is the simpler and probably better solution
>>> to "federation".
>>>
>> So, all user updates (password, attributes, otp, etc...) will be stored
>> in Keycloak and then synced with LDAP?
> Can be yes, the Sync SPI needs to be flexible enough to specify what should be synced. It may also only be a one-way sync. Some examples:
>
> * Full sync with LDAP - if a user is added/changed in Keycloak it will be updated in LDAP, same other way around. This includes everything we can sensibly store in LDAP. It will also sync role mappings.
> * Read only sync with LDAP - for whatever reason the admin doesn't want to let Keycloak write back to the LDAP server. In this case we'd read changes from LDAP, but not write changes back.
> * Write only of users - for example if an application wants to have user profiles (excluding passwords, otp, etc.) in a relational database that can be queried directly by the application. This can be done by implementing the Sync SPI, and they can obviously change the way a user is represented by transforming it during the sync.
>
> This is most likely a stupid idea, but could we use the same syncing solution to sync between a cache and the db?!?
>
>> Bill
>>
>> --
>> Bill Burke
>> JBoss, a division of Red Hat
>> http://bill.burkecentral.com
>>
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-dev



More information about the keycloak-dev mailing list