Wednesday 9 December 2015

First social login in Keycloak

One of the core Keycloak features is so called social brokering and identity provider brokering. Keycloak provides integration with the known social networks (Facebook, Google, Twitter, Github, StackOverflow, LinkedIn). You can also easily plug any other OpenID Connect, OAuth2 or SAML2 authentication server. When you click on particular social network (or identity server) button on login screen, Keycloak will use it to authenticate user and then redirect back to the application.

The social integration is available in Keycloak from it's early days. But we have also issues with so called First social login from it's early days. The term First login means that user authenticates to Keycloak for the first time through some particular social network (for example through Facebook).

Let's describe this in a bit more details. When Keycloak successfully authenticates user through social provider, there can be two situations:

  • There is already Keycloak user account linked with the authenticated social account. In this case, Keycloak will just authenticate as the existing user and redirect back to the application.
  • There is not yet existing Keycloak user account linked with the social account. This situation is more tricky. Usually you just want to register new account into Keycloak database, but what if there is existing Keycloak account with same email like the social account? Automatically link social account with existing Keycloak account is not very good option as there are possible security flaws related to that...
For the second case, we had lot of various related issues and lot of feedback and requirements from community and from our awesome jboss.org team. In the end, We changed the behaviour to be flexible and configurable through Authentication Flows SPI . This is available from Keycloak 1.7.0.CR1. Basically, you can configure the default set of authenticators, which allows you to change the behaviour according to your needs. It's also possible to implement your own Authenticator and adjust the behaviour exactly according your requirements.

