<html>
  <head>
    <meta content="text/html; charset=windows-1252"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">Few additional things, which applies
      for credentials like SPNEGO/Kerberos tokens, however I think they
      might be required for other credential types too.<br>
      <br>
      - Authentication of unknown user : For example in case of SPNEGO,
      you have just the token, but you don't know which user are you
      authenticating. User is "recognized" later once the SPNEGO token
      is successfully validated<br>
      <br>
      - More handshakes for credential validation : This is again
      related to SPNEGO, but I am sure it applies for some other
      credential types too. Instead of true/false we may need something
      like : SUCCESS, FAILED, CONTINUE. <br>
      Also the possibility to send some context info back to the client,
      so client can continue with the handshake. For the old
      federationProvider we had:<br>
      <br>
      <meta http-equiv="content-type" content="text/html;
        charset=windows-1252">
      <pre style="background-color:#ffffff;color:#000000;font-family:'DejaVu Sans Mono';font-size:9.0pt;">CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel credential);

</pre>
      I guess we need something similar for the new SPI too? Also for
      "isValid" method, I would rather return CredentialValidationOutput
      instead of just true/false. True/false is good for passwords/OTP,
      which are most widely used credential types in Keycloak, but may
      not be sufficient for other custom credential types.<br>
      <br>
      Marek<br>
      <br>
      On 16/08/16 00:57, Bill Burke wrote:<br>
    </div>
    <blockquote
      cite="mid:a59cd47b-6d17-0997-76f8-7dc62b08da0b@redhat.com"
      type="cite">
      <meta http-equiv="content-type" content="text/html;
        charset=windows-1252">
      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>
        <meta http-equiv="content-type" content="text/html;
          charset=windows-1252">
      </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>
        <meta http-equiv="content-type" content="text/html;
          charset=windows-1252">
      </p>
      <p>
        <meta http-equiv="content-type" content="text/html;
          charset=windows-1252">
      </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>
        <meta http-equiv="content-type" content="text/html;
          charset=windows-1252">
      </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&lt;String&gt; 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().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().</p>
      <p>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.</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().updateCredential. 
        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().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.</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>
      <p><br>
      </p>
      <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>