<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 30 June 2016 at 20:06, Bruno Oliveira <span dir="ltr">&lt;<a href="mailto:bruno@abstractj.org" target="_blank">bruno@abstractj.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Sorry about the duplicated e-mail.<span class=""><br><br><div class="gmail_quote"><div dir="ltr">On Wed, Jun 29, 2016, 11:21 PM Stian Thorgersen &lt;<a href="mailto:sthorger@redhat.com" target="_blank">sthorger@redhat.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 30 June 2016 at 08:08, Bruno Oliveira <span dir="ltr">&lt;<a href="mailto:bruno@abstractj.org" target="_blank">bruno@abstractj.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">What I suggested was based on what I saw at our current proposal:<br>
<br>
$ kcreg login -r master -u manage-client<br>
Server to connect to (<a href="http://localhost:8080/auth" rel="noreferrer" target="_blank">http://localhost:8080/auth</a>):<br>
Password:<br>
<br>
If you want to automate it for example in a shell script, unless I&#39;m<br>
mistaken, you have to provide user&#39;s password or obtain initial access<br>
token through console. If we&#39;re assuming that&#39;s the default<br>
flow for automated scripts should be obtaining an initial access token<br>
from console first, that&#39;s fine.<br></blockquote><div><br></div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Yes, the password is just for manual use and wouldn&#39;t be cached or anything like that.</div></div></div></div><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">
<br>
Flow for encryption:<br>
<br>
1. Admin client retrieve the public key from the server<br>
2. Admin client encrypt&#39;s whatever data is sensitive<br>
3. Server decrypt&#39;s it<br></blockquote><div><br></div></div></div></div><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div>Isn&#39;t that only going to hide the password? The encrypted password could still be used as the server would accept/decrypt it.</div></div></div></div></blockquote></div><div><br></div></span><div>Not only passwords, but username as well. Into other words any sensitive data.</div><div><br></div><div>I don&#39;t follow you on this. The server will decrypt and validate those credentials.</div><div><br></div><div>Anyways, this is just an idea, if it doesn&#39;t worth it, never mind.</div></blockquote><div><br></div><div>I don&#39;t think it&#39;s needed in this case as we won&#39;t be storing username/passwords. I&#39;d still like to understand/talk about what you are proposing though, but we should have that discussion in a separate thread ;)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><div><br></div><div><br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><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><div><br>
On 2016-06-30, Stian Thorgersen wrote:<br>
&gt; I can&#39;t see why we should consider it though:<br>
&gt;<br>
&gt; a) We have service account support, initial access tokens, offline tokens,<br>
&gt; etc.. All designed so credentials don&#39;t need to be stored. Using a user<br>
&gt; account directly is horrible as not only are you potentially exposing the<br>
&gt; credentials, you&#39;re also giving all permissions of the user to the<br>
&gt; automation. Using tokens or service account you can limit what permissions<br>
&gt; the automation has.<br>
&gt; b) If the credentials are encrypted, you&#39;ll also need to unlock the<br>
&gt; vault/encrypted file. How would you suggest we do that? I can&#39;t see the<br>
&gt; full flow here.<br>
&gt;<br>
&gt; On 30 June 2016 at 07:15, Bruno Oliveira &lt;<a href="mailto:bruno@abstractj.org" target="_blank">bruno@abstractj.org</a>&gt; wrote:<br>
&gt;<br>
&gt; &gt; Yes, the encrypted data goes into public repository with .travis.yaml file.<br>
&gt; &gt; Only the Travis server is able to decrypt such data and validate it[1][2].<br>
&gt; &gt;<br>
&gt; &gt; Like I mentioned, not a blocker, but maybe something to take into<br>
&gt; &gt; consideration.<br>
&gt; &gt;<br>
&gt; &gt; [1] -<br>
&gt; &gt; <a href="https://docs.travis-ci.com/user/encryption-keys/#Notifications-Example" rel="noreferrer" target="_blank">https://docs.travis-ci.com/user/encryption-keys/#Notifications-Example</a><br>
&gt; &gt; [2] - <a href="https://github.com/twbs/bootstrap/blob/master/.travis.yml#L30-L32" rel="noreferrer" target="_blank">https://github.com/twbs/bootstrap/blob/master/.travis.yml#L30-L32</a><br>
&gt; &gt;<br>
&gt; &gt; On 2016-06-30, Stian Thorgersen wrote:<br>
&gt; &gt; &gt; The encryption support in Travis isn&#39;t that so you can encrypt sensitive<br>
&gt; &gt; &gt; details that goes into .travis.yaml which is public through the repo?<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; On 30 June 2016 at 06:52, Stian Thorgersen &lt;<a href="mailto:sthorger@redhat.com" target="_blank">sthorger@redhat.com</a>&gt; wrote:<br>
&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; I don&#39;t see the need for that. For the client registration CLI we will<br>
&gt; &gt; &gt; &gt; support initial access tokens as well as service accounts with<br>
&gt; &gt; pub/priv key<br>
&gt; &gt; &gt; &gt; authentication. For admin cli we&#39;ll support service accounts. No one<br>
&gt; &gt; should<br>
&gt; &gt; &gt; &gt; be using username/password combined with automated jobs.<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt; On 29 June 2016 at 21:49, Bruno Oliveira &lt;<a href="mailto:bruno@abstractj.org" target="_blank">bruno@abstractj.org</a>&gt; wrote:<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; I&#39;m not sure if it&#39;s part of the scope for now. But<br>
&gt; &gt; &gt; &gt;&gt; thinking about situations where you have to automate jobs plus provide<br>
&gt; &gt; &gt; &gt;&gt; credentials without exposing them.<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; My suggestion, even if it&#39;s not part of the scope for now is to<br>
&gt; &gt; encrypt<br>
&gt; &gt; &gt; &gt;&gt; it,<br>
&gt; &gt; &gt; &gt;&gt; like travis does[1]. I know that our plan is to deal of access token,<br>
&gt; &gt; &gt; &gt;&gt; but would be nice to not expose credentials not even a single time.<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; [1] - <a href="https://docs.travis-ci.com/user/encryption-keys/" rel="noreferrer" target="_blank">https://docs.travis-ci.com/user/encryption-keys/</a><br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; On 2016-06-29, Stian Thorgersen wrote:<br>
&gt; &gt; &gt; &gt;&gt; &gt; On 28 June 2016 at 11:40, Marko Strukelj &lt;<a href="mailto:mstrukel@redhat.com" target="_blank">mstrukel@redhat.com</a>&gt;<br>
&gt; &gt; wrote:<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; On Tue, Jun 28, 2016 at 7:35 AM, Stian Thorgersen &lt;<br>
&gt; &gt; &gt; &gt;&gt; <a href="mailto:sthorger@redhat.com" target="_blank">sthorger@redhat.com</a>&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; wrote:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; On 27 June 2016 at 21:26, John Dennis &lt;<a href="mailto:jdennis@redhat.com" target="_blank">jdennis@redhat.com</a>&gt;<br>
&gt; &gt; wrote:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; On 06/27/2016 07:48 AM, Marko Strukelj wrote:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; I&#39;ve started work on Client Registration CLI tool. As a first<br>
&gt; &gt; &gt; &gt;&gt; step,<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; here<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; is a design document describing how I imagine the tool would<br>
&gt; &gt; be<br>
&gt; &gt; &gt; &gt;&gt; used.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; <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>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; I&#39;ll use this document as a spec / guide as I implement the<br>
&gt; &gt; client<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; tool.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; Within days I&#39;ll also send a link to initial ideas for Admin<br>
&gt; &gt; &gt; &gt;&gt; Client<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; tool<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; which in principle should allow administrator to configure<br>
&gt; &gt; &gt; &gt;&gt; everything<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; that can otherwise be done through Admin Console.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; &gt; Any feedback welcome.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; FWIW we&#39;ve already written a client registration tool for<br>
&gt; &gt; Keycloak.<br>
&gt; &gt; &gt; &gt;&gt; At<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; the moment it is specifically targeted for SAML clients (SP,<br>
&gt; &gt; Service<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; Provider) in Apache HTTPD but we have plans to extend it to<br>
&gt; &gt; OIDC.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; It is currently in Fedora and will also ship in OSP.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; It is hosted here:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; <a href="https://github.com/jdennis/keycloak-httpd-client-install" rel="noreferrer" target="_blank">https://github.com/jdennis/keycloak-httpd-client-install</a><br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; The man page for it (formatted for HTML) can be found here:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; <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>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; The man page discusses 3 different ways you can authenticate<br>
&gt; &gt; and 2<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; different ways client registration can be performed.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; I have a lot of experience with Keycloak client registration<br>
&gt; &gt; tools<br>
&gt; &gt; &gt; &gt;&gt; and<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; have worked through many issues, I&#39;m happy to share my<br>
&gt; &gt; experience.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; Here are some thoughts/issues you may want to take into account:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * The tool must be capable of running without interactivity as<br>
&gt; &gt; part<br>
&gt; &gt; &gt; &gt;&gt; of a<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; scripted installation task.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * It should not depend on a home directory being available.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * If a home directory is utilized how will you disambiguate any<br>
&gt; &gt; &gt; &gt;&gt; stored<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; state belonging to a script that is run by different processes<br>
&gt; &gt; but<br>
&gt; &gt; &gt; &gt;&gt; under<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; the same user (possibly simultaneously)? To clarify, many<br>
&gt; &gt; install<br>
&gt; &gt; &gt; &gt;&gt; tools<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; run as the root user or some other admin user. Each invocation<br>
&gt; &gt; of<br>
&gt; &gt; &gt; &gt;&gt; these<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; install tools can be run with entirely different parameters and<br>
&gt; &gt; may<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; execute either in parallel or partially overlapping in time.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; Maybe I should have included this link in the design document to<br>
&gt; &gt; make<br>
&gt; &gt; &gt; &gt;&gt; it<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; clear to everyone what Client Registration this tool is for:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; <a href="http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html" rel="noreferrer" target="_blank">http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html</a><br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; It&#39;s a REST API defined by specs, and is separate from Admin REST<br>
&gt; &gt; API.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; About using home directory, the way I see it - you either a)<br>
&gt; &gt; specify<br>
&gt; &gt; &gt; &gt;&gt; all<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; the state when executing a command, or b) you have a mechanism<br>
&gt; &gt; that<br>
&gt; &gt; &gt; &gt;&gt; allows<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; the concept of &#39;session&#39; between command invocations.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; If you use the first approach (a) then on each invocation of the<br>
&gt; &gt; &gt; &gt;&gt; command<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; you have to specify either username:password, or a token. The<br>
&gt; &gt; client<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; registration specification defines workflow for Initial Access<br>
&gt; &gt; &gt; &gt;&gt; Tokens, and<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; Registration Access Tokens, which require to automatically<br>
&gt; &gt; intercept a<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; newly issued token after each CRUD operation, and save it for any<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; subsequent operation on the same client resource. I can&#39;t see how<br>
&gt; &gt; this<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; could be achieved by using the first approach.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; For the second approach (b) you need a way to communicate<br>
&gt; &gt; &#39;session&#39;<br>
&gt; &gt; &gt; &gt;&gt; state.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; The state we are saving are just tokens associated with current<br>
&gt; &gt; user<br>
&gt; &gt; &gt; &gt;&gt; or<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; specific clients, or specific grants. Looks to me that if multiple<br>
&gt; &gt; &gt; &gt;&gt; parallel<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; sessions are in collision about these tokens then the cli tool<br>
&gt; &gt; itself<br>
&gt; &gt; &gt; &gt;&gt; might<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; be used the wrong way. Namely, once the client authenticates with<br>
&gt; &gt; a<br>
&gt; &gt; &gt; &gt;&gt; login,<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; access token and refresh token are cached. Multiple client<br>
&gt; &gt; instances<br>
&gt; &gt; &gt; &gt;&gt; can<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; use the same access token, and the same refresh token. A thing to<br>
&gt; &gt; &gt; &gt;&gt; maybe be<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; careful about is just properly locking the file when making<br>
&gt; &gt; changes<br>
&gt; &gt; &gt; &gt;&gt; to it.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; For initial access token you have to explicitly add it, and<br>
&gt; &gt; assign it<br>
&gt; &gt; &gt; &gt;&gt; an<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; alias - you can use any random value there if you want. For<br>
&gt; &gt; &gt; &gt;&gt; registration<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; access token they are automatically associated with initial token<br>
&gt; &gt; &gt; &gt;&gt; they were<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; initiated from - again there should be no collision.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; I like the option to have two approaches as there are two use-cases.<br>
&gt; &gt; &gt; &gt;&gt; One is<br>
&gt; &gt; &gt; &gt;&gt; &gt; manually registering for example during development or when manually<br>
&gt; &gt; &gt; &gt;&gt; &gt; configuring an application to use Keycloak. Another is scripted.<br>
&gt; &gt; Even<br>
&gt; &gt; &gt; &gt;&gt; for<br>
&gt; &gt; &gt; &gt;&gt; &gt; scripted you may quite likely want to just add service account<br>
&gt; &gt; &gt; &gt;&gt; credentials<br>
&gt; &gt; &gt; &gt;&gt; &gt; or initial access token directly to ~/.keycloak/ rather than pass<br>
&gt; &gt; these<br>
&gt; &gt; &gt; &gt;&gt; to<br>
&gt; &gt; &gt; &gt;&gt; &gt; the commands.<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; Registration access tokens are associated with a client, not an<br>
&gt; &gt; initial<br>
&gt; &gt; &gt; &gt;&gt; &gt; access token. Also, remember the registration access token is<br>
&gt; &gt; changed on<br>
&gt; &gt; &gt; &gt;&gt; &gt; updates.<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; What alternative mechanism would you suggest for storing &#39;session&#39;<br>
&gt; &gt; &gt; &gt;&gt; info?<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; We want to support Windows as well so it can&#39;t be Unix / Bash<br>
&gt; &gt; &gt; &gt;&gt; specific.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * The tool should be idempotent.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * You suggest storing tokens in a cache, how do you plan on<br>
&gt; &gt; &gt; &gt;&gt; handling the<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; case where a token expires before all operations are complete?<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * We also initially took the approach of caching tokens but<br>
&gt; &gt; &gt; &gt;&gt; discovered<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; the complexity did not justify the minimal cost of obtaining a<br>
&gt; &gt; new<br>
&gt; &gt; &gt; &gt;&gt; token<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; for each invocation. This greatly simplified the code with very<br>
&gt; &gt; &gt; &gt;&gt; little<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; performance impact.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * You do not mention what type of client you&#39;re registering. I&#39;m<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; assuming it&#39;s OpenID but SAML clients (SP) are equally<br>
&gt; &gt; important.<br>
&gt; &gt; &gt; &gt;&gt; The<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; tool must be able to handle both.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; Marko is probably referring to the Keycloak client<br>
&gt; &gt; representation,<br>
&gt; &gt; &gt; &gt;&gt; which<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; can be either OpenID or SAML. However, we also need to support<br>
&gt; &gt; OpenID<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; Connect client descriptions as well as SAML entity descriptors as<br>
&gt; &gt; &gt; &gt;&gt; both are<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; supported by client reg services.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; The CLI needs to know which of the client registration providers<br>
&gt; &gt; (REST<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; endpoints) to use - there are four as described in the Client<br>
&gt; &gt; &gt; &gt;&gt; Registration<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; documentation (<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; <a href="http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html" rel="noreferrer" target="_blank">http://keycloak.github.io/docs/userguide/keycloak-server/html/client-registration.html</a><br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; )<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; Ideally the input format of the file could be recognised as only<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; appropriate for one of these providers, and the correct provider<br>
&gt; &gt; then<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; automatically used. But maybe we need a way to explicitly tell the<br>
&gt; &gt; &gt; &gt;&gt; tool<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; what provider to use. For example:<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; kc new --type default --name test-app --enabled true --base-url<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; <a href="http://localhost:8480/test-app" rel="noreferrer" target="_blank">http://localhost:8480/test-app</a> --redirect-uri &#39;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; <a href="http://localhost:8480/test-app/*" rel="noreferrer" target="_blank">http://localhost:8480/test-app/*</a>&#39; --admin-url<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; <a href="http://localhost:8480/test-app/logout" rel="noreferrer" target="_blank">http://localhost:8480/test-app/logout</a> --secret password | kc<br>
&gt; &gt; create<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; --type default -f -<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; Having to set --type for both creating a description (kc new), and<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; pushing it to the server (kc create) is not ideal.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; We can detect the difference between Keycloak client rep, SAML and<br>
&gt; &gt; OIDC<br>
&gt; &gt; &gt; &gt;&gt; &gt; json that&#39;s pretty trivial and we should do that. However, there<br>
&gt; &gt; needs<br>
&gt; &gt; &gt; &gt;&gt; to<br>
&gt; &gt; &gt; &gt;&gt; &gt; be a way to specify the provider as well as there could be custom<br>
&gt; &gt; &gt; &gt;&gt; providers<br>
&gt; &gt; &gt; &gt;&gt; &gt; added.<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; For getting the client it should by default return Keycloak client<br>
&gt; &gt; &gt; &gt;&gt; &gt; representation, but we need an option to be able to specify the<br>
&gt; &gt; &gt; &gt;&gt; provider so<br>
&gt; &gt; &gt; &gt;&gt; &gt; it can return the client installation file instead.<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; With regards to creating by passing arguments rather than a file<br>
&gt; &gt; that<br>
&gt; &gt; &gt; &gt;&gt; &gt; should only support client representation files.<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * I don&#39;t see anything in your document on how to specify the<br>
&gt; &gt; SAML<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; metadata.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; Instead of piping in my-client.json, you would pipe in<br>
&gt; &gt; &gt; &gt;&gt; my-client-saml.xml,<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; possibly requiring an extra --type specifier as described above.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * I don&#39;t see anything in your document on how the user<br>
&gt; &gt; modifies the<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; client. It appears as if you are retrieving a<br>
&gt; &gt; ClientRepresentation<br>
&gt; &gt; &gt; &gt;&gt; JSON<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; document and expecting the user to edit it in a text editor<br>
&gt; &gt; which<br>
&gt; &gt; &gt; &gt;&gt; will<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; then be sent back. That won&#39;t work for non-interactive<br>
&gt; &gt; installs. It<br>
&gt; &gt; &gt; &gt;&gt; also<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; presumes the user knows how to read and modify the JSON.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; It would be nice to be able to set specific fields without<br>
&gt; &gt; having to<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; modify JSON. We discussed that for the Admin CLI, but we should<br>
&gt; &gt; &gt; &gt;&gt; probably<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; also add it to the client reg CLI<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; It would be very valuable to see some of the usecases, what kind<br>
&gt; &gt; of<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt; changes people do on existing clients.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; We should support anything that is in client representation. It<br>
&gt; &gt; should<br>
&gt; &gt; &gt; &gt;&gt; just<br>
&gt; &gt; &gt; &gt;&gt; &gt; be a generic way to change json fields. For example:<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; # kcreg update &lt;client id&gt; --set enabled=false --set baseUrl=<br>
&gt; &gt; &gt; &gt;&gt; &gt; <a href="http://new-url/myapp" rel="noreferrer" target="_blank">http://new-url/myapp</a> --remove rootUrl<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; This would get the KC client rep, change the corresponding fields<br>
&gt; &gt; and<br>
&gt; &gt; &gt; &gt;&gt; send<br>
&gt; &gt; &gt; &gt;&gt; &gt; it back.<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * Keycloak currently has a few problems with client<br>
&gt; &gt; registration and<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; it&#39;s necessary to modify the client before it will work<br>
&gt; &gt; correctly.<br>
&gt; &gt; &gt; &gt;&gt; We<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; currently do this via the REST API. How are you planning on<br>
&gt; &gt; handling<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; these issues in your installer? It would be nice if the<br>
&gt; &gt; installer<br>
&gt; &gt; &gt; &gt;&gt; was<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; aware of the Keycloak version and could apply &quot;fix-ups&quot; as<br>
&gt; &gt; needed<br>
&gt; &gt; &gt; &gt;&gt; based<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; on the version.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; AFAIK you have one problem? About not all redirect URI included<br>
&gt; &gt; from<br>
&gt; &gt; &gt; &gt;&gt; the<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; SAML entity descriptor. Is that what you are referring to or do<br>
&gt; &gt; you<br>
&gt; &gt; &gt; &gt;&gt; have<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; other problems?<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; In either case fix-ups should be performed by the client<br>
&gt; &gt; registration<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; services, not in the CLI.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * Keycloak has two ways to register a client (client<br>
&gt; &gt; registration<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; service vs. REST API). The two methods do not produce the same<br>
&gt; &gt; &gt; &gt;&gt; client<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; configuration (I suspect because they do not share common code<br>
&gt; &gt; in<br>
&gt; &gt; &gt; &gt;&gt; the<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; server). How are you planning on addressing the discrepancies?<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; The task of the CLI is not to address any discrepancies. It&#39;s<br>
&gt; &gt; just<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; invoking the client reg services. Any discrepancies should be<br>
&gt; &gt; &gt; &gt;&gt; handled by<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; the client reg services themselves. Have you created JIRA&#39;s for<br>
&gt; &gt; &gt; &gt;&gt; these or<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; can you list them to us?<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * The tool should be smart enough to produce a working client<br>
&gt; &gt; &gt; &gt;&gt; without<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; manual intervention (i.e. the need to run admin cli commands<br>
&gt; &gt; &gt; &gt;&gt; afterwards<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; to fix problems). Most admins won&#39;t know how to tweak the<br>
&gt; &gt; &gt; &gt;&gt; configuration.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; Can you list any you are aware of? Same comment as above applies<br>
&gt; &gt; &gt; &gt;&gt; though,<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; it&#39;s the responsibility of the client reg services to handle<br>
&gt; &gt; this,<br>
&gt; &gt; &gt; &gt;&gt; not the<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; CLI. Otherwise you&#39;d have different behavior if you invoke<br>
&gt; &gt; client reg<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; services directly rather than through the CLI.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; * The tool should not have significant dependencies.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt; It&#39;ll be a fat-jar and will have a single dependency on the JVM.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; Those are the thoughts off the top of my head, as you fill out<br>
&gt; &gt; the<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; details I&#39;ll continue to review. Recall the plan of record is<br>
&gt; &gt; for<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; Keycloak to provide such tools which we will then utilize. The<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; keycloak-httpd-client-install tool is a stop-gap solution until<br>
&gt; &gt; such<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; time as &quot;offical&quot; tools become available.<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; --<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; John<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; _______________________________________________<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; keycloak-dev mailing list<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; <a href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a><br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; &gt; _______________________________________________<br>
&gt; &gt; &gt; &gt;&gt; &gt; keycloak-dev mailing list<br>
&gt; &gt; &gt; &gt;&gt; &gt; <a href="mailto:keycloak-dev@lists.jboss.org" target="_blank">keycloak-dev@lists.jboss.org</a><br>
&gt; &gt; &gt; &gt;&gt; &gt; <a href="https://lists.jboss.org/mailman/listinfo/keycloak-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/mailman/listinfo/keycloak-dev</a><br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; --<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;&gt; abstractj<br>
&gt; &gt; &gt; &gt;&gt; PGP: 0x84DC9914<br>
&gt; &gt; &gt; &gt;&gt;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt; &gt; &gt;<br>
&gt; &gt;<br>
&gt; &gt; --<br>
&gt; &gt;<br>
&gt; &gt; abstractj<br>
&gt; &gt; PGP: 0x84DC9914<br>
&gt; &gt;<br>
<br>
</div></div>--<br>
<br>
abstractj<br>
PGP: 0x84DC9914<br>
</blockquote></div></div></div></blockquote></div>
</div></div></blockquote></div><br></div></div>