Friday 30 October 2015

Getting started with Keycloak - Securing a REST Service

This is the second post in the Getting Started with Keycloak series. In this post we'll be securing a simple REST service with Keycloak. The example REST service is created using JAX-RS and deployed to WildFly.

Start a Keycloak Server

Follow the steps from the previous post in the series Installing the Keycloak Server as you will need to have a Keycloak server up and running. If you are planning to run the Keycloak server on the same machine make sure you start it on a different port:

bin/standalone.sh -Djboss.socket.binding.port-offset=100

Downloading the REST service example

You need to have Java 8 (or 7) and Maven 3 installed prior to building and deploying the REST service.

The first thing we need to do is to download the REST service. The service is hosted on GitHub so you should either fork and clone the project from GitHub or download an archive of the project.

To clone the project on GitHub simply run:

git clone https://github.com/stianst/keycloak-blog-gs.git

If you are not familiar with Git then simply download and extract the project from here.

A look at the Services

The services consists of only 3 Java classes inside services-jaxrs/src/main/java/org/keycloak/quickstart/jaxrs. The classes and what they do are:

  • Application - this is used to bootstrap the application. It contains an @ApplicationPath annotation which in this case instructs JAX-RS to deploy the services to '/' within the applications context-path
  • Resource - this is the actual service endpoints we're creating. It consists of 3 endpoints, public, secured and admin. They are very simply and only support GET requests. Each endpoint will simply return a message with the name of the endpoint invoked
  • Message - this represents the JSON structure returned by our endpoints. Again very simple and all the endpoints return are a message saying what endpoint was invoked

Deploying the services

To deploy the services first download and install WildFly 9.0.2.Final. You can download it from here. Once downloaded simply extract it to a directory and start it by running:

wildfly-9.0.2.Final/bin/standalone.sh
or if you are using Windows by running:
wildfly-9.0.2.Final/bin/standalone.bat

Once WildFly is up and running you can deploy the services by opening the directory you clone (or extracted) the project to. Then deploy them to WildFly by running:

cd services-jaxrs
mvn clean install wildfly:deploy

Once the services has been deployed you can open the following endpoints in your browser:

The services are not yet secured, but we will soon secure them using Keycloak.

Securing the services

Now let's secure the REST services. To do this open the web.xml file within the service sources (services-jaxrs/src/main/webapp/WEB-INF/web.xml). Then add the following snippet:

<security-constraint>
    <web-resource-collection>
        <url-pattern>/secured</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>user</role-name>
    </auth-constraint>
</security-constraint>

<security-constraint>
    <web-resource-collection>
        <url-pattern>/admin</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>

<login-config>
    <auth-method>BASIC</auth-method>
</login-config>

<security-role>
    <role-name>admin</role-name>
    <role-name>user</role-name>
</security-role>
This configures the container (in this case WildFly, well actually Undertow is the web server on WildFly) to require the users to have certain roles to be allowed to invoke the endpoints. In this case the endpoint secured requires the role user and the endpoint admin requires the role admin.

Now re-deploy the services by running:

cd services-jaxrs
mvn install wildfly:deploy

Now you can again try to invoke the endpoints:

You should only be able to invoke the public endpoint. The two other endpoints require a user to be authenticated and the user should have the correct roles to access the service. However, we've not specified how users should be authenticate, nor do we have any users, so you won't be able to login to invoke the secured or admin endpoints.

Creating a Client in Keycloak

Now we need to create a client for the services within Keycloak. To do this open Keycloak admin console in your browser. Sign in and click on Clients in the menu on the left hand side. Once that's open click on Create on top of the table. On the next screen fill in the following values:

  • Client ID: service
  • Access Type: bearer-only
Then click on Save. In summary what you've just done is to configure a client with Keycloak. The client id is used for the client to identify itself to Keycloak. Setting the access type to bearer-only means that client will only verify bearer tokens and can't obtain the tokens itself. This means the service is not going to attempt to redirect users to a login page on Keycloak. This is perfect as we're deploying a service intended to be invoked by an application and not by users directly.

