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