As is, Keycloak has a default configuration which can introduce security flaws despite your manual testing, that why our partner Please Open It developed this Keycloak Config Checker to help you enforce your security practices.

Default configurations

As is, Keycloak has a default configuration for each new realm. For example, some scopes affected to each new client :

Keycloak config checker

Do you really need offline_access scope for each client you will create ?

Another example, scope « role » is affected by default with « Full scope allowed » checked :

Keycloak config checker

So, each token issued by this client will have all user’s roles into it. 2 main issues with this configuration :

  • access_token could be too long for an http header
  • unwanted roles for the context are in the token

Have you noticed that « Brute force detection » is disabled by default ?

Keycloak config checker

Would you push those configurations to a production platform ?

Bad combinations

Authentication flows in Keycloak are highly configurable. Starting from a username/password form, we can make the authentication flow exactly for our needs. Webauthn, otp, passphrase… feel free ! https://blog.please-open.it/auth_user_experience/

Keycloak config checker

« After highly customization of the browser login flow, my user could only connect by using our specific mobile app with the highest security standards ! »

Hum… no.

The « direct grant » flow is still the same as the original, with a login/password required to login. 2 ways :

  • a client has « direct access grant » enabled, because it is a default parameter when you create a client with the wizard
  • admin-cli client is still available…

Is it an extreme use case ? Not at all.

Automate checks

As auditors, we always check the same things : realm configuration, clients (direct access grant, offline, roles with full scope allowed…), so we automated those checks.

After an audit, the platform continues to live. It means that some clients could be created, users or realm parameters could be changed. Do those new resources or changed configurations could affect the global security of your platform ? That’s why we develop a set of SPIs that does those currents checks for you.

Differents ways were tested :

  • work on realm exports, with jq filters and tests. Works great, but unable to automate those tests. Exporting a realm is a high cost operation
  • use event listeners (on admin events), which checks on resource modifications or creation, the rules. Could work great and send alerts. Needs a lot of development work.
  • use existing monitoring systems (prometheus) and alerting software. Some endpoints could be checked regularly, if a change is detected it throws an alert. We use this way.

RealmResources

RealmResource is a Keycloak SPI interface used to create new API endpoints. For example, keycloak-metrics-spi from aerogear use it to expose data :

https://github.com/aerogear/keycloak-metrics-spi/blob/master/src/main/java/org/jboss/aerogear/keycloak/metrics/MetricsEndpoint.java

We did almost the same :

    @GET
    @NoCache
    @Produces(MediaType.TEXT_PLAIN)
    @Path("/realm/check")
    public Response checkRealmConfigMetric() {
        ClientModel clientModel = session.clients().getClientByClientId(realm, "configchecker");

        if(!hasAppRole(clientModel, "metrics")){
            return Response.status(Response.Status.FORBIDDEN.getStatusCode(), "not allowed").build();
        }

        return checkRealmConfig(false);
    }

We created 6 endpoints :

  • /realm/check
  • /realm/check/details
  • /clients/check
  • /clients/check/details
  • /users/check
  • /users/check/details

Details endpoints have more information, we made them in order to help an administrator see what is going wrong and why there is an alert.

Connect to monitoring

For each realm, connect each endpoint to Prometheus with metrics_path :

https://prometheus.io/docs/prometheus/latest/configuration/configuration/

On each check, a number is returned. It corresponds to the number of resources that could have the tested bad configuration.

Remember, having a client with « direct access grant » enabled is not wrong if you use it and you have the right configuration behind it.

Alerts are thrown on a change.

Checks

Realm configuration

  • brute force is disabled
  • reset password is enabled, login with email is enabled AND verify email is not enabled
  • reset password is enabled but there is not SMTP configuration
  • access_token lifespan is > 5min
  • events are saved. This feature is responsible for a high charge on the database. On each event, an insert is done. Reduce the number of events saved to preserve your database performances. This feature is not a logs collector.
  • offline_access role is registered as default role. Each new user will have this role. Check if you really need it.

Clients

  • client credentials uses refresh_token. This was a feature in Keycloak, but not defined in the oauth2 specs. A client_credentials operation returns only an access_token. For compatibility reasons, Keycloak adds an option to preserve refresh_token on client_credentials.
  • implicit flow. We know that this flow is now not recommended for use.
  • direct access grant enabled
  • redirect URIs that contains a wildcard
  • scope offline_access. Check if you really need it
  • scope « roles » and « full scope allowed ». It means that all the user’s roles will be in the token
  • access_token lifespan is > 5min
  • roles scope is default
  • offline scope is default

Users

  • has offline_access role
  • has administration roles on the realm

Performance

Thanks to streams in Keycloak, each check is done with a request. There is no loop on all resources.

For /check endpoints, only the number of matching resources is returned. Those endpoints have very great efficiency and should be called periodically.

All /details endpoints are a little slower, designed for humans.

Extend

For now, we built only a batch of checks regarding our experience on Keycloak. We will add more checks in the future. Feel free to add yours !

Sources

Checkout and build the module from Please Open It Github Repo.

Mathieu PASSENAUD
Les derniers articles par Mathieu PASSENAUD (tout voir)