<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 28 June 2016 at 11:40, Marko Strukelj <span dir="ltr"><<a href="mailto:mstrukel@redhat.com" target="_blank">mstrukel@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div class="h5">On Tue, Jun 28, 2016 at 7:35 AM, Stian Thorgersen <span dir="ltr"><<a href="mailto:sthorger@redhat.com" target="_blank">sthorger@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote"><div><div>On 27 June 2016 at 21:26, John Dennis <span dir="ltr"><<a href="mailto:jdennis@redhat.com" target="_blank">jdennis@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div><div>On 06/27/2016 07:48 AM, Marko Strukelj wrote:<br>
> I've started work on Client Registration CLI tool. As a first step, here<br>
> is a design document describing how I imagine the tool would be used.<br>
><br>
><br>
> <a href="https://docs.google.com/document/d/18SoZ34sY_k7N8ae-WDsvo7QeI-cHkpTURIlUk5dpIhU/edit?usp=sharing" rel="noreferrer" target="_blank">https://docs.google.com/document/d/18SoZ34sY_k7N8ae-WDsvo7QeI-cHkpTURIlUk5dpIhU/edit?usp=sharing</a><br>
><br>
><br>
> I'll use this document as a spec / guide as I implement the client tool.<br>
><br>
> Within days I'll also send a link to initial ideas for Admin Client tool<br>
> which in principle should allow administrator to configure everything<br>
> that can otherwise be done through Admin Console.<br>
><br>
> Any feedback welcome.<br>
<br>
</div></div>FWIW we've already written a client registration tool for Keycloak. At<br>
the moment it is specifically targeted for SAML clients (SP, Service<br>
Provider) in Apache HTTPD but we have plans to extend it to OIDC.<br>
<br>
It is currently in Fedora and will also ship in OSP.<br>
<br>
It is hosted here:<br>
<a href="https://github.com/jdennis/keycloak-httpd-client-install" rel="noreferrer" target="_blank">https://github.com/jdennis/keycloak-httpd-client-install</a><br>
<br>
The man page for it (formatted for HTML) can be found here:<br>
<a href="https://jdennis.fedorapeople.org/doc/keycloak-httpd-client-install.html" rel="noreferrer" target="_blank">https://jdennis.fedorapeople.org/doc/keycloak-httpd-client-install.html</a><br>
<br>
The man page discusses 3 different ways you can authenticate and 2<br>
different ways client registration can be performed.<br>
<br>
I have a lot of experience with Keycloak client registration tools and<br>
have worked through many issues, I'm happy to share my experience.<br>
<br>
Here are some thoughts/issues you may want to take into account:<br>
<br>
* The tool must be capable of running without interactivity as part of a<br>
scripted installation task.<br>
<br>
* It should not depend on a home directory being available.<br>
<br>
* If a home directory is utilized how will you disambiguate any stored<br>
state belonging to a script that is run by different processes but under<br>
the same user (possibly simultaneously)? To clarify, many install tools<br>
run as the root user or some other admin user. Each invocation of these<br>
install tools can be run with entirely different parameters and may<br>
execute either in parallel or partially overlapping in time.<br></blockquote></div></div></div></div></div></blockquote><div><br></div></div></div><div>Maybe I should have included this link in the design document to make it clear to everyone what Client Registration this tool is for: <a href="http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html" target="_blank">http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html</a><br></div><div><br></div><div>It's a REST API defined by specs, and is separate from Admin REST API.</div><div> </div><div>About using home directory, the way I see it - you either a) specify all the state when executing a command, or b) you have a mechanism that allows the concept of 'session' between command invocations.</div><div> </div><div>If you use the first approach (a) then on each invocation of the command you have to specify either username:password, or a token. The client registration specification defines workflow for Initial Access Tokens, and Registration Access Tokens, which require to automatically intercept a newly issued token after each CRUD operation, and save it for any subsequent operation on the same client resource. I can't see how this could be achieved by using the first approach.</div><div><br></div><div>For the second approach (b) you need a way to communicate 'session' state. The state we are saving are just tokens associated with current user or specific clients, or specific grants. Looks to me that if multiple parallel sessions are in collision about these tokens then the cli tool itself might be used the wrong way. Namely, once the client authenticates with a login, access token and refresh token are cached. Multiple client instances can use the same access token, and the same refresh token. A thing to maybe be careful about is just properly locking the file when making changes to it. For initial access token you have to explicitly add it, and assign it an alias - you can use any random value there if you want. For registration access token they are automatically associated with initial token they were initiated from - again there should be no collision.</div></div></div></div></blockquote><div><br></div><div>I like the option to have two approaches as there are two use-cases. One is manually registering for example during development or when manually configuring an application to use Keycloak. Another is scripted. Even for scripted you may quite likely want to just add service account credentials or initial access token directly to ~/.keycloak/ rather than pass these to the commands. </div><div><br></div><div>Registration access tokens are associated with a client, not an initial access token. Also, remember the registration access token is changed on updates.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>What alternative mechanism would you suggest for storing 'session' info? We want to support Windows as well so it can't be Unix / Bash specific.</div><span class=""><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* The tool should be idempotent.<br>
<br>
* You suggest storing tokens in a cache, how do you plan on handling the<br>
case where a token expires before all operations are complete?<br>
<br>
* We also initially took the approach of caching tokens but discovered<br>
the complexity did not justify the minimal cost of obtaining a new token<br>
for each invocation. This greatly simplified the code with very little<br>
performance impact.<br>
<br>
* You do not mention what type of client you're registering. I'm<br>
assuming it's OpenID but SAML clients (SP) are equally important. The<br>
tool must be able to handle both.<br></blockquote><div><br></div></div></div><div>Marko is probably referring to the Keycloak client representation, which can be either OpenID or SAML. However, we also need to support OpenID Connect client descriptions as well as SAML entity descriptors as both are supported by client reg services.</div></div></div></div></blockquote><div><br></div></span><div>The CLI needs to know which of the client registration providers (REST endpoints) to use - there are four as described in the Client Registration documentation (<a href="http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html" target="_blank">http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html</a>)</div><div><br></div><div>Ideally the input format of the file could be recognised as only appropriate for one of these providers, and the correct provider then automatically used. But maybe we need a way to explicitly tell the tool what provider to use. For example:</div><div><br></div><div><span><p dir="ltr" style="line-height:1.38;margin-top:2pt;margin-bottom:0pt;margin-right:9pt"><span style="font-size:12px;font-family:'Courier New';color:rgb(48,57,66);vertical-align:baseline;white-space:pre-wrap">kc new --type default --name test-app --enabled true --base-url </span><a href="http://localhost:8480/test-app" style="text-decoration:none" target="_blank"><span style="font-size:12px;font-family:'Courier New';text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">http://localhost:8480/test-app</span></a><span style="font-size:12px;font-family:'Courier New';color:rgb(48,57,66);vertical-align:baseline;white-space:pre-wrap"> --redirect-uri '</span><a href="http://localhost:8480/test-app/*" style="text-decoration:none" target="_blank"><span style="font-size:12px;font-family:'Courier New';text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">http://localhost:8480/test-app/*</span></a><span style="font-size:12px;font-family:'Courier New';color:rgb(48,57,66);vertical-align:baseline;white-space:pre-wrap">' --admin-url </span><a href="http://localhost:8480/test-app/logout" style="text-decoration:none" target="_blank"><span style="font-size:12px;font-family:'Courier New';text-decoration:underline;vertical-align:baseline;white-space:pre-wrap">http://localhost:8480/test-app/logout</span></a><span style="font-size:12px;font-family:'Courier New';color:rgb(48,57,66);vertical-align:baseline;white-space:pre-wrap"> --secret password | kc create --type default -f -</span></p><p dir="ltr" style="line-height:1.38;margin-top:2pt;margin-bottom:0pt;margin-right:9pt"><br></p></span></div><div><br></div><div>Having to set <font face="monospace, monospace">--type</font> for both creating a description (<font face="monospace, monospace">kc new</font>), and pushing it to the server (<font face="monospace, monospace">kc create</font>) is not ideal.</div></div></div></div></blockquote><div><br></div><div>We can detect the difference between Keycloak client rep, SAML and OIDC json that's pretty trivial and we should do that. However, there needs to be a way to specify the provider as well as there could be custom providers added.</div><div><br></div><div>For getting the client it should by default return Keycloak client representation, but we need an option to be able to specify the provider so it can return the client installation file instead.</div><div><br></div><div>With regards to creating by passing arguments rather than a file that should only support client representation files.</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* I don't see anything in your document on how to specify the SAML metadata.<br></blockquote></span></div></div></div></blockquote><div><br></div></span><div>Instead of piping in my-client.json, you would pipe in my-client-saml.xml, possibly requiring an extra --type specifier as described above.</div><span class=""><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* I don't see anything in your document on how the user modifies the<br>
client. It appears as if you are retrieving a ClientRepresentation JSON<br>
document and expecting the user to edit it in a text editor which will<br>
then be sent back. That won't work for non-interactive installs. It also<br>
presumes the user knows how to read and modify the JSON.<br></blockquote><div><br></div></span><div>It would be nice to be able to set specific fields without having to modify JSON. We discussed that for the Admin CLI, but we should probably also add it to the client reg CLI</div></div></div></div></blockquote><div><br></div></span><div>It would be very valuable to see some of the usecases, what kind of changes people do on existing clients.</div></div></div></div></blockquote><div><br></div><div>We should support anything that is in client representation. It should just be a generic way to change json fields. For example:</div><div><br></div><div># kcreg update <client id> --set enabled=false --set baseUrl=<a href="http://new-url/myapp">http://new-url/myapp</a> --remove rootUrl</div><div><br></div><div>This would get the KC client rep, change the corresponding fields and send it back.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* Keycloak currently has a few problems with client registration and<br>
it's necessary to modify the client before it will work correctly. We<br>
currently do this via the REST API. How are you planning on handling<br>
these issues in your installer? It would be nice if the installer was<br>
aware of the Keycloak version and could apply "fix-ups" as needed based<br>
on the version.<br></blockquote><div><br></div></span><div>AFAIK you have one problem? About not all redirect URI included from the SAML entity descriptor. Is that what you are referring to or do you have other problems?</div><div><br></div><div>In either case fix-ups should be performed by the client registration services, not in the CLI.</div><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* Keycloak has two ways to register a client (client registration<br>
service vs. REST API). The two methods do not produce the same client<br>
configuration (I suspect because they do not share common code in the<br>
server). How are you planning on addressing the discrepancies?<br></blockquote><div><br></div></span><div>The task of the CLI is not to address any discrepancies. It's just invoking the client reg services. Any discrepancies should be handled by the client reg services themselves. Have you created JIRA's for these or can you list them to us?</div><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* The tool should be smart enough to produce a working client without<br>
manual intervention (i.e. the need to run admin cli commands afterwards<br>
to fix problems). Most admins won't know how to tweak the configuration.<br></blockquote><div><br></div></span><div>Can you list any you are aware of? Same comment as above applies though, it's the responsibility of the client reg services to handle this, not the CLI. Otherwise you'd have different behavior if you invoke client reg services directly rather than through the CLI.</div><span><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
* The tool should not have significant dependencies.<br></blockquote><div><br></div></span><div>It'll be a fat-jar and will have a single dependency on the JVM.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><span>
<br>
Those are the thoughts off the top of my head, as you fill out the<br>
details I'll continue to review. Recall the plan of record is for<br>
Keycloak to provide such tools which we will then utilize. The<br>
keycloak-httpd-client-install tool is a stop-gap solution until such<br>
time as "offical" tools become available.<br>
<span><font color="#888888"><br>
<br>
<br>
--<br>
John<br>
</font></span></span><span><div><div>_______________________________________________<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>
</div></div></span></blockquote></div><br></div></div>
</blockquote></div></div></div><br></div></div>
</blockquote></div><br></div></div>