<html>
<head>
<meta content="text/html; charset=ISO-8859-1"
http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<div class="moz-cite-prefix">On 8/19/2016 2:43 AM, Stian Thorgersen
wrote:<br>
</div>
<blockquote
cite="mid:CAJgngAeD-9nKquNjEO_8CzARiAhJMVT494t6ta1OtZ4gdbaiAQ@mail.gmail.com"
type="cite">
<div dir="ltr"><br>
<div class="gmail_extra"><br>
<div class="gmail_quote">On 18 August 2016 at 21:00, Bill
Burke <span dir="ltr"><<a moz-do-not-send="true"
href="mailto:bburke@redhat.com" target="_blank">bburke@redhat.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000">
<div>
<div class="h5">
<p><br>
</p>
<br>
<div>On 8/18/16 5:12 AM, Stian Thorgersen wrote:<br>
</div>
<blockquote type="cite">
<div dir="ltr"><br>
<div class="gmail_extra"><br>
<div class="gmail_quote">On 16 August 2016 at
00:57, Bill Burke <span dir="ltr"><<a
moz-do-not-send="true"
href="mailto:bburke@redhat.com"
target="_blank">bburke@redhat.com</a>></span>
wrote:<br>
<blockquote class="gmail_quote"
style="margin:0 0 0 .8ex;border-left:1px
#ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"> 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.
<p>* Is the user configured for a
specific credential type</p>
<p>* Is a credential valid</p>
<p>* What required actions must be taken
for an unconfigured credential type</p>
<p>* update a credential</p>
<p>How each of these events is resolved
will depend on the configuration of
the system and these interfaces:</p>
<p> </p>
<pre style="background-color:#ffffff;color:#000000;font-family:'Menlo';font-size:9.0pt"><span style="color:#000080;font-weight:bold">public interface </span>CredentialInput {
String getType();
}
</pre>
<p> </p>
<p> </p>
<pre style="background-color:#ffffff;color:#000000;font-family:'Menlo';font-size:9.0pt"><span style="color:#000080;font-weight:bold">public interface </span>CredentialInputValidator {
<span style="color:#000080;font-weight:bold">boolean </span>supportsCredentialType(String credentialType);
<span style="color:#000080;font-weight:bold">boolean </span>isConfiguredFor(RealmModel realm, UserModel user, String credentialType);
<span style="color:#000080;font-weight:bold">boolean </span>isValid(RealmModel realm, UserModel user, CredentialInput input);
}
</pre>
<p> </p>
<pre style="background-color:#ffffff;color:#000000;font-family:'Menlo';font-size:9.0pt"><span style="color:#000080;font-weight:bold">public interface </span>CredentialInputUpdater {
<span style="color:#000080;font-weight:bold">boolean </span>supportsCredentialType(String credentialType);
Set<String> requiredActionsFor(RealmModel realm, UserModel user, String credentialType);
<span style="color:#000080;font-weight:bold">void </span>updateCredential(RealmModel realm, UserModel user, CredentialInput input);
}
</pre>
<p>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.</p>
<p>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.</p>
<p>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.</p>
<p>Let's walk through an authentication
flow, specificaly for OTP.</p>
<p>1. Authenticator calls
KeycloakSession.users().isConf<wbr>iguredFor(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().</p>
<p>2. If OTP is required and not
configured for the user, the
Authenticator then calls
KeycloakSession.users().requir<wbr>edActionsFor(...).
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.</p>
<p>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().u<wbr>pdateCredential.
The first UserStorageProvider or
CredentialProvider that can handle
this credential type will save the
credential.<br>
</p>
<p>3b. If OTP is configured for user,
the OTP is obtained by the
Authenticator and
KeycloakSession.users().isVali<wbr>d()
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.</p>
<p>** Admin console and Account Service
UIs **</p>
<p>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.<br>
</p>
</div>
</blockquote>
<div>Extending admin console is fine in
community, but would be hard to support. </div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
Generic rendering from a metamodel provided by a REST
API is something we can and should support. It won't be
completely pretty, but should work for most things. If
we don't want to support Angular extensions, then the
user can just completely punt and have a completely
different web app to configure a specific component.</div>
</blockquote>
<div><br>
</div>
<div>I didn't say we shouldn't support extensions to the UI,
but we need to consider how to do it. If we tie it to much
to Angular 1 specifics than it becomes even harder to
migrate to Angular 2.</div>
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><span class=""><br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div>Especially as we would eventually have to
move to AngularJS 2.0, which drastically
changes things. </div>
</div>
</div>
</div>
</blockquote>
<br>
</span> Moving to Angular 2 seems daunting. <br>
<br>
<a moz-do-not-send="true"
href="https://angular.io/docs/ts/latest/guide/upgrade.html#"
target="_blank">https://angular.io/docs/ts/<wbr>latest/guide/upgrade.html#</a></div>
</blockquote>
<div><br>
</div>
<div>Yep, it's a complete rewrite! Sucks.</div>
</div>
</div>
</div>
</blockquote>
Bill, you may not be aware that I'm coming to Boston next month to
attend the Angular conference. There are sessions on migrating, so
at least I should be able to get on the right track and make an
educated assessment of the suckiness.<br>
<blockquote
cite="mid:CAJgngAeD-9nKquNjEO_8CzARiAhJMVT494t6ta1OtZ4gdbaiAQ@mail.gmail.com"
type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><span class=""><br>
<br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div>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?</div>
<div><br>
</div>
</div>
</div>
</div>
</blockquote>
<br>
<br>
</span> Look at the old ldap provider for an example of
overriding a specific component UI over a fallback
generic one. It just has a more specific route than the
generic page. </div>
</blockquote>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><span class=""><br>
<br>
<blockquote type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div>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.<br>
</div>
</div>
</div>
</div>
</blockquote>
</span> Again, we can focus on generic rendering for
Account Service. Then it will translate quite easily to
whatever we do here.</div>
</blockquote>
<div><br>
</div>
<div>I don't think generic rendering works for account
service as it wants to be more end user friendly. Generic
rendering is probably OK for the admin console most of the
time, but it's never going to be brilliant for usability.</div>
</div>
</div>
</div>
</blockquote>
I've done quite a bit of work with generic rendering. The richness
and usability of the resulting UI tends to be a function of the
richness of the metadata that generates it. In other words, the
more you describe what you are rendering the better you can render
it. We'll just have to see how much work we want to put into it.<br>
<blockquote
cite="mid:CAJgngAeD-9nKquNjEO_8CzARiAhJMVT494t6ta1OtZ4gdbaiAQ@mail.gmail.com"
type="cite">
<div dir="ltr">
<div class="gmail_extra">
<div class="gmail_quote">
<div> </div>
<blockquote class="gmail_quote" style="margin:0 0 0
.8ex;border-left:1px #ccc solid;padding-left:1ex">
<div bgcolor="#FFFFFF" text="#000000"><span class="HOEnZb"><font
color="#888888"><br>
<br>
Bill<br>
</font></span></div>
</blockquote>
</div>
<br>
</div>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<br>
<pre wrap="">_______________________________________________
keycloak-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:keycloak-dev@lists.jboss.org">keycloak-dev@lists.jboss.org</a>
<a class="moz-txt-link-freetext" href="https://lists.jboss.org/mailman/listinfo/keycloak-dev">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a></pre>
</blockquote>
<br>
</body>
</html>