Authenticating Desktop Applications with Keycloak and the keycloak-installed adapter
by Thomas Darimont
Hello folks,
I played a bit with the undocumented? [0] keycloak-installed adapter [1]
for integrating
desktop applications with Keycloak SSO and found some issues with it, which
I'd like to share.
Small explanation for those who are reading the list but don't know the
adapter... [2]
First some general notes / suggestions:
Is the keycloak-installed adapter something that will stay in keycloak or
was this just a PoC?
In the former case I think there are some things that could be improved or
extended a bit:
- Allow users to customize the locale used for the login pages opened by
the adapter
- Provide customizable response templates (perhaps by leveraging a provided
ResourceBundle)
- Allow to customize pages shown after login / logout served by the
keycloak-installed adapter
- Add support for TLS (with custom certificates) for https:// with localhost
I noticed that some browsers (e.g. Chrome) show an error page when trying
to
redirect to the local mini-webserver after a successful login since the
mini-webserver
(...server-socket) embedded in the adapter doesn't respond with a valid
HTTP response.
With that fixed, it worked with all browsers I tested (IE, Firefox, Chrome).
My current modifications of the keycloak-installed adapter
(with HTTP response fixes and response customizations) are here:
https://github.com/thomasdarimont/keycloak/commit/b8ee52a946e73503b1737f5...
An extended example (using the the modified keycloak-installed adapter) can
be found here:
https://gist.github.com/thomasdarimont/c59c14f45ea2ee00d7b6fbe2c013c5f1
WDYT?
Cheers,
Thomas
[0] Not mentioned here:
https://keycloak.gitbooks.io/documentation/securing_apps/topics/oidc/java...
[1] https://github.com/keycloak/keycloak/tree/master/adapters/oidc/installed
[2] For those that haven't seen the adapter yet, it allows to authenticate
against Keycloak
from a desktop app (e.g. swing, javafx) by opening a desktop browser window
where a user
uses the regular keycloak login pages to login.
The trick is now that login page is opened with redirect URL that points to
a small local
"web server" (server-socket) on a free ephemeral port which is started by
the adapter.
After logging in the mini web-server receives performs the authenorization
code flow and eventually receives the tokens (access_token, refresh_token,
id_token) which can then be
used to call backend services from the client or retrieve new tokens
A nice side effect of this is, that the desktop application never sees a
users
password and one can leverage existing SSO sessions.
Btw. the google cloud cli uses the same approach to authenticate with gcp.
The Keycloak repo contains a small example for this:
https://github.com/keycloak/keycloak/blob/master/examples/demo-template/c...
6 years, 11 months
ProviderFactory::postDeploy?
by Dmitry
Hi,
At the moment, the ProviderFactory::postInit() method is not called
during hot (re)deployment of providers, only during server startup.
This is considered a bug (see discussion in keycloak-user, KEYCLOAK-
5131 and PR #4282).
Meanwhile, Marek and I have been discussing the problem of accessing
data model from postInit (see the keycloak-user post). Turns out that
the semantics should be significantly different depending on whether
postInit() is called during server startup or hot deploy. In the first
case, one should listen for PostMigrationEvent. In the second case, the
event is not available and thus shouldn't be listened for. However, the
provider should be able to somehow distinguish the cases. There are
some hacks like analyzing current thread name, querying JNDI or
Resteasy, but maybe we can come up with something more clean and
simple?
Marek has suggested that the new method should be introduced on the
ProviderFactory interface, with empty default implementation (in order
not to break the code). What do you think?
Dmitry
7 years, 1 month
Change in enabling / disabling features
by Marko Strukelj
This is a heads up about an upcoming change in how to enable or disable
features in Keycloak.
Keycloak has a notion of features, which makes it possible to disable
certain functionality that is enabled by default, or enable certain
functionality that is disabled by default.
There are four sets of functionality you can enable or disable as features:
impersonation, script, authorization, and docker. See [1] for more info.
Currently a file called profile.properties can be used to enable / disable
features, or system properties can be used, which override any
configuration inside profile.properties as explained in [1].
This is an aberration from how other configuration is specified on the
server via standalone.xml.
Also, the reason config file is called profile.properties, and not
features.properties is because the set of enabled/disabled features is
different for upstream project (where all but 'docker' are enabled), for
product based on Keycloak - RHSSO (where only 'impersonation' is enabled),
and for technology preview versions of RHSSO.
This additionally complicates things. The idea is to simplify that and
remove the notion of profiles, stop using profile.properties, and move all
configuration to standalone.xml where all the available features will be
listed with default values:
<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
...
<features>
<feature name="authorization" enabled="true" />
<feature name="impersonation" enabled="true" />
<feature name="scripts" enabled="true" />
<feature name="docker" enabled="false" />
</features>
...
</subsystem>
This is how configuration would look like in Keycloak distribution. In
product distributions different features would be enabled / disabled - no
more named profiles.
However, in order to allow system properties override the idea is to do it
slightly differently:
<features>
<feature name="authorization"
enabled="${keycloak.feature.authorization:true}" />
<feature name="impersonation"
enabled="${keycloak.feature.impersonation:true}" />
<feature name="scripts" enabled="${keycloak.feature.scripts:true}" />
<feature name="docker" enabled="${keycloak.feature.docker:false}" />
</features>
We should probably also facilitate transition for current deployments, and
take old style system properties into account if they are used - converting
them to the new ones before configuration is applied.
Deprecated: -Dkeycloak.profile.feature.impersonation=enabled
New style: -Dkeycloak.feature.impersonation=true
We don't want to keep support for this indefinitely (maybe for one minor
version?) so if use of deprecated system properties is detected a warning
will be logged.
Also, Stian proposed that features not considered stable yet, should carry
a suffix '-preview' in the name. So the actual feature name, and system
property name may still change for some features.
You can follow progress on JIRA issue [2].
-
[1]
https://keycloak.gitbooks.io/documentation/server_installation/topics/pro...
[2] https://issues.jboss.org/browse/KEYCLOAK-4994
7 years, 2 months
Proposal for merging user accounts in Keycloak
by Thomas Darimont
When integrating multiple legacy systems one often finds that a particular
user
has multiple user accounts. In such scenarios it would be helpful if users
could consolidate their user accounts themselves by merging some of them
into one.
Currently Keycloak doesn't have an official way to merge two existing user
accounts.
Since I'm currently facing this in a project I thought a bit about how this
could
be solved in Keycloak.
Keycloak could provide a dedicated "merge" sub-page in the account
application,
e.g. account/merge. There a authenticated user1 could select the account he
likes
to merge with and verify the ownership of this account.
If the ownership could be verified successfully the user1 would be asked
for a
final merge confirmation. If the user1 confirms the merge then the selected
user
account (user2) would be merged into the currently logged-in user account
(user1).
Some logic would then need to decide how to merge the selected user2 into
the
currently logged-in user1, e.g. by assining roles and / or consents and
potentially
copy over some user profile values.
The account for user2 would then either be marked as merged or deleted.
Login with
user2 is no longer possible from this point on.
This could be supported by a dedicated "user account merge" SPI that could
decide
whether two accounts can be merged, how the merge is performed and what
user information
will be merged. This would enable great flexibility and help quite a lot to
ease integration of legacy systems.
Finally after a successful merge a USER_ACCOUNT_MERGED event with some
metadata
(about user1, user2 etc.) would be fired to notify other systems about the
user account merger.
Here are the steps in some more detail:
# Authentication
0) Unauthenticated user1 goes to the /account/merge page and gets
redirected
to the login page.
1) User1 authenticates and gets redirected back to /account/merge
# Account Selection / Verification
2) User1 selects an account to merge with, e.g. user2 and verfies ownership
E.g. by showing an embedded login form and ask for Username + Password +
2nd Factor
if present
# Merge
3) Merge the user account
3.0) Ask user whether accounts should be merged (account of user1 will
become
the remaining / leading account). This is irreversible!
3.1) Avoid account modification for user2 during merge, e.g. deactivate the
old user (user2)
3.2) Record some information about the merged user
Perhaphs via user attributes or maintain an explicit list of merged users.
# Decide what should be merged
A built-in logic and / or the user decides what should be merged.
3.4) User Profile information (e.g. complete incomplete fields?
E.g. firstname, lastname, mobile, etc.)
3.5) Grant all roles of user2 to user1
3.6) Grant all consents of user2 to user1
3.7) Grant all group memberships of user2 to user1
Credentials of user2 would be ignored.
# Conclude the merge
4) Mark user2 as merged or delete user 2
Delete user2 or rename user2 and change email to be able to use that
information for user1.
4.1) Propagate user account merge as event
Propagate a USER_ACCOUNT_MERGED event via the EventListener infrastructure.
The event should contain at least the userId of user1, and the userId of
user2 and
tells which is now the leading account. This enables downstream systems to
get notified
about the account merge.
WDYT?
Cheers,
Thomas
7 years, 3 months
Migration guide moved!
by Stian Thorgersen
The upgrade guide from RH-SSO has been moved to keycloak-documentation and
now serves as the upgrade guide for both Keycloak and RH-SSO.
That means add changes for Keycloak
to upgrading/topics/keycloak/changes.adoc and not to the
old MigrationFromOlderVersions.adoc file.
I've left the old MigrationFromOlderVersions.adoc for now in case there's
something that's missing in the new guide, but it's not included in the
topics list.
7 years, 3 months
Docs ready again
by Stian Thorgersen
Docs are now ready for changes again after the recent restructuring. It's
now all pure AsciiDoctor and we will no longer use GitBook.
Check out the README.md in the repo for instructions on how to build:
https://github.com/keycloak/keycloak-documentation/blob/master/README.md
Editing the docs is pretty much the same as before, but you don't need to
do the hacks with links and images anymore. All features from asciidoctor
should now work as well.
7 years, 3 months
Renaming testsuite/integration to testsuite/integration-deprecated
by Stian Thorgersen
I would like to rename testsuite/integration to
testsuite/integration-deprecated. This is to make it clear to external
contributors that the testsuite is deprecated and new tests should be added
to testsuite/integration-arquillian.
I would also like to rename testsuite/integration-arquillian
to testsuite/integration.
7 years, 3 months
Docs frozen!
by Stian Thorgersen
Do not make edits to the documentation! We are making big changes to the
docs moving away from GitBook to pure AsciiDoctor. As part of that all
documentation sources will be converted and any edits will be lost and any
changes you have in a clone will most likely be a pain to merge.
It'll take a few days and I'll let you all know when it's ready!
7 years, 3 months