The default behaviour for first social login is this:

  • User is optionally faced with the Review profile page where he can edit the claims (email, first name, last name and more) retrieved from social provider. By default, the page is displayed only when some of mandatory claims is missing (For example in case of Twitter, the page is always displayed as Twitter doesn't return email of user).
  • If there is no user with conflicting email in Keycloak database, user is automatically created and redirected back to the application.
  • Otherwise he needs to confirm that he wants to link his existing Keycloak account with the newly authenticated social account
  • If user choose to link accounts, he needs to either confirm linking by email verification, or he needs to re-authenticate and type his password (and optionally OTP). It depends on admin on how exactly he configures the authentication flow.

Here are some screenshots of how the typical first login with Facebook can look like. It includes review profile, confirming that user wants to link his Facebook account and verification of successful account linking by email verification.

For more details, see Keycloak documentation .

Additionally in 1.8 version, we have a plan for adding post-broker flow, which will allow additional verification after each login with social provider (For example OTP). So stay tuned.

Tuesday 8 December 2015

Keycloak 1.7.0.Final Released

This release contains no changes since 1.7.0.CR1 as there where no major bugs reported. Thanks to everyone that did give CR1 a try and provided feedback.

For new features in this release check out the blog post about Keycloak 1.7.0.CR1 release

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

Thursday 3 December 2015

Keycloak 1.7.0.CR1 Released

I'm pleased to announce the release of Keycloak 1.7.0.CR1. Recently we've gone straight to Final, but we'd like to give everyone a chance to try a release out first. Unless there are major issues reported we will release Final next week.

As usual we've been far from idle and have a number of highlights in this release, including:

  • Groups - users can belong to one or more groups and inherit role mappings and attributes from the group.
  • First Broker Login Flow - we've introduced a number of improvements to first login with identity brokers as well as the ability to customize the flow used.
  • Client Registration - clients can now dynamically register themselves with a Keycloak server. This supports Keycloak client representations, OpenID Connect Dynamic Client Registration and SAML Entity Descriptors. Client registration are simple REST endpoints, there's also a Java library and a CLI is coming soon.
  • OpenID Connect Implicit and Hybrid flows - we've added support for the Implicit and Hybrid flows. It's also possible to select what flows are available for a specific client.
  • Add User script - as a first step to not having a default admin user we've added a script that allows creating an initial admin account.
  • Cache fixes - there's a number of fixes related to caching, which should improve performance especially in clusters.
  • Email Sender SPI - previously we had one SPI that created email content from FreeMarker and also sent emails. We've now split this into two separate SPIs.
  • SAML SP WildFly subsystem - there's now a WildFly subsystem for the SAML SP adapter, which makes it easier to use the SAML SP adapter on WildFly.
  • WildFly 10 adapter support - the WildFly adapter, including adapter subsystem, now supports WildFly 10.

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

Tuesday 1 December 2015

Offline tokens in Keycloak

In Keycloak 1.6.1 We added support for offline tokens. This feature is described in OpenID Connect 1.0 specification and is useful for the applications, which needs to be able to do some actions on behalf of user, but in offline mode. Offline mode means that user is currently not logged in.

For example imagine Photo Album application, which needs to do periodic backup of saved user photos every day on midnight. This application can't never ensure that user is logged each midnight, but what it can do is:

  • When user authenticates to the application through Keycloak server, the application asks Keycloak server to return offline token instead of classic refresh token. The only thing application needs to do to request offline token is to add the parameter scope=offline_access during authentication request to Keycloak. Offline token is just special kind of refresh token, which never expires.
  • Photo Album application then saves the offline token in it's database
  • When user logout from the application, the session of user is invalidated. However offline token is still considered valid by Keycloak server.
  • On midnight, the application loads the offline token from it's database and send request to Keycloak to retrieve new access token. Even if user is offline, Keycloak will return access token corresponding to previously authenticated user. Application can use this access token to do the backup of photos on behalf of user and invoke any REST Backup service with the issued access token.

User is able to see and revoke any previously issued offline tokens in Keycloak Account Management application.

Also admin has possibility to see and revoke offline tokens of any particular user or eventually revoke all offline tokens issued to particular client application.

For more details, see Keycloak documentation and our Offline-access-app example, which is part of Keycloak example demo.

Wednesday 18 November 2015

5000 Commits on GitHub

We've just passed 5000 commits on GitHub. I know this includes merge commits and everything, but in any case it's an excellent indicator that Keycloak is a very active project. A huge thanks to everyone that has been involved in getting us to this point.

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.

Tuesday 22 September 2015

Having fun with REST API documentation

Recently I’ve been looking at ways to replace our current REST API documentation build with one that works with Java 8. Our requirements are - generate static html from JAX-RS annotations and JavaDoc. Simple, right? It shouldn’t be much more than finding a maven plugin and using it, right? Wrong.

Here’s how it went …

For a long time we’ve been using JAX Doclet. It generates JavaDoc html, except that it describes REST endpoints rather than classes, supported verbs rather than class methods, parameter bindings rather than method arguments, and status codes rather than method return types. It’s simple to integrate, and produces decent static html. It has one caveat though - it only works with Java 7. Java 8 brought changes in internal java doclet classes which caused many third party doclets to now maintain separate branches for Java 7, and Java 8. JAX Doclet has been feature complete and dormant for some time now, and there is no Java 8 compatibility on the horizon.

Here we are at a decision point - fork JAX Doclet and tailor it for Java 8, or find a replacement?

Programmers are a lazy bunch, or rather - we like to economize in order to reach our goal faster. Find a replacement then ...

Go to GitHub, and search for ‘jaxrs doclet’. There’s exactly one project with some traction on the topic. This is probably going to work.

The project we find is Swagger JAXRS Doclet, and it’s been quite some time since it’s seen any activity, but there’s a link to a fork that’s still very active, so we end up using teamcarma/swagger-jaxrs-doclet.

Good thing is it uses JAX-RS annotations, and JavaDoc descriptions to generate docs. Bad thing is the only output it generates are Swagger 1.2 compatible .json files, and an option to package them together with swagger-ui to get a rich single page web application to explore the API.

Sure, why not, surely you can double-click on index.html and run swagger-ui locally in your browser. It turns out that’s not the case.

Swagger-ui relies on XHR requests, and unbeknownst to me browsers have recently become immensely suspicious of XHR to the point of basically disabling it for local disk access.

That’s a problem for me, as I need static html. There might be magic switches to get browsers to perform XHR against local filesystem, but who wants to deal with that for the sake of browsing documentation ...

What now?

Well, find another maven plugin that takes REST API description in swagger .json format, and creates static HTML from it, of course.

Back on GitHub, searching for ‘swagger maven’, we get many results.

First hit is a very popular project, but immediately it doesn’t sound quite right for what we need - swagger-maven-plugin. It’s really a replacement for swagger-jaxrs-doclet, except it doesn’t understand JAX RS annotations, or JavaDoc comments, but requires classes to be annotated with Swagger annotations. That’s a deal breaker for me, as I don’t want to pollute our code with non-standard third-party annotations, and we don’t even particularly care about Swagger at this point - it’s just a tool to get to the static html documentation.

But this tool does something neat - it is able to generate not only swagger json files, but static text files of different formats as well - html, asciidoc, markdown … Sigh, if only it could work with JAX RS annotations, and JavaDoc … Would it be difficult to add such functionality? Could we generate Swagger annotations where they are missing, based on JAX RS annotations, and JavaDoc? Do we explore the idea, or look for existing working solution?

Let’s look further …

The next interesting project we find is swagger2markup-maven-plugin. This one looks exactly as what we need. It takes Swagger .json files, and converts them to asciidoc or markdown - unfortunately not also directly to html. For that we would then need another plugin - asciidoctor-maven-plugin. Not ideal, as we would end up with a bloated pom.xml, and a slow doc generation process, but as long as it does the job ...

Looking further still, we find that there are no more better candidates for what we need. So let’s work with swagger2markup-maven-plugin, and see how far it takes us.

It looks quite easy to use. We just add a few snippets to our pom.xml.

First, let’s make sure all of these extra plugins work with Java 8, since that is the whole reason we’re doing this:

  <properties>
    <!-- maven-compiler-plugin -->
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    ...
  </properties>

Then we add swagger-jaxrs-doclet to javadoc-maven-plugin:

  <properties>
    ...
    <version.swagger.doclet>1.0.5</version.swagger.doclet>
    ...
  </properties>
  <build>
    <plugins>
      ...

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-javadoc-plugin</artifactId>
        <executions>
          <execution>
            <id>generate-service-docs</id>
            <phase>generate-resources</phase>
            <configuration>
              <doclet>com.carma.swagger.doclet.ServiceDoclet</doclet>
              <docletArtifact>
                <groupId>com.carma</groupId>
                <artifactId>swagger-doclet</artifactId>
                <version>${version.swagger.doclet}</version>
              </docletArtifact>

              <reportOutputDirectory>${project.basedir}/target/apidocs-rest/swagger</reportOutputDirectory>
              <useStandardDocletOptions>false</useStandardDocletOptions>
              <additionalparam> -skipUiFiles -apiVersion 1 -includeResourcePrefixes org.keycloak.services.resources.admin,org.keycloak.protocol.oidc -docBasePath /apidocs -apiBasePath http://localhost:8080/auth</additionalparam>

            </configuration>
            <goals>
              <goal>javadoc</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

      ...

    </plugins>
  </build>

This should trigger the doclet during JavaDoc generation, and produce swagger .json files in target/apidocs-rest/swagger directory without also including swagger-ui.

Now that we got the first part done, we move to the next step - configuring swagger2markup-maven-plugin to convert the created swagger .json files to asciidoc document.

This second maven plugin uses its own maven repository:

  <repositories>
    <repository>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <id>central</id>
      <name>bintray</name>
      <url>http://jcenter.bintray.com</url>
    </repository>
  </repositories>

  <plugins>
    …

    <plugin>
      <groupId>com.redowlanalytics</groupId>
      <artifactId>swagger2markup-maven-plugin</artifactId>
      <version>0.7.1</version>
      <executions>
        <execution>
          <id>gen-asciidoc</id>
          <phase>process-resources</phase>
          <goals>
            <goal>process-swagger</goal>
          </goals>
          <configuration>
            <inputDirectory>${project.basedir}/target/apidocs-rest/apidocs/swagger</inputDirectory>
            <outputDirectory>${project.basedir}/target/apidocs-rest/asciidoc</outputDirectory>
            <markupLanguage>asciidoc</markupLanguage>
          </configuration>
        </execution>
      </executions>
    </plugin>

  </plugins>

That should produce three .adoc files in target/apidocs-rest/asciidoc directory - overview.adoc, paths.adoc, and definitions.adoc. The idea of Swagger2Markup is that these are three distinct document segments that can be combined with additional separately prepared .adocs into a complete and final document. Swagger2Markup itself however will only take it as far as preparing these three document segments for you.

There is one problem though. If you have multiple swagger .json files for input - as a result of multiple REST endpoints, then it looks like the created files will reflect documentation for only the last .json file processed. As if every next .json file processed will generate the three .doc files of the same name, overwriting the previous ones. Lucky for me I’m only dealing with one endpoint, so no need to figure out how to make it work with multiple files.


Next, we have to generate a composite asciidoc, and then perform translation into html. For that we’ll use asciidoctor-maven-plugin.

For starters, we need an asciidoc file that will tie together the three input .adoc files into one.

Let’s call it index.adoc, and let’s keep it very simple:
include::{generated}/overview.adoc[]
include::{generated}/paths.adoc[]
include::{generated}/definitions.adoc[]
We just combine all the three documents into one without any additional content.

We place this file into src/docs/asciidoc directory of our maven project.

Now we configure asciidoctor-maven-plugin:

      <plugin>
        <groupId>org.asciidoctor</groupId>
        <artifactId>asciidoctor-maven-plugin</artifactId>
        <version>1.5.2</version>
        <executions>
          <execution>
            <id>generate-docs</id>
            <phase>package</phase>
            <goals>
              <goal>process-asciidoc</goal>
            </goals>
            <configuration>
              <sourceDirectory>${project.basedir}/src/docs/asciidoc</sourceDirectory>
              <sourceDocumentName>index.adoc</sourceDocumentName>
              <outputDirectory>${project.basedir}/target/apidocs-rest/html</outputDirectory>
              <backend>html5</backend>
              <attributes>
                <!-- List of attributes: 
                        https://github.com/asciidoctor/asciidoctorj/blob/master/asciidoctorj-core/src/main/java/org/asciidoctor/Attributes.java
                  -->
                <generated>${project.basedir}/target/apidocs-rest/asciidoc</generated>
              </attributes>
            </configuration>
          </execution>
        </executions>
      </plugin>

That will produce a single index.html file in target/apidocs-rest/html directory that is what we were after. Mission accomplished!

Well ... sort of.

There are some problems with this document.

For one, it has a big ‘null’ for its title.

Tracing back the issue, we can see it in overview.adoc already, and is the result of title info missing in service.json file generated by our very first plugin.

Turns out that’s easy to fix.

We create a file apiinfo.json:
{
  "title": "Keycloak Admin REST API",
  "description": "This is a REST API reference for Keycloak Admin"
}

We place it in src/docs/swagger directory.

Then we add another parameter to <additionalParam> line in the first plugin:
-apiInfoFile ${project.basedir}/src/docs/swagger/apiinfo.json
That should fix the title.


Next problem is that the document is not very readable. We could address that by tweaking the .css.

But that's a styling issue.

More problematic is that the document contains some dead links for generic types like Request, Object, Map which have no model definition in definitions.adoc. We only notice that now when we view the document as html, but the problem originates in swagger .json file already.

Also, some of our operations apparently don’t have the JavaDoc descriptions, and for those the .json file doesn’t contain any description, rather the output falls back to auto-generated string composed of HTTP method and uri. This wasn’t an issue with original JAX Doclet since output was JavaDoc html, and content organisation followed endpoint / uri / method hierarchy, analogous to package / class / method hierarchy - therefore descriptions were optional.

With Swagger2Markup the hierarhy is flat. For a single endpoint all you get is a list of method-uri items where each one’s description serves as its title.

There is one way to fix this - adding the missing JavaDoc descriptions to our code. But then a more readable form would be one without using descriptions as titles - but rather using “{method} {uri}” as a title and putting description in content underneath. Is there a way to do that with Swagger2Markup? The underlying library is certainly capable of it. But can we reach it through maven plugin? Doesn’t look like we can.

If we could do that, we also then wouldn’t have to fill out all the JavaDoc descriptions for our methods - many are self-explanatory, and don’t require a description.

At the end of the day the result we got is not perfect, we’ll have to do more work. Looking over at swagger-maven-plugin (the one that is based on Swagger annotations), it has a very flexible templating support which allows to define how content is generated, by using something called moustache templates. We could skip the whole swagger.json-to-asciidoc-to-html chain of three plugins, and do it all in one - much more elegant. But for our use-case we would first have to enhance that library to support auto-generating the default Swagger annotation values based not only on JAX RS annotations, but also on JavaDoc tags. That’s not a trivial undertaking, especially since here we’re dealing with a standalone maven plugin, not a doclet.

Another option would be to enhance Swagger2Markup library to give us more control over how the documentation content is organised, and make that available through its maven plugin.

Yet another option is to decide that the solution we got thus far is good enough, and not worth investing more time in.

We could also change our mind about swagger annotations. Many projects have gone the Swagger way. In the end we might be better off by simply putting swagger annotations in our code, and use swagger-maven-plugin.

There’s so much other important, and interesting things to do on Keycloak. Let's use this solution for now, and move on to other things. We'll revisit REST API docs generation some other time.

Monday 21 September 2015

Google Summer of Code 2015


Google Summer of Code (GSoC) inspires young developers to begin participating in open source development and gives them a sound exposure to real-world software development (for example, distributed development and version control, software licensing issues, and mailing list etiquette). Luckily, I was a part of GSoC 2015 for JBoss community where I contributed bits and bytes to JBoss Security i.e., SSO SaaS  Keycloak. I was being mentored by Keycloak co-lead Stian Thorgersen.
Contributing to JBoss Community has been a great experience for a newbie like me starting right from GSoC 2014 (Picketlink @asaldhan @pedroigor) to GSoC 2015 (Keycloak @stianst @mposolda). JBoss Community offers awesome projects ranging from Testing to Tooling, Application development to Security, Run time to Web frameworks, Asynchronous messaging to Integration and the Ceylon programming language. Although GSoC is over, but, I will always be up contributing bits and bytes to JBoss community as and when time will permit.
It was my second GSoC summer with JBoss community. I contributed during GSoC 2014 as well. GSoC entire coding period was an extremely elegant and eternal experience for me. I learnt about some of the best practices followed while working and collaborating on a very large code base. Building a beautiful API design, writing high quality code, synchronizing code with a version control system, raising issues on JIRA were some of the skills honed during GSoC in addition to establishing connections with some of the most awesome developers across the globe.
Contributing to Keycloak provided me a deep insight into Single Sign On security. Keycloak is an authentication server that provide users with the ability to centrally login, logout, register and manage their user accounts. The Keycloak administration UI manages roles and role mappings of any application secured by Keycloak. 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.
I had from little to no idea about OAuth, OpenID, Mutual SSL authentication before I started contributing to Keycloak. Hacking on SSO SaaS Keycloak is a great way to achieve proficiency over single sign on security and be a part of the awesome community. Keycloak UI is built upon Angular JS with Patternfly and can be customized. With each Keycloak contribution, I learnt something about security. With regards to Keycloak contributions, I achieved skills in ssl configuration over Keycloak, mutual ssl authentication for user’s and client’s over Keycloak, effective management of admin actions for auditing and monitoring, maintenance of sound password policies etc.
I managed to setup mutual SSL client authentication over WildFly. Similarly, I also had success in securing a war app and assigning application authorization access to the users via certificate roles. Setting and achieving the same functionality with Keycloak is still a work in progress. Keycloak will feature a Certificate Authority which would be responsible for issuing certificates and keys to realms, users and clients. Keycloak will have certificate authentication where in mutual SSL will be enabled i.e., Keycloak would not only check for a valid client certificate but will also verify the identity of certificate owner. In addition, writing test cases for features or fixing JIRA bugs helped in realizing open source software development cycle.
If you love security, Keycloak will surely lead you to the rescue path of learning hell lot of security in and around single sign on. Keycloak truly defines the next generation authentication server for cloud, HTML5 and mobile.

Friday 11 September 2015

Keycloak 1.5.0.Final released

We've just released Keycloak 1.5.0.Final!

A few highlights from the release includes:

  • Custom auth flows - in 1.4.0 we introduced a new authentication and required actions SPIs, but we didn't make it possible to define your own flows. In this release you can now use the SPIs to create your own authenticators and also define your own authentication flows through the admin console
  • Custom auth flows for clients - we also made it possible to create your own authenticators and flows to authenticate clients.
  • Client signed token authentication - we introduced support to authenticate users with public/private keys and signed JWT tokens. This complements the introduction of service accounts from 1.4.0
  • Event/counter OTP for Google Authenticator and FreeOTP - through the admin console you can now configure if you want to use time based OTP or event based OTP
  • Make Infinispan cache default and remove in-mem cache - we removed the custom in-mem caches we had in previous releases and now only support the Infinispan based caches
  • Make Infinispan user session default and remove in-mem, jpa and mongo user session providers - we removed the JPA, Mongo and in-mem user session providers and will now focus on just the Infinispan based provider
  • Deal with time inconsistency in keycloak.js - the time on end-users computers can often be out of sync so we now deal with this in the javascript adapter by estimating the time skew between Keycloak and the users computer
  • Remove address from registration and account management - we've simplified the registration screen and account management and removed the address fields. If you need to add these or others you can now refer to the new address example theme

As usual we've been real busy and there's loads more, for full details check the release notes. To download the release go to keycloak.org.

Monday 7 September 2015

Windows 10 app with integrated Keycloak OAuth 2.0

Team Aerogear provides many useful libraries not only for Android, iOS and Cordova. They developed OAuth2.0 Nuget package for Windows Phone platform enabling user to easily authorized through Google, Facebook and even through Keycloak. On their github you can find Windows Phone 8.1 example application using this library to upload a captured photo on web application which displays these uploaded photos in slideshow. What I did was conversion of this example app to Windows 10 platform and analysis of cooperation with the latest version of Keycloak 1.4.0. After reading of several tutorials from various sources I decided to create one summarizing step by step tutorial which describes how to deploy this app on Windows 10 mobile emulator.

General requirements

Pre-requisites and settings

  1. Download Keycloak Demo Bundle (version 1.4.0 Final)
  2. Setup Keycloak to use SSL (original resource)
    1. Create Self Signed Certificate by command:
    2. keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
      (answer for the What is your first and last name? should be DNS name (IP adress) of PC with running server). PC and mobile should be connected to the same Wi-Fi network.
    3. Move generated keycloak.jks to keycloak-demo-1.4.0.Final/keycloak/standalone/configuration
    4. To security-realms in keycloak-demo-1.4.0.Final/keycloak/standalone/configuration/standalone.xml add:
      <security-realm name="UndertowRealm">
          <server-identities>
              <ssl>
                  <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" 
       keystore-password="SELECTED_PASSWORD" />
              </ssl>
          </server-identities>
      </security-realm>
      
    5. And to <server name="default-server"> element add:
<https-listener name="https" socket-binding="https" security-realm="UndertowRealm" />

Starting the server

  1. Start the server keycloak-demo-1.4.0.Final/keycloak/bin/standalone.bat -b 0.0.0.0
  2. Go to http://localhost:8080/auth/admin/index.html
  3. Login using admin / admin
  4. Click on Add realm and import this configuration file

Starting and setting the web application

  1. Download this project and get only the Shoot directory
  2. Add "auth-server-url": "/auth" to Shoot/src/main/webapp/WEB-INF/keycloak.json
  3. Build (mvn clean install)
  4. Open Shoot/target/shoot.war (with WinRAR for example) and add keycloak.cer there
  5. Go to http://localhost:9990/console/App.htmland navigate to Deployments and add shoot.war
    (if we deploy the .war by mvn wildfly:deploy, we would lost added certificate)

Installing certificate to Windows 10 emulator

  1. Open browser(Edge) and download the certificate by navigating to http://<IP>:8080/shoot/keycloak.cer where IP is the name of the certificate chosen earlier.
  2. Open and install the certificate

Preparing example app

Because this app was built for Windows Phone 8.1 platform, we need to convert the project to be executable on Windows 10, in other words the project has to target the Universal Windows Platform (UWP). There exists some scripts or nuget plugins which can do the conversion automatically, but finally there is more mess then before and you have to manually edit lot of stuffs in our case, so the most easiest way is to create new solution in VS15 for UWP and copy the source code into it.
  1. Download the source code of example app.
  2. Create new solution in VS15 and import the source code into it.
  3. Download the aerogear-windows-oauth2 project which is actually the source code of library available as Nuget package and import it to our solution
  4. Next you have to edit the MainPage.xaml.cs by configuring the IP adress to the same adress as the server is running on (it is assuring that it is going to run also on real device) and then add the line adding the scope to the configuration.
  5. Then in aerogear-windows-oauth2 project you should edit the class AccountManager.cs as below. That is because the manifest files of Windows Phone 8.1 and Windows 10 are different and the redirect protocol (org.aerogear.Shoot) is not that easy to parse from Windows 10 file.
  6. Build and run the solution on one of the Windows 10 emulators. The result is shown on screenshots below.

Application flow

  • You capture a photo (on emulator only this "tv noise"). Click on Keycloak icon, then you are redirected to login Keycloak page where you enter user / password (according to settings in realm). Finally we get feedback about succesfully uploaded image to our web application.
  • If we check the web application then, the image is visible there.

Conclusion

Library aerogear-windows-oauth2 was recently updated for Windows 10 as well so there is no need to manually edit the code in AccountManager and do other changes. It is good to say that this tutorial was focused mainly on Windows 10 mobile application, if we want to deal with desktop Windows 10 application, there has to be done some other additional changes such as adding the certificate directly to the "Trusted Publishers" and change of piece of code which does the authentication part.

Monday 31 August 2015

Service accounts support in Keycloak

From 1.4 we added support for Service accounts to Keycloak. This feature allows to authenticate the client application with Keycloak server and retrieve the access token dedicated to this application. No interaction with users needed. This is great for administrative tasks executed on behalf of a service instead of individual user. You also don't even need browser available, the communication with Keycloak server is done in background.

To support service accounts, you just need to enable switch "Service accounts enabled" for particular client in admin console and then map roles will, which will be available in access token granted to the client. How to send client authentication request and retrieve service account is described in documentation . There is also service account example, which is part of the main demo example application from keycloak example distribution.

Right now, we support authenticating clients just through Client Credentials Grant from OAuth 2.0 spec, but in the future we plan to add more ways how to authenticate clients. This will include public/private key pair (similarly like Google is doing), 2-way SSL with client certificates and maybe more. We also plan to add suport for offline tokens, which might be quite useful for the service accounts, as I suppose one of the main usecases for them is triggering various offline administrative tasks periodically etc.

Thursday 20 August 2015

Improved LDAP integration with Keycloak

LDAP integration in Keycloak is done through User Federation SPI. It works in a way that users are synced from LDAP into Keycloak database. This is needed because Keycloak needs to store various metadata about users and some of them may not be supported by the LDAP schema. The configuration of LDAP Federation provider in admin console is flexible enough, so you can choose whether your LDAP server is read-only or writable and whether new users created in Keycloak will be synced back to LDAP or just into Keycloak database etc.

Before 1.3.1 release we pulled just basic data of users from LDAP like first name, surname, email, username and password. From 1.3.1 we improved this and added support for LDAP mappers. This allows you even more flexibility in configuring which LDAP data are synced to Keycloak and back (for writable LDAP). Right now we have:

  • User Attribute mapper - This allows to specify which LDAP attributes are mapped to which User attributes in Keycloak. As you can see there are various things you can configure. For example you can specify if attribute is read-only. In this case will be data synced from LDAP to Keycloak DB, but not back to LDAP in case that user is changed in Keycloak.
  • Full name mapper - Allows some additional flexibity in mapping full name. Many LDAP deployments have full name in single LDAP attribute like "cn: John Doe". This mapper will ensure that this single attribute is properly mapped to first name and lastname in Keycloak DB
  • Role mapper - Allows to map role mappings from LDAP into Keycloak. You can specify LDAP DN where are roles configured and you can specify whether the roles are mapped into realm roles in Keycloak or to client roles of specified client. You can also specify the mode like whether role mappings are read-only or writable to LDAP etc.
Mapper SPI provides few callback methods, which are executed at the point when new user is registered in Keycloak, imported from LDAP or searched in Keycloak. You can implement the SPI and add your own mapper if default implementations are not sufficient.

Mappers were added in older 1.3.1 release, but in 1.4 we added more improvements and fixed lot of bugs based on the feedback from community. We also added simple LDAP example, which is part of Keycloak example distribution . It's really easy to have the example up and running, as it contains embedded ApacheDS based LDAP server, so only thing you need is JDK and maven. More documentation about mappers is in Keycloak documentation but note that admin console contains tooltips on various options and hence is quite self-documenting.

It's still possible that you can see the issues - various organizations have various data in their LDAP servers and it's quite a challenge to handle everything correctly in Keycloak. In this case, feel free to write questions on our keycloak-user mailing list or create JIRA.

Wednesday 29 July 2015

Keycloak 1.4.0.Final released

Keycloak 1.4.0.Final is available for download. As usual we've been busy bringing new features as well as a number of improvements and bug fixes (in fact we resolved 119 issues for this release!). The highlights of this release includes:
  • Authentication and Required Actions SPI - We've create SPIs for authentication flows and required actions and made existing flows pluggable. Currently the flows are hard-coded, but can be configured to some extent. In the future we'll make it possible to define your own authentication flows, authenticators as well as required actions.
  • Service account - We've added support for clients to obtain tokens on behalf of themselves. These tokens can be obtained by using the Client Credentials Grant flow. In the future we'll add support for additional mechanisms to authenticate clients.
  • User impersonation - Admins can now impersonate users. This allows admins to login to applications as a specific user without knowing the users credentials.
  • Re-captcha for registration - Re-captcha can be enabled for the registration page.
  • Upgrade to WildFly 9.0.1.Final - Keycloak is now built on top of WildFly 9.0.1.Final.
  • More details on server info page - There's now a bit more details about the Keycloak server on the server info page in the admin console.
  • Improvements to admin console We've had the UXP experts look at our admin console and we've already done some improvements. Expect more fine tuning of the admin console in the future.
For all changes in this release check out JIRA, to download the release go to the Keycloak website.

Wednesday 17 June 2015

Keycloak 1.3.1.Final Released

Keycloak 1.3.1.Final has just been released. There's not too many new features this time around, but a lot of improvements.

LDAP enhancements and mappers

This release brings a lot of improvements to our LDAP User Federation Provider and also introduces mappers for User Federation making it possible to map attributes and groups from LDAP to attributes and role mappings in the Keycloak database.

WildFly 9.0.0.CR2

Keycloak standalone is now built on WildFly 9.0.0.CR2. This also means that the server-overlay is only deployable to WildFly 9.0.0.CR2 and we no longer support WildFly 8.2.0.Final for the server. There's also a server-overlay-eap which supports deploying the server to EAP 6.4.0.GA.

We've also added adapter for WildFly 9. There's different downloads for WildFly 8 and 9, so make sure you grab the correct one.

Admin events

You can now enable admin events through the admin console. This will log all modifications done by admins. You can view what changes where made and by whom.

Easier cluster setup

It's now slightly easier to setup clustering as the included standalone-ha.xml contains the Infinispan configuration. All you need to do now is to change providers in keycloak-server.json and add a shared database.

Recover admin password

In the past if you forgot your admin password your only option was to edit the database directly. We've now introduced a mechanism that lets you recover the admin password. Obviously this requires you to have direct access to the server.

Release notes and download

For all issues resolved in this release see the change log in JIRA. As usual refer to the migration guide before upgrading. To download yet another great Keycloak release go to our web site.

Sunday 7 June 2015

OpenShift UI Console authentication with Keycloak and OpenID Connect

Two months ago OpenShift team implemented OpenID Connect support for authentication in its UI Console. Thanks to this work it can be easily integrated with Keycloak using fairly simple configuration. In this blog post I'll take you through example configuration process.

For complete documentation about configuration of authentication in OpenShift please check official guide here

Requirements:

  • Keycloak 1.2.0.Final zip distribution
  • Environment with properly installed and configured Docker 1.6. Steps below were verified on Fedora 22


Part 1 - Keycloak installation and SSL setup

OpenShift v3 requires usage of HTTPS and also verifies that requests are signed with valid Certificate Authority. For the purpose of this blog we'll take the shortest possible route and quickly generate our own CA and self signed certs. In practice even when using self signed certificates there are number of good practices to follow which we'll not cover here. Be warned that what is described below is not a proper production setup :)

