<div dir="ltr">We already have an SPI for authenticators, which allows you to create custom authenticators without modifying Keycloak code. The code in validCredentials pre-dates the authenticator SPI.</div><div class="gmail_extra"><br><div class="gmail_quote">On 15 June 2016 at 16:46, Mitya <span dir="ltr">&lt;<a href="mailto:mitya@cargosoft.ru" target="_blank">mitya@cargosoft.ru</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><span class=""><blockquote type="cite"><div dir="ltr">I&#39;m not quite following the problem. You can encode the secret/key using Base32. In fact this Keycloak already stores the secret as a Base32 encoded string. We don&#39;t strictly support hardware tokens at the moment as there&#39;s no way to specify the secret, but you can probably do that through the admin endpoints.</div></blockquote><div><br></div></span><div>Yep, I&#39;ve already done it (via custom realm resources, since there is no SPI for custom *admin* resources yet).</div><div><br></div><div>To be accurate: KeyCloak *stores* HOTP secrets as plain strings, but transfers them to phones as Base32. For example:</div><div><br></div><div>s7hAVBHOOPvAnTa3w4mh - this is what is stored in the database (plain string)</div><div>OM3W QQKW IJEE 6T2Q OZAW 4VDB GN3T I3LI - this is printed out to be entered into FreeOTP / Google Authenticator</div><div><br></div><div>When authenticating, the plain string is converted to bytes and used as a secret for HmacOTP. Since storage type is String/VARCHAR, such a secret is limited to printable characters.</div><div><br></div><div>My intention was to use the KeyCloak&#39;s standard HOTP authenticator to validate OTPs generated by hardware tokens. Unfortunately, tokens that I&#39;m working with (namely Aladdin eToken PASS) are programmed with seeds that contain arbitrary bytes, and therefore they cannot be stored into Credential&#39;s &quot;value&quot; field.</div><div><br></div><div>But now it turns out that I&#39;ll have to implement custom authenticator either way. Thus, I&#39;ll just store seeds as hex string and decode them in my authenticator before calling HmacOTP. I&#39;ll probably use different credential type, ex., &quot;hotp+&quot;, in order not to mess up with KeyCloak OTP.</div><div><br></div><div>By the way, do you think having a SPI for credential types could be a good idea (custom/proprietary OTP algorithms; custom storage format, like in my case)? At the moment, all the supported credential types (password, HOTP/TOTP etc.) are hardcoded into org.keycloak.models.utils.CredentialValidation. If we had a SPI, it would become possible to add new types without modifying KeyCloak code - and all the code that uses context.getSession().users().validCredentials(...) could make use of new credential types.</div><div><br></div><div>Cheers,</div><div>Mitya</div><span class=""><div><br></div><blockquote type="cite"><div class="gmail_extra"><br><div class="gmail_quote">On 13 June 2016 at 20:14, Mitya <span dir="ltr">&lt;<a href="mailto:mitya@cargosoft.ru" target="_blank">mitya@cargosoft.ru</a>&gt;</span> wrote:<br><blockquote type="cite"><div><div>The current KeyCloak HOTP implementation assumes that a HOTP key (aka<br>seed, aka initialization vector) is stored as string, and thus contains<br>only printable characters. However, the HOTP standard (RFC 4226)<br>doesn&#39;t impose any restrictions on key material; any arbitrary byte<br>array is acceptable.</div><div><br></div><div>Moreover, many hardware HOTP tokens are pre-programmed at the factory,<br>and do contain non-printable seeds. Even though KeyCloak doesn&#39;t<br>support hardware tokens out of the box, developers could implement it<br>by extending KeyCloak and employing existing algorithms. Unfortunately,<br>the existing convention (to store HOTP seeds as printable strings)<br>makes this impossible.</div><div><br></div><div>For the &quot;password&quot; credential type, the &quot;value&quot; field is already stored<br>as Base64. I think &quot;hotp&quot; credentials could also be stored as Base64 or<br>hex; another option would be to store the &quot;value&quot; field as BLOB (like<br>it&#39;s already done for the &quot;salt&quot; field).</div><div><br></div><div>I think I could produce a PR for this, I only need to know which<br>scenario is preferred.</div><div><br></div><div>Cheers,</div><div>Mitya</div><div><br></div></div><br>_______________________________________________<br>
keycloak-dev mailing list<br>
<a href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a><br></blockquote></div><br></div>
</blockquote></span></div></blockquote></div><br></div>