Now click on the Installation tab on the top of the form. Under format option select Keycloak JSON. Click on the Download tab. You should move the downloaded file (keycloak.json to services/src/main/webapp/WEB-INF. This provides the required configuration for the Keycloak client adapter.

There's also an alternative method when deploying to WildFly (or JBoss EAP) which is to specify the configuration found in keycloak.json inside standalone.xml instead. We're not going to cover this approach in this post, but it can be more convinient to use this option if you don't want to open up your WAR (or change the source like we did now).

You should also open services/src/main/webapps/WEB-INF/web.xml in your favorite editor and change:

BASIC
To:
KEYCLOAK

Don't try to redeploy the WAR just yet as we have to first install the Keycloak client adapter into WildFly.

Create User and Roles

Now we need to create a user that has the correct roles to access the endpoints. Again open the Keycloak admin console in your browser. First click on Roles there's already an admin role so we don't need to add that, but we need to create the user role so click on Add Role. Use user for the Role name and click Save.

We've now have the two roles we need for our service, next step is to create a user. Click on Users in the menu. Then click on Add User. Set the username to user and click on Save. Then click on Credentials. Enter a password in the password and password confirmation fields. Click on the toggle next to Temporary so it displays OFF. This prevents the user from having to reset the password on the next login. Now click on Role Mappings. To demonstrate that this user is only allowed to invoke the secured endpoint, not the admin endpoint, we're going to only assign the user role to this user. Under Realm Roles in Available Roles select user and click Add selected. Now we're done configuring Keycloak.

Install Client Adapter into WildFly

Next thing we're going to do is to install the Keycloak client adapter into WildFly. Download the WildFly client adapter keycloak-wf9-adapter.tar.gz (or keycloak-wf9-adapter.zip). Extract the archive into the root of your WildFly installation and run:

bin/jboss-cli.sh -c ':shutdown(restart=true)'
Wait until WildFly has restarted then run:
bin/jboss-cli.sh -c --file=bin/adapter-install.cli
Finally run:
bin/jboss-cli.sh -c ':shutdown(restart=true)'

Re-deploy services

Now we've installed the WildFly client adapter we can re-deploy the service with the Keycloak config. To do this run:

cd services-jaxrs
mvn install wildfly:deploy

Once the services has been re-deployed now try the endpoints again:

Now if you try to access the secured or admin endpoint you will no longer get the basic prompt for username and password, but simply a message saying Unauthorized. That's because you haven't included an access token in your request. Next steps we will do is to manually obtain an access token and invoke the services using CURL so that we can pass the token along with the request.

Obtain Token and Invoke Service

First we need to create a client that can be used to obtain the token. Go to the Keycloak admin console again and create a new client. This time give it the Client ID curl and select public for access type. Under Valid Redirect URIs enter http://localhost.

As we are going to manually obtain a token and invoke the service let's increase the lifespan of tokens slightly. In production access tokens should have a relatively low timeout, ideally less than 5 minutes. To increase the timeout go to the Keycloak admin console again. This time click on Realm Settings then on Tokens. Change the value of Access Token Lifespan to 15 minutes. That should give us plenty of time to obtain a token and invoke the service before it expires.

Now we're ready to get our first token using CURL. To do this run:

RESULT=`curl --data "grant_type=password&client_id=curl&username=user&password=password" http://localhost:8180/auth/realms/master/protocol/openid-connect/token`
This is a bit cryptic and luckily this is not how you should really be obtaining tokens. Tokens should be obtained by web applications by redirecting to the Keycloak login page. We're only doing this so we can test the service as we don't have an application that can invoke the service yet. Basically what we are doing here is invoking Keycloaks OpenID Connect token endpoint with grant type set to password which is the Resource Owner Credentials flow that allows swapping a username and a password for a token.

Take a look at the result by running:

echo $RESULT
The result is a JSON document that contains a number of properties. There's only one we need for now though so we need to parse this output to retrieve only the value we want. To do this run:
TOKEN=`echo $RESULT | sed 's/.*access_token":"//g' | sed 's/".*//g'`
This command uses sed to strip out everything before and after the value of the access token property. I'm afraid these instructions will only work on Linux or iOS so Windows users will have to figure out how to do this themselves or install Cygwin. If anyone knows how to do this on Windows I'd appreciate if you'd add the instructions as a comment to this post.

Now that we have the token we can invoke the secured service. To do this run:

curl http://localhost:8080/service/secured -H "Authorization: bearer $TOKEN"

Tuesday 27 October 2015

Keycloak 1.6.1.Final Released

We've just released Keycloak 1.6.1.Final. After releasing 1.6.0.Final we discovered some issues with migration that has been resolved in this release. There's also a fix to a medium security issue that was introduced in 1.6.0.Final.

For the full list of issues resolved check out JIRA and to download the release go to the Keycloak homepage.

There's an issue with the website so it still shows 1.6.0.Final. You can download 1.6.1.Final here.

Monday 26 October 2015

Getting started with Keycloak - Installing the Keycloak Server

This is the first post in a series of getting started guides. In this first post we will look at how to install the Keycloak server. Next time we will look at how to create and secure a simple REST service using Keycloak. Then we'll look at how to create a simple HTML5 application that adds sign on using Keycloak and invokes the REST service. After that we'll see what guides I feel like writing (or what guides are requested by the community), but a few topics I'd like to visit include configuring Keycloak, enabling social login and hybrid mobile application. I'd also like to deploy the basic REST service and HTML5 application using Docker as well as with OpenShift.

If you have any problems getting the steps in this guide working or you have some suggestions to improvements feel free to add a comment below. Also, if you have any requests for future guides add a comment about that.

Keycloak comes in a few different flavors. There's a standalone server that can be installed by simply extracting an archive. You can also start Keycloak on Docker or on OpenShift. You can also install Keycloak into an existing WildFly server.

Standalone installation

The simplest way to get Keycloak up and running unless you're using Docker or OpenShift is to use the standalone bundle. This is a simple archive (zip or tar.gz) that is installed by simply extracting it into a directory. All you need in advance is Java 8 installed (Java 7 works as well, but we'll soon require Java 8 for the server).

