December 22nd, 2015 by Jonas van Vliet

Microservices have become very popular in recent years. Crosscutting concerns still apply to microservices and in this blog post we will briefly look at the security aspect. We will create a very simple proof of concept that secures a webpage and a REST microservice behind it.

But first, lets look at the problem. In a Java-monolith running on an application server, REST endpoints/resources are protected by filters that require authentication and authorisation. These filters often use a user database representation that is part of the application server. The application server might performs lookups in AD or in its own store where it stores the users. Often these filters are bundled with the application server and work for that specific server, but not on application servers made by other vendors.

When splitting a part of a monolith into a microservice, the user database representation has to be split as well. If the application server hosts the users, this requires syncing users/logins between the monolith and the microservice. If the microservice runs on a different kind of server than the monolith, this becomes hard to manage.

When the number of microservices increases, storing/syncing the state of users and logins across multiple servers becomes harder, so a different approach is necessary. This is where Keycloak enters the stage.

Keycloak is an off-the-shelf solution for authentication, authorization and managing users. Keycloak is responsible for storing the users (or integrating with AD) and providing access tokens to clients on behalf of users that have successfully logged in.
A Keycloak token can contain some fields with user data (firstname/lastname/email etc) and the roles the user has. When a service gets such a token, it can verify that the token is issued by keycloak and that the token contains a certain role. It can do this without contacting the keycloak server since the token is encoded with a shared secret.
Keycloak is bundled with adapters that make it very easy to use Keycloak with a lot of different application servers, Spring boot and node.js.

In this POC we use the following components:

  1. Keycloak server
  2. Dropwizard microservice containing a REST resource
  3. Node.js server that serves static html/javascript and functions as gateway to the REST service

The goal is to make the REST resource inaccessible unless the user has logged in through Keycloak. The flow we would like to have is:

  1. The users goes to the webpage
  2. The user is redirected to the Keycloak server to log in
  3. Keycloak redirects the user back to the node app after logging in, providing the user with a token that contains a Keycloak login
  4. The node server appends the token to the original request to the REST resource and sends it. The REST service checks that the token is valid and grants access to the REST resource.

keycloak-overview

To achieve this, we need to configure the components as follows.

Keycloak

From the keycloak documentation:

The core concept in Keycloak is a Realm. A realm secures and manages security metadata for a set of users and registered clients. Users can be created within a specific realm within the Administration console. Roles (permission types) can be defined at the realm level and you can also set up user role mappings to assign these permissions to specific users.
A client is a service that is secured by a realm. You will often use Client for every Application secured by Keycloak. When a user browses an application’s web site, the application can redirect the user agent to the Keycloak Server and request a login. Once a user is logged in, they can visit any other client (application) managed by the realm and not have to re-enter credentials. This also hold true for logging out. Roles can also be defined at the client level and assigned to specific users. Depending on the client type, you may also be able to view and manage user sessions from the administration console.

 

In this POC we createĀ a realm called “hellorealm” and a client called “helloclient” usingĀ the Keycloak admin console. We download the client’s configuration json file (keycloak.json) to use in our node app and dropwizard service. This file contains the secret that is used to verify that tokens received by node and Dropwizard are issued by Keycloak.
Keycloak has a lot of configuration options. We can add a user registration flow, set password policies, define valid URLs that Keycloak will provide access tokens to etc. For now, we create a user “john” (full name: John Doe) and keep the configuration as is.

Node

The node server uses express to map URLS to static files and resource endpoints. The following snippet shows how to require a keycloak login and fetch the result from a different host – in this case the dropwizard microservice. The keycloak variable refers to a nodeadapter made by keycloak that requires very little configuration. The node app requires the keycloak.json file.

 

When a user accesses a protected URL without an active login, the user is redirected to the keycloak login page. The body of this code is not run unless unless the user is logged in.
The apiProxy refers to a http-proxy that is used to proxy requests to the node app towards a microservice. The proxy must be configured to include the token from the browser’s session with node. Otherwise the dropwizard service will conclude that the user is not logged in and deny access.

 

 

The URL mapping is fixed to point toward the dropwizard service. This is acceptable in a POC. In a real life setup with multiple services, this should be replaced by a service discovery/lookup mechanism.

Dropwizard

Unfortunately, Keycloak is not bundled with a dropwizard adapter. The dropwizard service needs to block requests that do not include a bearer token. We could use the following plugin, but to keep things as simple as possible, we implement the bare minimum and only use dependencies to the official Keycloak libraries. The implementation is heavily inspired by this plugin.
To secure our REST endpoint, we add the following maven dependencies to our pom:

To block access to the REST resource we add the following filter to the dropwizard configuration:

The filter blocks all requests to rest services that do not contain a valid bearer token.

The token contains information about the user and this information should be available to the service in order to save investigations, log who requested a resource etc. To access this, we need to register Keycloak as the security constraint authenticator:

We can then access the data in the token in our REST endpoint:

As previously mentioned, the bearer token also contains the user’s roles. These roles can be used to only allow or deny access.

Working with roles and tokenproperties like this is not pretty – injecting a securityContext and casting objects is a bad smell. The plugin previously mentioned provides a nice interface for these operations.

Trying it out

When we spin everything up and access the REST service path on the node gateway, we are redirected to keycloak.

keycloak-login

According the to the documentation, the login page is configurable. You can style the page and include your company logo/ product name.
When logged in, the service responds with:

service-response

If we try to access the REST resource without going through the node gateway, we get a http 401. This confirms that our service cannot be accessed without valid user credentials.

 

Final remarks

Security is hard, so avoid reimplementing the wheel. Figuring out how to store user passwords in a database in a secure way takes longer than implementing a security setup using Keycloak.
Keycloak is an active open source project. As long as it is maintained, I feel confident that it provides better security than a homemade implementation. The documentation even contains a section on possible security risks and how to mitigate them.

If you want to secure a single server with Keycloak and an adapter is available, then Keycloak is very easy to setup. If you want to do something a little bit more complex, for instance sending user credentials from one server to another, you will need a basic understanding of how the tokens issued by Keycloak work. To this extent, I highly recommend reading the OAuth 2.0 spec.

Now hiring in Dubai! - Read more

Posted in develop software Tagged with: , , , , , , ,