[keycloak-dev] kcinit console sso tool

Bill Burke bburke at redhat.com
Mon Mar 12 13:59:12 EDT 2018


On Mon, Mar 12, 2018 at 10:16 AM, Stian Thorgersen <sthorger at redhat.com> wrote:
> Very cool. A few questions/comments:
>
> * As it's Java based it does make it harder to package/install. Compare 'oc'
> tool for instance to our 'kcadmin' and 'kcclient' tools. Not sure how
> realistic it would be to write our CLI tools in for instance Go though.
>

Its a pretty simple tool so it could be ported.  The only thing that
might be a tiny bit challenging is making sure there's crypto stuff
available in another language to encrypt/decrypt token files.  Might
be a nice little project for me to learn Go.

> * I assume the console display is optional and it basically means that you
> can only use authenticators that support this rather than all authenticators
> require to implement it.
>

I don't have a switch to launch browser, but, I could as this
functionality is already implemented.  Not sure if that would be
portable to Go or another language though.  Java has a facility to
automatically launch browser (I think you know that already as you
wrote KeycloakInstalled).

BTW, what sucks about a browser login is that you have to manually
kill the browser window after you complete the login.

> * Not sure I fully understand the user experience with the encrypted
> password file. How does this compare to kinit and ssh-agent for instance?
> They both allow unlocking automatically through the regular OS login I
> believe. For 'kcadmin' and 'kcclient' we don't currently protect the tokens
> so we should probably consider aligning these approaches (probably even
> getting rid of the auth stuff there in favour of kcinit).
>

I just read up on kinit and ssh-agent.  Have you actually used either
of these before(I haven't)?  I don't think they work as you think they
do.

For instance, ssh-agent is a bit convoluted and requires IPC
communication with a background process using a file-based socket.
The background process holds private keys in memory which must be
unlocked and loaded with a password when you boot your windows manager
or your shell.  The socket used must be set as an environment variable
before you can invoke ssh in your shell.  I think when you invoke ssh,
it looks for this environment variable and works with the ssh-agent to
establish a connection over the local file socket.

For kinit, I think to have a global login for the entire machine, it
creates a keytab file which has file permissions readable by any
process started by the user.  And the keytab contains the tickets.
This is no different than what we do now for kcadmin.

The current solution I have is only for creating an sso session for
the current shell and any processes run within the shell would be able
to figure out how to access the encrypted token files.


> * Should we consider merging all our CLIs into one CLI? Just 'kc' instead of
> 'kcinit', 'kcadmin' and 'kcclient'? If we someone could get this stuff in Go
> and get native binaries that'd be even easier for users to use.
>

kcadmin and kcclient should be merged.  kcinit should be a separate
small generic reusable utility.


> On 12 March 2018 at 14:29, Bill Burke <bburke at redhat.com> wrote:
>>
>> I'm finally finishing the generic console login tool I've been
>> promising and working on for awhile now.  Its an extension of
>> KeycloakInstalled, but it works entirely on the command line and
>> doesn't require a browser.  Its all text input and output in your
>> command line console to login.  All driven by the server and rendered
>> by the utility.   Supports localization just like the browser too.
>>
>> * To enable this a simple challenge-based protocol was implemented.
>> OAuth Code to token flow is required.
>>
>>  Authenticator returns 401 with a WWW-Authenticate header with value of
>>
>> X-Text-Form-Challenge callback="{url}" param="username"
>> label="Username: " mask="false"
>>
>> param/label/mask are input parameter definitions that require command
>> line console input and can be repeated for each input parameter you
>> require from the console.  Label is what should be outputed to the
>> console.  If mask is true, this means it is a password field and
>> should be hidden on input.
>>
>> If the Response contains "text/plain" content, then that should be
>> outputed before command input is asked for.  Client should loop and
>> render/ask for input until a 302 response is returned that contains a
>> "code" parameter.  Then regular OAuth is used to get the token.
>>
>> * The access and refresh token is stored locally in a password
>> protected file (like ssh does). This file is checked before login is
>> initiated to see if the user is still logged in.
>>
>> * If logged in, and the client has permission, the kcinit tool can
>> also perform token exchange to obtain tokens for other clients.  It
>> stores these tokens in password protected files on local disk.
>>
>> * I have extended the OAuth layer on the server to support the OIDC
>> "display" parameter. (It just stores this value in the AuthSession.
>> I'm also in the process to refactor all the built-in Authenticators
>> and Required Actions to support the "display" parameter and use the
>> texts protocol described above if the "display" parameter is
>> "console".
>>
>> * kcinit is implemented via Java and a shell and windows batch
>> scripts.  There's also a wrapper template script that can be used to
>> secure existing command line tools.  here's example usage with the
>> target app command being `oc`.
>>
>> $ . kcinit
>>
>> Initially you will be prompted for the "local password" that protects
>> token files on local disk.  If you do not "source" this script (with a
>> '.' or 'source' command), then you will have to enter in this local
>> password every time you interact with kcinit utility.
>>
>> the kcinit script will prompt for this local password.  Once it gets
>> the password value, it will invoke the Java kcinit program:
>>
>> read -sp 'Local password: ' password
>> KC_SESSION_KEY=`java -jar kcinit.jar password $password`
>>
>> The `password` command will generate an AES key from the password that
>> will be used encrypt and decrypt locally stored files.  I do it this
>> way so that when the user's shell is exited, they can no longer access
>> stored tokens.
>>
>> Once the user is logged in, they can start using command line
>> utilities that are secured by it.  To secure a command line utility
>> the developer must use a wrapper script for each of their command line
>> tools.  The wrapper script looks like this
>>
>> - checks to see if KC_SESSION_KEY is set.  If not, it will prompt for
>> the local password and generate this key.
>> - It then tries to obtain the token for the app
>>
>> token=`java -jar kcinit.jar token oc`
>>
>> This will perform a token exchange to obtain a token for the `oc`
>> client.  If this is not successful, an error message is displayed
>> (i.e. "You are not logged in".)  If successful, then the target
>> command line tool is invoked.  The tool extracts the "token"
>> environment variable to invoke on its REST services.
>>
>> $path_to_real_command/$0 $@
>>
>> * There is an install option for kcinit
>>
>> $ kcinit install
>>
>> This will prompt you for auth server url, realm, client, client
>> secret, and the local password to encrypt things.
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> --
>> Bill Burke
>> Red Hat
>> _______________________________________________
>> keycloak-dev mailing list
>> keycloak-dev at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/keycloak-dev
>
>



-- 
Bill Burke
Red Hat


More information about the keycloak-dev mailing list