To install the archive first to go downloads and download either keycloak-1.6.0.Final.tar.gz or keycloak-1.6.0.Final.zip. Once the download is completed extract this into a directory somewhere.

To start the server open the directory you extracted Keycloak into and run

keycloak-1.6.0.Final/bin/standalone.sh
or if you are using Windows
keycloak-1.6.0.Final/bin/standalone.bat

You should now have the Keycloak server up and running. To check that it's working open http://localhost:8080/auth. Then click on Admin Console the username is admin and password is admin. You'll be asked to change the default password when you login.

One thing to note is that Keycloak runs by default on port 8080. For production this is generally not a problem as you should run Keycloak on a dedicated machine. However, for development you may quite likely want to run another web server for your applications which often use port 8080 as well. You have a few choices in this case:

  • Run Keycloak on a different port - to use port 8080 instead run
    bin/standalone.sh -Djboss.socket.binding.port-offset=100
  • Run Keycloak on another hostname - to expose on 127.0.0.2 (you can also add "localhost2" entry in hosts file for convenience) run
    bin/standalone.sh -b 127.0.0.2 -bmanagement=127.0.0.2
  • Run Keycloak inside WildFly - Keycloak requires a specific version of WildFly, but if that works you can deploy both Keycloak server and your JavaEE apps to the same WildFly instance.
  • Run Keycloak on a separate machine or VM
  • Run Keycloak on Docker
  • Run Keycloak on OpenShift

Install into existing WildFly

Installing Keycloak into an existing WildFly installation can be convenient for JavaEE developers as you will have everything available in one process. It's also possible to do this in production, but we generally recommend having a separate standalone installation of Keycloak. Having it as a separate instance makes it easier to upgrade and scale. Keycloak also requires a specific version of Wildfly (for 1.6.0.Final Keycloak requires WildFly 9.0.1.Final). Finally, with regards to security it's a good idea to isolate your authentication server from your applications.

To install Keycloak into Wildfly you should first have WildFly 9.0.1.Final installed. Then you should download keycloak-overlay-1.6.0.Final.tar.gz or keycloak-overlay-1.6.0.Final.zip. Once you've downloaded the Keycloak overlay archive simply extract this into the WildFly home directory.

To start WildFly with Keycloak run

bin/standalone.sh --server-config=standalone-keycloak.xml
or if you are on Windows
bin/standalone.bat --server-config=standalone-keycloak.xml
.

You should now have Keycloak server up and running. To check that it's working open http://localhost:8080/auth. Then click on Admin Console the username is admin and password is admin. You'll be asked to change the default password when you login.

Install on Docker

To start Keycloak on Docker simply run

