[keycloak-dev] new credential SPI

Stian Thorgersen sthorger at redhat.com
Thu Aug 18 05:12:30 EDT 2016


On 16 August 2016 at 00:57, Bill Burke <bburke at redhat.com> wrote:

> I'm currently working on a new credential SPI that will replace existing
> methods on UserProvider and UserModel, as well as replacing
> UserCredentialModel, etc.  This is a work in progress where we may see
> multiple iterations in master.  I hope to remain backward compatible, but
> can't guarentee I won't break existing User Federation Providers.  Here's
> an initial writeup to explain things.  Credentials revolve around these 4
> events that are initiated by authentication flows, the admin console, and
> the account service.
>
> * Is the user configured for a specific credential type
>
> * Is a credential valid
>
> * What required actions must be taken for an unconfigured credential type
>
> * update a credential
>
> How each of these events is resolved will depend on the configuration of
> the system and these interfaces:
>
> public interface CredentialInput {
>     String getType();
> }
>
> public interface CredentialInputValidator {
>     boolean supportsCredentialType(String credentialType);
>     boolean isConfiguredFor(RealmModel realm, UserModel user, String credentialType);
>     boolean isValid(RealmModel realm, UserModel user, CredentialInput input);
>
> }
>
> public interface CredentialInputUpdater {
>     boolean supportsCredentialType(String credentialType);
>     Set<String> requiredActionsFor(RealmModel realm, UserModel user, String credentialType);
>     void updateCredential(RealmModel realm, UserModel user, CredentialInput input);
> }
>
>
> Two different types of components will be able to implement these
> interfaces.  UserStorageProviders (user federation) and
> CredentialProviders.  CredentialProviders are components configured at the
> realm level.  CredentialProviders are responsible for managing one or more
> types of credential types and are the bridge between CredentialInput and
> where the credential is stored.  UserStorageProvider is always asked first
> whether it can complete the requested action, then CredentialProviders are
> queried in order of their priority.
>
> Each UserStorageProvider and/or CredentialProvider can implement the
> OnUserCache callback interface discussed in my previous custom caching
> email.  This allows each credential type to decide whether it will be
> cached or not along with the user.  For example, HOTP cannot be cached.
>
> So, for example, there will be a KeycloakMobileOTPProvider.  This deals
> with Google Authenticator and FreeOTP as well as storing these things
> within Keycloak storage, it also looks at the OTP policy of the realm to
> determine how to update and store the OTP secret and stuff.  There is also
> a KeycloakPasswordProvider which hooks into Keycloak storage and the
> PasswordPolicies set up by the realm.  When a user is cached, the
> KeycloakPasswordProvider will add the hashed password to the user cache,
> the KeycloakMobileOTPProvider will add the OTP secret to cache if its  not
> HOTP and needs to maintain a counter.
>
> Let's walk through an authentication flow, specificaly for OTP.
>
> 1. Authenticator calls KeycloakSession.users().isConfiguredFor(realm,
> user, "OTP").  If the user was loaded by a UserStorageProvider and that
> provider implements the CredentialInputValidator interface,
> isConfiguredFor() is called on that.  If that returns false, each
> CredentialProvider is iterated on to call isConfiguredFor().
>
> 2. If OTP is required and not configured for the user, the Authenticator
> then calls KeycloakSession.users().requiredActionsFor(...).  Again,
> UserStorageProvider is queried first, then the CredneitalProviders.  The
> first provider that returns a non-empty set will end the query and the set
> of required actions will be returned.
>
> 3a. Let's say that in this particular example, the generic OTP Requried
> Action screen is invoked.  In that case, this required action provider
> callsKeycloakSession.users().updateCredential.  The first
> UserStorageProvider or CredentialProvider that can handle this credential
> type will save the credential.
>
> 3b. If OTP is configured for user, the OTP is obtained by the
> Authenticator and KeycloakSession.users().isValid() method is called.
> Again, UserStorageProvider first, then each CredentialProvider.  Each
> provider is queried until one returns true or the list is exhausted.  FYI,
> This algorithm allows for multiple OTP authenticators per user.
>
> ** Admin console and Account Service UIs **
>
> Like we do for other components, the UserStorageProvider or
> CredentialProvider can optionally provide a list of
> ProviderConfigProperties for the admin console and/or account serviceso
> that it can create a credential for a specific user.  There will be
> separate property lists for admin console and account service.  If a
> specific custom screen is desired, I'm pretty sure we can just allow the
> develoepr to plug in their own $routeProvider for the admin console.  We
> don't have a pluggable mechanism for the account service yet (or a way to
> generic render either).  This will need to be developed eventually.
>
Extending admin console is fine in community, but would be hard to support.
Especially as we would eventually have to move to AngularJS 2.0, which
drastically changes things. I also wonder if we should provide an higher
level extension to register extensions than having to do $routeProviders
etc as that sounds like a fairly low level approach. Do you have any
example?

Account service should be completely scrapped and replaced with something
more modern. The UI needs a complete revamp and it should also be changed
to AngularJS and REST service to make it more customizable and extensible.

>
>
> _______________________________________________
> keycloak-dev mailing list
> keycloak-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/keycloak-dev/attachments/20160818/c68b6cb7/attachment.html 


More information about the keycloak-dev mailing list