[keycloak-dev] How would you handle an external user store?

Bill Burke bburke at redhat.com
Tue Jul 8 19:10:55 EDT 2014



On 7/8/2014 4:06 PM, Marek Posolda wrote:
> On 8.7.2014 18:50, Bill Burke wrote:
>>> AuthProvider is trying to achieve something different than storing
>>> users, and the combination of the two is quite flexible.
>> They serve different purposes? And yet AuthProvider stores users:
>>
>> AuthProvider.registerUser()
>>
>> and retrieves them:
>>
>> AuthProvider.getUser()
>>
>> Then you have AuthenticationManager which creates a UserModel, sets up
>> an AuthenticationLink.  So a developer has to implement registerUser()
>> as well as the create interfaces of UserProvider.
> IMO the difference is:
> - UserProvider is used to implement whole storage SPI and store *all*
> informations needed for user (roles, socialLinks, requiredRoles etc...)
>
> - AuthenticationProvider is used just for password based authentication
> and hence need just very small subset of UserProvider methods. Note that
> methods "registerUser" and "updatePassword" are not mandatory to
> implement if you set "passwordUpdateSupported" for particular
> AuthenticationProvider to false. Method "registerUser" is used just to
> send "some" data of UserModel to the Auth store, but it doesn't need to
> be all (For example with LDAP you store just username, firstName,
> lastName, email ).
>

I was under the impression that LDAP schemas often store more than 
username, first, last, and email. i.e. address, phone number, really any 
number of claims.  They also can store role mappings as well, correct? 
So if a user has all those things in LDAP *AND* they want to 
authenticate through LDAP, what do they do?

The same could be said of RDBMS too.

> The point is, that AuthenticationProvider is really easy to implement as
> it doesn't need to store all Keycloak data related to user.

But that is not currently how you use AuthenticationProvider.

If the user is not already stored in a Keycloak UserModel, then 
AuthenticationProvider.getUser() must be implemented.  Otherwise 
INVALID_USER is returned.


Besides.  UserProvider is just as easy to implement.

> See
> PropertiesAuthenticationProvider from our examples. And note that we
> already have community members, who implement their own Authentication
> providers. IMO LDAP, Properties file, or legacy database are classic
> example, which suits much better as AuthenticationProvider than
> UserProvider.
>

I really don't care if users are already implementing SPIs for a beta 
project.  The time to fix the SPIs is *NOW* not after 1.0 Final release. 
  Once the APIs/SPIs go final, we are stuck with them.


> I am not sure if Federation based on metadata on UserModel is good idea.
> I think we already discussed Federation approach and the decision was to
> avoid it due to many reasons. I believe that Authentication SPI and Sync
> SPI were introduced mainly to avoid federation approach...
>

What Sync SPI are you talking about?  We don't have a Sync SPI.  We only 
have a one-way half-baked sync from AuthenticationProvider.AuthUser -> 
UserModel.

>   I am happy with AuthUserProvider

Drawing 3 boxes with lines between them does not an SPI make.

, which delegates "store" to other
> underlying UserProvider, but authentication to one or more
> AuthenticationProviders. This might help to remove the "authentication"
> related code from AuthenticationManager. So something like:
>
>                                           +--------------------+
>                             Store         |                    |
>                              +------------>  JpaUserProvider   |
>                              |            |                    |
>                              |            +--------------------+
>           +------------------+
>           |                  |
>           | AuthUserProvider |            +--------------------+
>           |                  |            |                    |
>           +------------------+            |  LDAPAuthenticationProvider  |
>                              +------------>                    |
>                             Authenticate  +--------------------+
>
>
>
> LDAPUserProvider or PropertiesFileUserProvider doesn't make much sense
> to me as implementors would need to leave almost all methods empty or
> "throw new NotImplementedException()"
>

They wouldn't leave these methods empty.  Take a look at the 
UserProvider methods.  For example

     User getUserById(String id, String realm);
     User getUserByUsername(String username, String realm);
     User getUserByEmail(String email, String realm);
     User getUserByAttribute(String name, String value, String realm);


Would not an LDAPUserProvider do an LDAP query to see if the user 
exists, then import the user into local UserProvider storage, then 
return that object?

UserProvider.verifyCredentials(User user, Credentials... credentials)

If LDAP only verifies password, then do an LDAP query, otherwise 
delegate to the local UserProvider.

If the local User is modified, then wouldn't it be prudent for the 
LDAPUserProvider to wrap return User instances so that it could register 
sync events?  Sync events that would trigger the update to get back to 
the LDAP server eventually?

IMO, UserProvider is the *perfect* place to implement a Sync API.  Out 
of the box, we would have an LDAPUserProvider which you could configure 
in the admin console.  i.e. specify connection parameters and attribute 
mappings.  Anything beyond that common use case would have to be written 
by the user.

> As I said LDAPUserProvider doesn't make much sense to me, so it's not
> needed to configure in 2 places. AFAIK in next KC version, the plan for
> stuff like SMTP and LDAP is to remove it from realm configuration and
> move it to keycloak-server.json . And also the possibility to configure
> stuff from keycloak-server.json in admin console UI.
>

If you move LDAP config to keycloak-server.json then you remove the 
notion of Keycloak being able to have multiple and distinct realms. 
Same goes with SMTP.  You might want to use different email/password for 
email login for different realms.

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


More information about the keycloak-dev mailing list