docker run jboss/keycloak --name keycloak
This will download the Keycloak image from Docker Hub and start Keycloak and name the container keycloak. To find the IP address of the Docker container you can run
docker inspect --format='.NetworkSettings.IPAddress' keycloak

You can also expose Keycloak on localhost if you want. To do this run

docker run jboss/keycloak --name keycloak -p 8080:8080
This will expose Keycloak on localhost:8080. If you want to expose Keycloak on a different port replace the first 8080 with the port you want to expose it on.

You should now have Keycloak server up and running. To check that it's working open http://DOCKER-IP:8080/auth or http://localhost:8080/auth if you exposed it on localhost with -p. Then click on Admin Console the username is admin and password is admin. You'll be asked to change the default password when you login.

Install on OpenShift

This one is nice and simple. Assuming you have OpenShift CLI tools installed just run

rhc app create keycloak http://cartreflect-claytondev.rhcloud.com/github/keycloak/openshift-keycloak-cartridge
OpenShift will start the Keycloak gear for you and output the URL you can access Keycloak on. You'll even have https already setup. You can also start it from the OpenShift web console, simply use http://cartreflect-claytondev.rhcloud.com/github/keycloak/openshift-keycloak-cartridge as the cartridge url.

Next steps

Once you have Keycloak installed there's a few things you should do. At least you should do these prior to going to production. This includes:

  • Database configuration - by default Keycloak uses an embedded H2 database. For production we recommend we you replace this with a standalone database. We support MySQL, PostgreSQL, Oracle and a few more. To configure the database refer to the Keycloak user guide.
  • SSL configuration - to prevent exposing credentials and tokens Keycloak requires all communication to be done over HTTPS. You should also make sure that at least the services you protect with Keycloak are invoked over HTTPS. For details on how to enable SSL refer to the Keycloak user guide.
  • Clustering - to increase availability and scalability we recommend running Keycloak in a cluster with at least two nodes. For details on how to enable clustering refer to the Keycloak user guide.
  • Change admin password - Keycloak requests that you change the default admin password when you first login. Make sure this is done before exposing Keycloak outside of your local network.

Tuesday 20 October 2015

Keycloak 1.6.0.Final Released

We're pleased to announce the release of Keycloak 1.6.0.Final.

  • SAML SP - in the past we only had client libraries for OpenID Connect, now we also have client libraries for SAML
  • Offline Tokens - if your applications need long term access outside of the users session you should take a look at the new offline tokens support we've added
  • Client Registration - we introduced a new rest api that can be used to automate the registration of clients, this includes a java client library. This feature will be further polished in a future release, including documentation and examples
  • Import Clients in Admin Console - it's now possible to import clients through the admin console using the Keycloak JSON client representation or OpenID Connect descriptions
  • Added Root URL to Clients - we've added a root url to clients. For clients that have a root url defined you can use relative urls for redirect uris and other urls
  • Internationalization support in Admin Console - we've added support for internationalization of the Admin Console. Around half the pages now support translation and the rest will be added in the next release

For the full list of issues resolved check out JIRA and to download the release go to the Keycloak homepage.

Tuesday 13 October 2015

Keycloak 1.5.1 released

We've just released Keycloak 1.5.1. This release contains a moderate impact security fix and we recommend everyone that are currently using 1.5.0 to upgrade as soon as possible. The security issue does not affect older releases.

Monday 12 October 2015

Authentication of clients with signed JWT

Until version 1.4 the confidential OpenID Connect client applications can be authenticated just with client ID and client secret. Client secret is shared between client application and Keycloak server and hence is known to both parties.

From the 1.5 version, we added support for authentication with private/public key pair. It's based on the RFC 7523 . The client authentication works in a way, that the client/adapter generates the Json Web Token (JWT) and signs it with his private key. The Keycloak server then verifies the signed JWT with the client's public key and authenticates client based on it.

The private key of client can be generated by Keycloak server and saved to keystore file on client side, or you can use existing private key of client and upload just certificate/public key to Keycloak server. In both cases, there is just client certificate and public key saved in Keycloak database.

There is increased security in this kind of client authentication in comparison to client secret, as the private key of client is not saved in Keycloak database and it's not sent over the network during client authentication.

More than that, we added support for pluggable client authentication. So if it's still not sufficient for you to authenticate your client with client secret or with signed JWT, you can implement and plug your own authenticator and configure it in admin console . See docs for more details.