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.