Create a directory which will be used for Keycloak installation, certs and OpenShift configuration:
$ export DEMO_DIR=/home/bdaw/kc_os_demo 
$ mkdir $DEMO_DIR
$ cd $DEMO_DIR
$ mkdir certs
$ mkdir openshift
Those few commands below should generate dummy CA and a keystore for Keycloak with properly signed certificate. "localhost" should be used as a domain name and "secret" as a password.

$ cd certs
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
Enter keystore password: secret
Re-enter new password: secret
What is your first and last name?
 [Unknown]: localhost
What is the name of your organizational unit?
 [Unknown]: IT
What is the name of your organization?
 [Unknown]: ACME
What is the name of your City or Locality?
 [Unknown]: Eden
What is the name of your State or Province?
 [Unknown]: Heaven
What is the two-letter country code for this unit?
 [Unknown]: AA
Is CN=localhost, OU=IT, O=ACME, L=Eden, ST=Heaven, C=AA correct?
 [no]: yes
Enter key password for <localhost>
 (RETURN if same as keystore password): secret
Re-enter new password: secret 
$ keytool -certreq -alias localhost -keystore keycloak.jks > keycloak.careq
Enter keystore password: secret 
$ openssl genrsa -out rootCA.key 2048 

$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem
-----
Country Name (2 letter code) [XX]:AA
State or Province Name (full name) []:Heaven
Locality Name (eg, city) [Default City]:Eden
Organization Name (eg, company) [Default Company Ltd]:ACME
Organizational Unit Name (eg, section) []:IT
Common Name (eg, your name or your server's hostname) []:localhost
Email Address []:adam@acme.org 
$ openssl x509 -req -in keycloak.careq -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out keycloak-ca.crt -days 500
Signature ok
subject=/C=AA/ST=Heaven/L=Eden/O=ACME/OU=IT/CN=localhost
Getting CA Private Key 
$ keytool -import -keystore keycloak.jks -file rootCA.pem -alias root
Enter keystore password: secret
(...)
Trust this certificate? [no]:  yes
$ keytool -import -alias localhost -keystore keycloak.jks -file keycloak-ca.crt
Enter keystore password: secret
Certificate reply was installed in keystore 
$ ls
keycloak-ca.crt keycloak.careq keycloak.jks rootCA.key rootCA.pem rootCA.srl

Now unzip keycloak and copy created keystore
$ cd $DEMO_DIR
$ cp <dir_with_your_kc_zip>/keycloak-1.2.0.Final.zip .
$ unzip keycloak-1.2.0.Final
$ cp $DEMO_DIR/certs/keycloak.jks $DEMO_DIR/keycloak-1.2.0.Final/standalone/configuration/
To configure Keycloak to use SSL you need to follow procedure described in documentation. As you already have properly generated and signed certs in a keystore only changes in standalone.xml need to be applied.

Open $DEMO_DIR/keycloak-1.2.0.Final/standalone/configuration/standalone.xml in your favourite text editor and apply changes listed below:

To the security-realms element add:
<security-realm name="UndertowRealm">
        <server-identities>
            <ssl>
                <keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
            </ssl>
        </server-identities>
    </security-realm>
Find the element <server name="default-server"> (it's a child element of <subsystem xmlns="urn:jboss:domain:undertow:1.2">) and add:
<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>
Additionally we need to avoid conflict with default ports used by OpenShift. Find and adjust line below to change port 8080 to 8180 and 8443 to 8543:
<socket-binding name="http" port="${jboss.http.port:8180}"/>
<socket-binding name="https" port="${jboss.https.port:8543}"/>

Part II - Keycloak Configuration - Realm and OpenID Connect client for OpenShift

Start Keycloak and create new realm for openshift configuration
$ cd $DEMO_DIR/keycloak-1.2.0.Final/bin
$ ./standalone.sh
Go to https://localhost:8543/auth/admin

Log in with credentials admin/admin

In the top right corner click on "Add realm" link. Use "openshift" as a name and click "Save". You can play with configuration a bit if you want - allowing user registration and etc.



As a next step create "openshift" client

On the left side click on "Clients" and then "create" button. Fill in "openshift" for both client ID and name and "https://localhost:8443/*" for valid redirect URIs. Leave all other fields with default values.

Go to "Credentials" tab and copy value of "secret" field. It will be needed later in OpenShift configuration.



To verify authentication we'll need a sample user. On the left side click on "Users" and then "Add user". Use "test-user" as a username and click save. Then go to "Credentials" tab and set new password - for simplicity just use "password" as a value and submit with Enter :)

Voila! Now Keycloak should be properly configured to provide authentication for OpenShift. As you can see above biggest part of it was actually not related to OpenID Connect and OpenShift at all but to proper generation of certificates and SSL configuration... :)

Part III Openshift installation and configuration

There are few different ways to install OpenShift which are described either in official documentation or on github. Fabric8 can be used as well as it was described by Marko in one of previous posts

Simplest way to obtain needed parts to try out UI authentication is to use docker image and this is the setup we'll follow.

Start another terminal windows (first one should be occupied with running Keycloak server).
$ export DEMO_DIR=/home/bdaw/kc_os_demo 
$ sudo docker run -it --name "openshift-origin" --net=host --privileged -v /var/run/docker.sock:/var/run/docker.sock -v $DEMO_DIR:/opt/demo/ openshift/origin start master --write-config="/opt/demo/openshift/config"
It should create configuration files and exit.

Open $DEMO_DIR/openshift/config/master-config.yaml in your favorite text editor and adust configuration as below.

Find "oauthConfig" section and replace whole "identityProviders" section under it with content below:
   identityProviders:
  - name: keycloak
    challenge: false
    login: true
    provider:
      apiVersion: v1
      kind: OpenIDIdentityProvider
      ca: /opt/demo/certs/rootCA.pem
      clientID: openshift
      clientSecret: fdceb89f-3fa7-4b6d-8780-06074de5c62e
      claims:
        id:
        - sub
        preferredUsername:
        - preferred_username
        name:
        - name
        email:
        - email
      urls:
        authorize: https://localhost:8543/auth/realms/openshift/tokens/login
        token: https://localhost:8543/auth/realms/openshift/tokens/access/codes

Important thing to not forget - replace "clientSecret" value with the one which you found in Keycloak Admin UI.

As you can see "ca" is pointing to our dummy CA certificate (rootCA.pem). Alternatively you can remove this line and just add this cert to your system. OpenShift will validate against system wide ones by default.

Additionally locate the line starting with "logoutURL" and point it to Keycloak:

logoutURL: "https://localhost:8543/auth/realms/openshift/protocol/openid-connect/logout?redirect_uri=https://localhost:8443/console"

That is pretty much everything which is required on OpenShift side

In the master-config.yaml you can see to which IP address container is bind by checking "masterPublicURL" value. Obviously there are few other and probably better ways to determine it upfront... :). In my case it is "https://192.168.0.19:8443". This URL needs to be added to "openshift" client configuration in Keycloak as "Valid Redirect URI".



Now you can start OpenShift container again:
$ sudo docker rm openshift-origin
$ sudo docker run -it --name "openshift-origin" --net=host --privileged -v /var/run/docker.sock:/var/run/docker.sock -v $DEMO_DIR:/opt/demo/ openshift/origin start master --config="/opt/demo/openshift/config/master-config.yaml"
Go to "https://localhost:8443/console" and log in as "test-user" with password "password". Please note that you can also logout and this will properly get propagated to Keycloak.


In case of any issues you should hopefully see a meaningful error message logged either by OpenShift or by Keycloak server. Most common problems are related to network connectivity between OS and KC, certificate validation on the OS side and having proper redirect URI whitelisted in Keycloak. 

Huge thanks to Jordan Liggitt who implemented OpenID Connect support in OpenShift and Rob Cernich who contributed to it and initially tested it with Keycloak. You guys rock! :)