Some community feedback & service-to-service calls
by Thomas Darimont
Hello Keycloak Team,
sorry for the (again long email)
TLDR:
- some community feedback
- people want examples / guidelines for secure service to service
communication
- Ideas for a blog post about that
---
This week I gave a talk about Keycloak at a small Java conference
in Düsseldorf / Germany: jcon.one.
In my talk I gave a brief overview on Keycloak and explained how SSO
via OpenID Connect works in detail. I also explained and briefly showed
how to work with the various token types e.g. how to query a bearer-only
API backend from a confidential client. I also demonstrated the
KeycloakInstalled-adapter, which apparently isn’t shown very often.
The talk was very well received.
During the days after the talk I got a lot of questions about Keycloak and
in particular
about how general service-to-service communication could be secured by
Keycloak.
I explained that there are some options like using
service-accounts or explicit technical user accounts to represent a service
which can obtain AccessTokens by itself and use those tokens to access
other
services secured by one of the various Keycloak adapters.
However many folks didn't seem to be aware of those options.
I think the reason for this is because although many articles
about Keycloak describe how to secure a common web application,
[perhaps with a SPA frontend and an API backend which gets accessed via an
AccessToken] one (IMHO) hardly finds articles with some detailed
discussions about how to properly secure service-to-service communication.
E.g. some mentioned scenarios were
- service calls another service on it's own (cron job)
- ... or triggered by an event or some messaging system.
both without direct user interaction.
In the examples project there is also (only?) one example about
using service accounts which looks a bit verbose:
https://github.com/keycloak/keycloak/blob/master/examples/demo-template/s...
I think a blog post about "Best practices for securing service-to-service
communication with keycloak" would be a good topic for the Keycloak blog.
I think one should highlight some APIs like the KeycloakAdmin Client API
which makes it fairly easy to retrieve tokens for the client_credentials
grant.
E.g:
Keycloak keycloak = KeycloakBuilder.builder() //
.serverUrl("http://localhost:8081/auth")
.realm("service-to-service")
.clientId("service-a")
.clientSecret("73e7a71a-015e-4896-80ae-8e39ccb41deb")
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.build();
System.out.println(keycloak.tokenManager().getAccessTokenString());
Another point could be when an AccessToken should/needs to be verified
(e.g. via RSATokenVerifier).
One could also show the differences between the two approaches of using a
service-account and a "technical" user account.
Service Account:
- Enablement: Whole Service or just Service Account can be enabled /
disabled
- Credential: Service Account uses client credential
- Username: service-account-${client_id}
- Email: ${username}(a)placeholder.org
- Attributes: In datamodel but not exposeable to tokens
- Password Policy: does not apply
- Bruteforce Protection: does not apply
- Credential handling: visible in AdminConsole
- Grant type to obtain AccessToken: client_credentials
e.g.:
curl -X POST \
http://localhost:8081/auth/realms/service-to-service/protocol/openid-conn...
\
-d 'grant_type=client_credentials' \
-d 'client_id=service-a' \
-d 'client_secret=1e1ebe68-96f2-4dca-bda8-03df44d3be13'
Technical User Account:
- Enablement: User can be enabled / disabled
- Username: arbitrary
- Email: arbitrary
- Attributes: arbitrary attributes can be exposed to tokens via
ProtocolMapper
- Password Policy: applies
- Bruteforce Protection: applies
- Credential handling: hidden in AdminConsole
- Roles: can be assigned arbitrarily
- Grant type to obtain AccessToken: password -> needs Direct Access Grants
enabled
e.g:
curl -X POST \
http://localhost:8081/auth/realms/service-to-service/protocol/openid-conn...
\
-d 'grant_type=password' \
-d 'client_id=admin-cli' \
-d 'username=svc-onboarding' \
-d 'password=secret'
When using technical user accounts it is IMHO advisable to prefix the
username of the
service users to ease differentiation between real users and "technical"
users, e.g.
"svc-onboarding", "svc-shipping".
I'm still undecided which of these approaches is best but I'm currently
leaning towards 1) for simplicity but 2) for security....
Another thing that I found:
One can define some kind of "locked-down client" that only allows
client_credentials grants
to obtain AccessTokens / RefreshTokens(IMHO).
To do that one needs to set "Standard Flow Enabled", "Implicit Flow
enabled",
"Direct Access Grants enabled" to "off" but "Service Accounts enabled" to
"On".
One could also describe how such clients could protected, e.g.
"bearer-only" or a
"confidential" client with autodetect-bearer set to true protected by one
of
the many Keycloak adapters.
Another thing to note is that using a secured channel like TLS for the
communication
between two services is IMHO still a good idea.
Cheers,
Thomas
8 years, 2 months
If you ever touch Freemarker....
by Stan Silvert
If you ever touch our Freemarker code, you need to be aware that we have
changed the way that HTML is escaped. Don't use ?html any more.
Freemarker is now upgraded to the latest version which provides
automatic escaping of all variables by default. The ?html suffix is no
longer allowed. This is far more secure as we err on the side of caution.
If you intend to include html in a Freemarker variable value you need to
tell Freemarker that it shouldn't escape it. Use the ?no_esc suffix.
For example, let's say you have a message bundle entry that looks like this:
totpStep1=Install <a href="https://myurl/">FreeOTP</a> or Google
Authenticator on your device.
In Freemarker, you need to say:
<p>${msg("totpStep1")?no_esc}</p>
Also, be aware that you are responsible for the safety of anything
marked with ?no_esc. Make sure there is no way it can be modified from
outside Keycloak or you will be opening Keycloak to an XSS attack.
Stan
8 years, 2 months
X509 integration tests
by Bruno Oliveira
Good morning,
While investigating an issue with X509 certificates, I was wondering if we
run integration tests for it on Travis. Looking at travis.yml I don't see
any reference like `run-server-tests org.keycloak.testsuite.x*`.
What I'm trying to do is pretty much:
mvn clean install -Pdistribution -DskipTests=true && cd
testsuite/integration-arquillian && cd tests/base && mvn clean test -B -nsu
-Pauth-server-wildfly -Dtest=*X509BrowserLoginTest
But all the tests are failing. Am I missing something?
8 years, 2 months
Enhancement to Keycloak logging
by Narendra Kadali
Hi,
I feel that logging information in Keycloak is not sufficient to debug
issues. Sometimes I struggle to debug issues in our environment due to lack
of enough logs. When I look at the Keycloak source code, I noticed that
most of the classes doesn't have any loggers in it code.
I believe that with logs we should be able to identify what classes are
being called for executing an request and what data is passed to various
methods. This will make our life simple while debugging issues.
Do we have any plans for enhancing existing logging in Keycloak?
Thanks!
8 years, 2 months
Execution order of required actions
by Martin Hardselius
Hi,
This might be a question for the user list, but I haven't seen any activity
there in a while.
Is there a way to ensure execution order of required actions? Like "action
x to always fire last", or "action x should fire after action y".
Cheers,
Martin
8 years, 2 months
Conditional testing of cross-dc on Travis
by Hynek Mlnarik
Hi
as part of the cross-dc, we need to introduce some means of running
cross-dc tests on PRs that touch critical classes. On the other hand, these
tests are not necessary for every and each PR as they take 15-20 minutes to
complete and for many changes bring no additional value to regular
testsuite run.
I've implemented a straightforward test for checking whether the given
group in travis should be tested [1] and would love to hear your feedback
on it. It is intentionally simple, based on filename pattern matching, in
the future the checks can become more complex, based on our needs.
There are two types of check:
- global which is run regardless of the current test group (as defined by
.travis.yml). Currently it checks whether only a change in .md documents
and if yes, it blocks running the TS
- per test-group condition on whether a particular test group should be
executed or not (it is "crossdc" group in the PR). If the check is not
defined for a given test group, the test group is run (e.g. "server-group1")
Thanks
--Hynek
[1] https://github.com/keycloak/keycloak/pull/4584
8 years, 2 months
Groups completely hosed
by Stan Silvert
The Groups section of the Admin Console is completely messed up in master.
I see that the main screen has a table control on the bottom (not sure
why). It says "1 of Infinity".
If you create more than one group off of the root then only the first
one will show up. Also, it appears that the Default Groups tab doesn't
fill the Available Groups section.
Anyone else see what I see? Anyone know how it got so broken?
Stan
8 years, 2 months
Keycloak and Kubernetes
by Bill Burke
I believe there will be two distinct integration points of Keycloak
with Kubernetes.
* Kubernetes relies on Keycloak for authentication and even authorization
* Keycloak is offered as a Kubernetes services for appliations and users to use
These should be 2 distinct use cases.
--
Bill Burke
Red Hat
8 years, 2 months
Flexible HTTP Proxy support for HttpClientProvider
by Thomas Darimont
Hello,
I've sent a PR [1] for KEYCLOAK-4743 [2] Add proxy support to
HttpClientProvider SPI.
The proposed implementation is based on the discussions from an older
(rejected) PR [3]
The current DefaultHttpClientProviderFactory doesn't support HTTP proxies
which makes
it very difficult to integrate social Identity Providers like google /
facebook etc...
when you are required to tunnel all external communications though a proxy
server.
Server Developers are currently required to either convince their network
admins to
loosen the proxy rules ... or provide a custom implementation of a
HttpClientProvider,
which is quite complex. Therefore it would be great if keycloak would add
support
for this out of the box.
Since keycloak needs to be able to selectively use a (dedicated) proxy
server
for external and potentially no proxy for internal connections the
configuration
for that needs to be quite flexible.
The current PR proposes to use an ordered list of proxymappings that match
a http request host based on a regex pattern to a proxy uri which are
processed
by a new ProxyMappingsAwareRoutePlanner that is added to the internal
HttpClient.
A ProxyMapping has the form hostname-pattern;proxy-uri e.g.:
.*\.(google|googleapis)\.com;http://www-proxy.acme.corp.com:8080
.*\.acme\.corp\.com;NO_PROXY
.*;http://fallback:8080
(the catch all is optional)
The first matching mapping defines the proxy to use. If no pattern matches
then no proxy is used. One can also explicity define that certain
connections should
not use a proxy.
... and can be configured via jboss-cli
echo SETUP: Configure proxy routes for HttpClient SPI
/subsystem=keycloak-server/spi=connectionsHttpClient/provider=default:add(enabled=true)
/subsystem=keycloak-server/spi=connectionsHttpClient/provider=default:write-attribute(name=properties.proxy-mappings,value=[".*\\.(google|googleapis)\\.com;
http://www-proxy.acme.corp.com:8080",".*\\.acme\\.corp\\.com;NO_PROXY",".*;
http://fallback:8080"])
This can be tested as follows:
1) Apply the PR in branch, build a server distribution.
2) Start Keycloak with portOffset 10000 for http/https/ajp port.
Configure the ProxyMappings in standalone.xml:
via jboss-cli:
echo SETUP: Configure proxy routes for HttpClient SPI
/subsystem=keycloak-server/spi=connectionsHttpClient/provider=default:add(enabled=true)
/subsystem=keycloak-server/spi=connectionsHttpClient/provider=default:write-attribute(name=properties.proxy-mappings,value=[".*\\.(google|googleapis)\\.com;
http://localhost:8080"])
3) Download and start BurpSuite [4]
4) By default burpsuite starts a proxy server on port 8080
5) Register google as auth provider and check entries in burp proxy log
(Note that you potentially need to explicitly forward the request in the
proxy tab in Burp)
WDYT?
Cheers,
Thomas
[1] https://github.com/keycloak/keycloak/pull/4543
[2] https://issues.jboss.org/browse/KEYCLOAK-4743
[3] https://github.com/keycloak/keycloak/pull/4040
[4] https://portswigger.net/burp/help/suite_gettingstarted.html
8 years, 2 months