Running Keycloak with Docker

Keycloak is an Open Source Identity and Access Management solution for modern Applications and Services. Docker Images for Keycloak are available on the quay.io Docker repository. In this tutorial we will learn how to run it with Docker, using some common environment parameters.

So as said, the Docker Image for Keycloak is currently maintained in this repository: https://quay.io/repository/keycloak/keycloak

You can pull it as follows:

$ docker pull quay.io/keycloak/keycloak

On the other hand, when it’s time to run it, you would typically use some environment variables to make it fit for your applications. Let’s see some use cases.

Starting Keycloak and adding an Admin User

That is the most obvious use case, as an Admin user is needed in order to manage Keycloak:

docker run --rm --name keycloak -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin  -p 8180:8180  -it quay.io/keycloak/keycloak  -b 0.0.0.0  -Djboss.http.port=8180

You will see that Keycloak starts in foreground and binds to port 8180 (by default port 8080 will be used but it can clash with other services, like WildFly, running on that port):

09:16:07,923 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0025: Keycloak 15.0.2 (WildFly Core 15.0.1.Final) started in 22594ms - Started 692 of 977 services (686 services are lazy, passive or on-demand)
09:16:07,925 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0060: Http management interface listening on http://127.0.0.1:9990/management
09:16:07,925 INFO  [org.jboss.as] (Controller Boot Thread) WFLYSRV0051: Admin console listening on http://127.0.0.1:9990

Next, login to the Admin Console, which is available at: http://localhost:8180 with admin/admin:

Adding other Keycloak users

You can also add an Admin user on an already running container by executing the add-user-keycloak script available in the /opt/jboss/keycloak/bin folder.

Firstly, collect the container id:

$ docker ps

CONTAINER ID        IMAGE                        
31a5c280ecdf        quay.io/keycloak/keycloak

Next, run the following command:

docker exec 31a5c280ecdf /opt/jboss/keycloak/bin/add-user-keycloak.sh -u frank -p foo

You will see the following log:

Added 'frank' to '/opt/jboss/keycloak/standalone/configuration/keycloak-add-user.json', restart server to load user

Finally, restart the container with:

docker restart 31a5c280ecdf

Managing Keycloak Realms running on Docker

You can approach Keycloak management on docker in at least two ways. One option is using the Web Console as we have seen in the previous section. Another option is to use the Keycloak CLI which you can trigger with a docker exec command.

Let’s see it in action. Firstly, we need to login to Keycloak server:

docker exec 31a5c280ecdf /opt/jboss/keycloak/bin/kcadm.sh config credentials --server http://localhost:8180/auth --realm master --user admin --password admin

We have now logged with the admin user. Let’s use this session to add another realm:

docker exec 31a5c280ecdf /opt/jboss/keycloak/bin/kcadm.sh create realms -s realm=wildfly-realm -s enabled=true -o

If you want a quickstart example of Keycloak CLI you can check this tutorial: Keycloak quickstart example using CLI

Importing a Keycloak Realm at start up

Just in case you want to boot Keycloak and have your Realm imported, you can add the KEYCLOAK_IMPORT Environment variable and the Volume argument (-v) to specify the path where the JSON Realm file will be picked up:

docker run --rm \ 
--name keycloak \ 
-e KEYCLOAK_USER=admin \ 
-e KEYCLOAK_PASSWORD=admin \ 
-e KEYCLOAK_IMPORT=/tmp/realm.json -v /tmp/realm.json:/tmp/realm.json \ 
-p 8180:8180 \ 
-it quay.io/keycloak/keycloak \ 
-b 0.0.0.0 \ 
-Djboss.http.port=8180 \ 
-Dkeycloak.profile.feature.upload_scripts=enabled

Exporting a Keycloak Realm

If you want to export a realm that you have created you’ll need to ensure the container running Keycloak has a volume mapped. For example you can start Keycloak setting the volume (‘v’) option to the /tmp folder:

docker run -d -p 8180:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin -v $(pwd):/tmp --name keycloak quay.io/keycloak/keycloak

Then, you can then get the export from this instance by running:

docker exec -it keycloak keycloak/bin/standalone.sh \ 
-Djboss.socket.binding.port-offset=100 -Dkeycloak.migration.action=export \ 
-Dkeycloak.migration.provider=singleFile \ 
-Dkeycloak.migration.realmName=my_realm \ 
-Dkeycloak.migration.usersExportStrategy=REALM_FILE \ 
-Dkeycloak.migration.file=/tmp/my_realm.json

(notice we use -Djboss.socket.binding.port-offset=100 so that the export runs on a different port than Keycloak itself).

Configuring a Database for Keycloak Image

Keycloak image supports multiple database as backend. You can specify the DB vendor directly with the DB_VENDOR environment variable. Supported values are:

  • h2 for the embedded H2 database,
  • postgres for the Postgres database,
  • mysql for the MySql database.
  • mariadb for the MariaDB database.
  • oracle for the Oracle database.
  • mssql for the Microsoft SQL Server database.

Environment variable names can be used to configure any of the above Database type:

  • DB_ADDR: This is the hostname of the database (optional).
  • DB_PORT: This is the port of the database (optional, default is DB vendor default port)
  • DB_DATABASE: Specify name of the database to use (optional, default is keycloak).
  • DB_SCHEMA: Specify name of the schema to use for DB that support schemas.
  • DB_USER: This is the user to authenticate against the database (optional, default is “).
  • DB_USER_FILE: This is the user to authenticate to the database via file input (alternative to DB_USER).
  • DB_PASSWORD: Specify user’s password to use to authenticate to the database (optional, default is “).
  • DB_PASSWORD_FILE: Specify user’s password to use to authenticate to the database via file input (alternative to DB_PASSWORD).

PostgreSQL example

First, start a PostgreSQL instance:

docker run -d --name postgres --net keycloak-network -e POSTGRES_DB=keycloak -e POSTGRES_USER=keycloak -e POSTGRES_PASSWORD=password postgres

Next, launch the Keycloak server:

docker run --name keycloak --net keycloak-network quay.io/keycloak/keycloak  -e DB_USER=keycloak -e DB_PASSWORD=password

Keycloak tutorial for beginners – Mastertheboss

Keycloak is an Identity and Access Management Server for Modern Applications and Services. In this Keycloak tutorial we will learn how to set up Keycloak and configure it to authenticate/authorize Enterprise applications.

First of all, download the latest stable build of Keycloak from http://keycloak.jboss.org/keycloak/downloads

Then, you will need to patch our WildFly server in order to enable the keycloak subsystem, so download as well the keycloak adapter from https://www.keycloak.org/downloads.html

Starting Keycloak

Keycloak ships bundled in a WildFly installation. We will start it with an offset of 100 in order to avoid conflicts with our WildFly server (that will be bound with 0 offset), where our application will run:

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

Next, log into Keycloak Administration Console, available at: http://localhost:8180

In your first Login, you will be requested to create an administration user:

Next, login with the admin user you have just created:

Create your Realm, Roles and Users

The core concept in Keycloak is a Realm. A realm secures and manages security metadata for a set of users, applications, and registered oauth clients. Users can be created within a specific realm within the Administration console. Roles (permission types) can be defined at the realm level and you can also set up user role mappings to assign these permissions to specific users.

First, create a new Realm by clicking on the Add Realm Button, located on the left side bar:

Next, enter the Realm Name, for example MyRealm and click on Create:

Then, we will define a Role. The Role will be used by your applications to define which users will be authorized to access the application. Click on the “Roles” left link and choose “Add Role“:

We have added a Role named “Manager” that will be authorized to access our application. So far we don’t have any User, besides the admin user. We will create another one to be used by our application. Click on the “Users” left option and choose to Add a new User:

The User named “frank” will be added by clicking on Save. Now select the User from the list: we need to perform two actions on it.

The first one will be setting a password for it so click on Credentials and set a new Password for the user:

Finally, we will include the User as part of the Manager Role. Click on Role Mappings and assign the User to the Manager Role by selecting the Manager Role and clicking on Add selected:

Define secure Client policies

Done with User and Realms. We need to define which applications are mapped to our Users/Roles. In the earlier versions of KeyCloak you had to click on the “Applications” left link. Now applications are categorized as “Clients” so click on that link on the left:

Choose to Create a new Client. The most important settings are the application Root URL (that will be appended to the URI path) and the Redirect URIs where request will be forwarded after login. In our case, we will create a web application named “keydemo” therefore we will use the following settings:

Next, click on Save. Once saved, the last step will be generating a public key for your realm that will be bundled in your application. From the Clients perspective, click on the Installation link and choose to generate a JSON authorization code for your application:

Download the JSON or simply copy it in an editor, we will use it in a minute.

Installing Keycloak adapter for WildFly

Your application server, as it is, is now aware of Keycloak authentication/authorization mechanisms, hence we need to install an adapter for it. You should have already download the correct installer for your server version. In order to patch the application server perform these two steps:

1) Unzip the Adapter into the directory where you have installed WildFly:

Unzip this file into the root directory of your Wildfly distribution.

2) Next execute the CLI script to install the adapter:
For WildFly 10:

$ cd bin
$ ./jboss-cli.sh --file=adapter-install-offline.cli

For WildFly 11 and above:

$ cd bin
$ ./jboss-cli.sh --file=adapter-elytron-install-offline.cli

This script will make the appropriate edits to the …​/standalone/configuration/standalone.xml file of your app server distribution.

Great. Reload or Restart your server which now is Keycloak aware!

Securing applications with Keycloak

This paragraph of our Keycloak tutorial discusses how to secure applications. There are three options to authenticate your applications using Keycloak.

  • The first option consists in adding the Keycloak JSON file within your Web application and specify in web.xml that we will be using KEYCLOAK Auth.
  • The second option consists in configuring WildFly keycloak’s subsystem with the list of applications that will use KEYCLOAK Auth.
  • The third option allows to download the CLI command to run on WildFly to allow Keycloak Authentication/Authorization for a specific deployment unit.

Keycloak security in the Web application

Create a Web application that exposes the “/hello” URL and include within the web.xml file a security-constraint bound to the “Manager” Role. Also include as authentication mechanism “KEYCLOAK” which is not a standard JEE authentication mechanism, hence it needs that you patched the application server as we have describer earlier:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">

    <module-name>basicauth</module-name>
	
    <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>Manager</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>KEYCLOAK</auth-method>
        <realm-name>MyRealm</realm-name>
    </login-config>

    <security-role>
        <role-name>Manager</role-name>
    </security-role>
</web-app>

Next, we need to add, in the WEB-INF folder, is a keycloak.json with that contains the JSON descriptor we have just generated:

{
   "realm":"MyRealm",
   "auth-server-url":"http://localhost:8180/auth",
   "ssl-required":"external",
   "resource":"demo-keycloak",
   "credentials":{
      "secret":"86f1644f-b686-4011-8c05-31ca7245f94a"
   },
   "confidential-port":0
}

Save and deploy the application. If you try to access your application at localhost:8080/hello the Keycloak login authentication UI will prompt:

Enter your User’s credentials with the “Manager” Role and verify that you can access the pages contained in your application.

Plugging Keycloak security in the WildFly (XML)

This option has the advantage that can be applied without changing the content of your Web application. It requires accessing the XML Configuration of your WildFly Application Server.

From the Keycloak Clients Panel, select the Installation Tab and pickup in the Format OptionKeycloak OIDC JBoss Subsystem XML” as you can see from this picture:

Next, copy the XML template from the Installation page, and paste this into the standalone.xml file that resides in the standalone/configuration directory of the application server instance on which your application is deployed.

Open the standalone/configuration/standalone.xml file (or the one you use) and search for the following text:

<subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>

Simply paste the XML in the subsystem and replace the secure-deployment name with the application name. You are done!

Plugging Keycloak security in the WildFly (CLI)

Finally, the last option which you can use, is available in the Format OptionKeycloak OIDC JBoss Subsystem CLI” as you can see from this picture:

This option is the recommended choice. A common use case for it is creating a MicroService with WildFly Bootable Jar, where your server configuration includes custom CLI commands to run at start.

Some example applications

Well, done. You have just completed your first Keycloak tutorial. We have several examples of Application Secured with Keycloak.

If you want to check a JAX-RS application secured with Keycloak (WildFly) then check this tutorial: Keycloak OAUTH2 example with a REST Application

If you want to check a JAX-RS application secured with Keycloak (Spring Boot) then check this tutorial: Managing Keycloak user metadata and custom attributes

Keycloak OAUTH2 example with a REST Application

This article will guide you through understanding OAuth2 and OpenID usage with Keycloak using a JAX-RS filter named ContainerRequestFilter which is available in JAX-RS servers such as WildFly.

OpenID is a process which deals with authentication (i.e. proving who you are). On the other habd, OAuth is about authorisation (i.e. to grant access to resources without having to deal with the original authentication).

OAuth is typically used in external partner sites to allow access to protected data without them having to re-authenticate a user.

In order to run this example, you will need a Keycloak server up and running. To learn more about it, check this tutorial: Introduction to Keycloak

Using Keycloak Admin CLI to create a Realm

Our example requires a Keycloak Realm to be set up and a Client definition which is allows up to be authorized using a Token issued by Keycloak. You can create the Realm and Client by executing the following CLI, which uses Keycloak Admin CLI (located in the bin folder):

#Authenticate with the Admin Server    
./kcadm.sh config credentials --server http://localhost:8180/auth --realm master --user admin --password admin
#Create Realm Demo-Realm
./kcadm.sh create realms -s realm=demo-realm -s enabled=true -o
#Create User customer-admin
./kcadm.sh create users -r demo-realm -s username=customer-admin -s enabled=true -s email="joe@gmail.com"
#Set customer-admin password
./kcadm.sh set-password -r demo-realm --username customer-admin --new-password admin
#Create Client
./kcadm.sh create clients -r demo-realm -s clientId=customer-manager-client -s bearerOnly="false"   -s "redirectUris=[\"http://localhost:8080/*\"]" -s enabled=true -s directAccessGrantsEnabled=true -s clientAuthenticatorType=client-secret -s secret=mysecret
#Create Role customer-manager
./kcadm.sh create roles -r demo-realm -s name=customer-manager
#Assign Role to customer-admin 
./kcadm.sh add-roles --uusername customer-admin --rolename customer-manager -r demo-realm

You can check from Keycloak’s Admin Console that the Realm and Client have been correctly defined:

As you can see, we have defined as Redirect URI a generic localhost:8080 which will return, after checking the token, to the root page of a Web Server. In real world examples, you will want to redirect to a precise Web context.

Building the OAUTH Example

This project will run as WildFly Bootable Jar. To learn more about WildFly bootable Jar we recommend checking this tutorial: Turn your WildFly applications in bootable JARs
In terms of application set-up, the application will be a JAX-RS endpoint with a Secured endpoint.
Here is our JAX-RS Secured Endpoint:

The “hello” GET Endpoint returns a JSON which contains a set of information collected from the KeycloakPrincipal. It is going to include the Principal name (the User name that logged in) and the User’s email.

@Path("/")
public class MyService {
    @Context
    SecurityContext context;

    @GET
    @Path("hello")
    @RolesAllowed({"customer-manager"})
    @Produces(MediaType.APPLICATION_JSON)
    public HashMap hello() {
        KeycloakPrincipal principal = (KeycloakPrincipal) context.getUserPrincipal();
        
        HashMap map = new HashMap();
        map.put("principal",principal.getName());
        map.put("email", principal.getKeycloakSecurityContext().getToken().getEmail());
        
        Map<String, Object> customClaims = (principal.getKeycloakSecurityContext().getToken().getOtherClaims());
        map.putAll(customClaims);
        return map;				
     
    }

}

The Endpoint also collects the list of all available Claims, such as Custom Attributes, from the KeycloakSecurityContext. In the section “Adding Custom Attributes to our Realm” we will see how to add a Custom Attribute to our User.

The JAX-RS Endpoint requires an Activator to be available:

@ApplicationPath("/rest")
public class JaxRsActivator extends Application {
   /* class body intentionally left blank */
}

In order to use Keycloak Authentication, we have mainly three options. Check the Installation Tab of your Keycloak Client and select the Keycloak OIDS JBoss Subsystem CLI:

/subsystem=keycloak/secure-deployment="simple-webapp.war"/:add( \
    realm="demo-realm", \
    resource="customer-manager-client", \
    auth-server-url=http://localhost:8180/auth/, \
    ssl-required=EXTERNAL)

/subsystem=keycloak/secure-deployment="simple-webapp.war"/credential=secret:add(value=mysecret)

Include this CLI script in the root directory of your project.

Without our pom.xml, we will configure the project dependencies and, in the Bootable JAR plugin, the WildFly layers to be included in our Runtime and the Path to the CLI Script to be executed:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>com.mastertheboss.jaxrs</groupId>
   <artifactId>keycloak-demo</artifactId>
   <packaging>war</packaging>
   <version>1.0.0</version>
   <name>WildFly Bootable JAR - Keycloak</name>
   <description>An application secured with Keycloak example</description>
   <properties>
      <version.keycloak>13.0.0</version.keycloak>
      <version.wildfly>24.0.0.Final</version.wildfly>
      <surefire.version>3.0.0-M5</surefire.version>
      <maven.compiler.source>11</maven.compiler.source>
      <maven.compiler.target>11</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   </properties>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>jakarta.platform</groupId>
            <artifactId>jakarta.jakartaee-api</artifactId>
            <version>8.0.0</version>
            <scope>provided</scope>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>jakarta.platform</groupId>
         <artifactId>jakarta.jakartaee-api</artifactId>
         <scope>provided</scope>
      </dependency>
      <dependency>
         <groupId>org.keycloak</groupId>
         <artifactId>keycloak-core</artifactId>
         <version>15.0.1</version>
      </dependency>
   </dependencies>
   <build>
      <finalName>simple-webapp</finalName>
      <plugins>
         <plugin>
            <groupId>org.wildfly.plugins</groupId>
            <artifactId>wildfly-jar-maven-plugin</artifactId>
            <version>5.0.2.Final</version>
            <configuration>
               <feature-packs>
                  <feature-pack>
                     <location>wildfly@maven(org.jboss.universe:community-universe)#${version.wildfly}</location>
                  </feature-pack>
                  <feature-pack>
                     <groupId>org.keycloak</groupId>
                     <artifactId>keycloak-adapter-galleon-pack</artifactId>
                     <version>${version.keycloak}</version>
                  </feature-pack>
               </feature-packs>
               <layers>
                  <layer>jaxrs</layer>
                  <layer>management</layer>
                  <layer>keycloak-client-oidc</layer>
               </layers>
               <context-root>false</context-root>
               <cli-sessions>
                  <cli-session>
                     <script-files>
                        <script>keycloak.cli</script>
                     </script-files>
                  </cli-session>
               </cli-sessions>
            </configuration>
            <executions>
               <execution>
                  <goals>
                     <goal>package</goal>
                  </goals>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
</project>

You can start the application as follows:

mvn clean install wildfly-jar:run

Testing from the Browser

If you are testing the Endpoint from the browser, just head to:

http://localhost:8080/simple-webapp/rest/hello
You will be redirected to Keycloak Login Page:

Enter “customer-admin” / “admin” as User and Password. You will get as response the JSON Payload:
{
  "principal": "65007a42-be20-4172-a25a-a1f3f3f19e85",
  "email": "joe@gmail.com",

}

Testing from the Command Line

On the other hand,you can access the Endpoint from the Command Line as well. For that, we will at first collect the Keycloak Token sending the Username credentials and the Secret:

export access_token=$(\
    curl -X POST http://localhost:8180/auth/realms/demo-realm/protocol/openid-connect/token \
    --user customer-manager-client:mysecret \
    -H 'content-type: application/x-www-form-urlencoded' \
    -d 'username=customer-admin&password=admin&grant_type=password' | jq --raw-output '.access_token' \
 )

Then, you can access the Endpoint with cURL as follows:

curl -H "Authorization: Bearer $access_token" http://localhost:8080/simple-webapp/rest/hello

Adding Custom attributes to our Realm

Let’s add a Custom Attribute to our user. Custom Attributes are used to extend the basic Metadata information available to Users.

We will add a Custom Attribute from Keycloak Admin application. Select the Users Panel and check the Attributes Tab. There Click to Add an Attribute and Save it.

We have now added the customer.id Custom Attribute. To make this attribute available to our Client application, we need to create a Protocol Mapper. From your Clients Panel, select the customer-manager-client and the Mappers Tab and click on Create:

Above you can see the Mapper that has been added for the User attribute “customer.id“. Save the Mapper.

Accessing User Custom Attributes

Now that you have added a Custom Attribute to your Keycloak user, let’s try again to access the endpoint.

curl -s -H "Authorization: Bearer $access_token" http://localhost:8080/simple-webapp/rest/hello | jq
{
  "principal": "65007a42-be20-4172-a25a-a1f3f3f19e85",
  "email": "joe@gmail.com",
  "sid": "45c81ff7-3064-41d0-b376-a281492dc5a6",
  "customer": {
    "id": "1234"
  }
}

As you can see, the JSON Payoad now includes the customer.id attribute.

Conclusion

In this turorial we have covered how to create a JAX-RS Application protected with OAUTH2 and WildFly. If you want to see an equivalent REST Application running with Spring Boot and secured with Keycloak check this tutorial: Managing Keycloak user metadata and custom attributes

Source code for this tutorial: https://github.com/fmarchioni/mastertheboss/tree/master/keycloak/oauth2

Installing Keycloak Client adapters on WildFly

This article covers how to install Keycloak Client Adapters on WildFly so that you can let Keycloak manage the whole authentication/authorization of your applications running on WildFly.

Please note: If you are running WildFly 25 or above, you can secure your applications with Keycloak using Elytron OpenID Connect which is available out of the box.
Check this article to learn more: Secure WildFly applications with OpenID Connect

There are mainly three options for patching WildFly with Keycloak Client adapters:

1) Download Keycloak Client Adapters and run the install scripts

The most common option is to download Keycloak client adapters and install them on the top of your WildFly distribution.

Follow these steps:

  • Download the WildFly distribution and extract it from the compressed file into a directory on your machine.
  • Download the WildFly OpenID Connect adapter distribution from https://www.keycloak.org/downloads.html.
  • Extract the contents of this file into the root directory of your WildFly distribution.

When done, run the appropriate script for your platform:

WildFly 10

$ cd bin
$ ./jboss-cli.sh --file=adapter-install-offline.cli

Wildfly 11 and newer

$ cd bin
$ ./jboss-cli.sh --file=adapter-elytron-install-offline.cli

Start the application server.

$ cd bin
$ ./standalone.sh

An example application, running on the top of a patched WildFly installation, is shown in this tutorial: Introduction to Keycloak

2) Install Keycloak layer with Galleon

The keycloak-client-oidc Galleon layer brings the OIDC keycloak subsystem (and associated JBoss modules) and configures the server security. To install it, you need to download the Galleon tool from https://github.com/wildfly/galleon/releases

Once downloaded, unzip and move to the ‘bin’ folder. From there, launch the galleon script:

$ ./galleon.sh

At first, provision a basic WildFly distribution. For example a distribution which contains the web-server layer:

install wildfly:current --layers=web-server --dir=wildfly-keycloak

On the top of that, install the keycloak-adapter-galleon-pack:

install org.keycloak:keycloak-adapter-galleon-pack:12.0.2 --layers=keycloak-client-oidc --dir=wildfly-keycloak

Please notice that, unlike the WildFly feature pack, the Keycloak feature pack is not part of a Galleon universe and so a fully qualified group:artifact:version reference to the feature pack is required.

That’s it. You can now start the application server.

$ cd wildfly-keycloak/bin
$ ./standalone.sh

3) Running your application as Bootable JAR with Keycloak layer

This approach also uses Galleon under the hoods. However, we will be able to run our application as Bootable Jar. Just as a recap, to turn your application as Bootable Jar, it is required to include the wildfly-jar-maven-plugin in your pom.xml file. Within its configuration, we will include the keycloak-adapter-galleon-pack:

    <build>
        <finalName>simple-webapp</finalName>
        <plugins>
            <plugin>
                <groupId>org.wildfly.plugins</groupId>
                <artifactId>wildfly-jar-maven-plugin</artifactId>
                <configuration>
                    <feature-packs>
                        <feature-pack>
                            <location>wildfly@maven(org.jboss.universe:community-universe)#${version.wildfly}</location>
                        </feature-pack>
                        <feature-pack>
                            <groupId>org.keycloak</groupId>
                            <artifactId>keycloak-adapter-galleon-pack</artifactId>
                            <version>12.0.2</version>
                        </feature-pack>
                    </feature-packs>
                    <layers>
                        <layer>web-server</layer>
                        <layer>keycloak-client-oidc</layer>
                    </layers>
                    <context-root>false</context-root>
                    <cli-sessions>
                        <cli-session>
                            <script-files>
                                <script>configure-oidc.cli</script>
                            </script-files>
                        </cli-session>
                    </cli-sessions>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Also notice, to enable Keycloak secure deployments, we need to add a reference to the Keycloak Realm to our deployment. This is done by the configure-oidc.cli script that will be launched on our Bootable WildFly server:

/subsystem=keycloak/secure-deployment=simple-webapp.war:add(realm=wildfly-realm, resource=simple-webapp, public-client=true, auth-server-url=http://localhost:8180/auth/, ssl-required=EXTERNAL)

The full example, forked from WildFly Bootable Jar repository, is available here: https://github.com/fmarchioni/mastertheboss/tree/master/bootable-jar/keycloak

In this repository I have added a script for creating a Keycloak Realm so that you can test it against a Docker image of Keycloak. Let’s see how to test it. First start Keycloak Docker image to run on port 8180:

docker run --rm     --name keycloak    -e KEYCLOAK_USER=admin    -e KEYCLOAK_PASSWORD=admin     -p 8180:8180    -it quay.io/keycloak/keycloak    -b 0.0.0.0    -Djboss.http.port=8180    

Now copy the script.sh available in the root folder in the folder /opt/jboss/keycloak/bin of your Keycloak server:

docker cp script.sh keycloak:/opt/jboss/keycloak/bin

Then, set execution permissions and run the script:

docker exec -it keycloak chmod 755 /opt/jboss/keycloak/bin/script.sh
docker exec -it keycloak /opt/jboss/keycloak/bin/script.sh

The script we have just run, creates a Keycloak Realm named “wildfly-realm” with a Role named “Users”, one User (demo/demo) and a Client application to which we will redirect after login:

#!/bin/bash

cd /opt/jboss/keycloak/bin

./kcadm.sh config credentials --server http://localhost:8180/auth --realm master --user admin --password admin
./kcadm.sh create realms -s realm=wildfly-realm -s enabled=true -o
./kcadm.sh create users -r wildfly-realm -s username=demo -s enabled=true
./kcadm.sh set-password -r wildfly-realm --username demo --new-password demo
./kcadm.sh create clients -r wildfly-realm -s clientId=simple-webapp -s publicClient="true"  -s "redirectUris=[\"http://localhost:8080/simple-webapp/*\"]" -s enabled=true
./kcadm.sh create roles -r wildfly-realm -s name=Users
./kcadm.sh add-roles --uusername demo --rolename Users -r wildfly-realm

That’s it. Now start the Bootable jar:

$ mvn install; java -jar target/simple-webapp-bootable.jar

Reach the secured Servlet at http://localhost:8080/simple-webapp/secured

The Keycloak Login for the Realm will prompt:

Enter demo/demo. You will be able to access the secured Servlet.

That’s it! Enjoy Keycloak with WildFly.

Configuring Keycloak Database

This tutorial will show you three different ways to configure a different database for your Keycloak Identity Provider. Let’s check it out!

Configuring a local Keycloak Database

So the first way to configure a Keycloak Identity Provider with a Database is by adding a Datasource configuration specific for keycloak. This can be done by setting the property dataSource of your keycloak subsystem, nested into the spi element:

<subsystem xmlns="urn:jboss:domain:keycloak-server:1.1">
    ...
    <spi name="connectionsJpa">
     <provider name="default" enabled="true">
         <properties>
             <property name="dataSource" value="java:jboss/datasources/KeycloakDS"/>
             <property name="initializeEmpty" value="false"/>
             <property name="migrationStrategy" value="manual"/>
             <property name="migrationExport" value="${jboss.home.dir}/keycloak-database-update.sql"/>
         </properties>
     </provider>
    </spi>
    ...
</subsystem>

Therefore, you have to provide a valid KeycloakDS definition in your configuration. For example, if you were to use MySQL as back-end for your Keycloak server:

<subsystem xmlns="urn:jboss:domain:datasources:4.0">
   <datasources>
      <datasource jndi-name="java:/jboss/datasources/KeycloakDS" pool-name="KeycloakDS" enabled="true">
         <connection-url>jdbc:mysql://localhost:3306/keycloak?useSSL=false&characterEncoding=UTF-8</connection-url>
         <driver>mysql</driver>
         <pool>
            <min-pool-size>5</min-pool-size>
            <max-pool-size>15</max-pool-size>
         </pool>
         <security>
            <user-name>keycloak</user-name>
            <password>keycloak</password>
         </security>
         <validation>
            <valid-connection-checker class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLValidConnectionChecker" />
            <validate-on-match>true</validate-on-match>
            <exception-sorter class-name="org.jboss.jca.adapters.jdbc.extensions.mysql.MySQLExceptionSorter" />
         </validation>
      </datasource>
      <drivers>
         <driver name="mysql" module="com.mysql">
            <driver-class>com.mysql.jdbc.Driver</driver-class>
         </driver>
      </drivers>
   </datasources>
</subsystem>

For that to work, you have to create the schema on the Keycloak Database:

mysql> CREATE USER 'keycloak'@'%' IDENTIFIED BY 'keycloak';
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE DATABASE keycloak CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON keycloak.* TO 'keycloak'@'%';
Query OK, 0 rows affected (0.00 sec)

Well that appears to be a bit verbose, so let’s see how we can speed up things using the Docker image of keycloak. For more info about how to use the Docker image of keycloak check this tutorial: Running Keycloak with Docker

Creating a Docker Network to bind Keycloak with a Database

So, the next option we will show, consists in creating an User Defined Network with docker, in order to connect the Docker image of Keycloak with that of a Database.

The following command will create an user defined bridge network:

docker network create keycloak-network

Now start the Database instance, for example a PostgreSQL instance, passing as argument (–net) the user defined network:

docker run -d --name postgres --net keycloak-network -e POSTGRES_DB=keycloak -e POSTGRES_USER=keycloak -e POSTGRES_PASSWORD=password postgres

Start a Keycloak instance, passing as well as argument the user’s defined network:

docker run --name keycloak --net keycloak-network jboss/keycloak -e DB_USER=keycloak -e DB_PASSWORD=password

That’s all. pretty cool isn’t it?

Using Docker compose to manage Keycloak and the DB Container

Lastly, it is worth mentioning that you can use Docker-Compose tool to manage both Keycloak Identity Provider and the Database container image in a single file. In this approach, we will use the DB_VENDOR environment variable of keycloak’s image to determine which database we want to link to. Here’s an example docker-compose.yml file which configures Keycloak with PostgreSQL Database:

version: '3'

volumes:
  postgres_data:
      driver: local

services:
  postgres:
      image: postgres
      volumes:
        - postgres_data:/var/lib/postgresql/data
      environment:
        POSTGRES_DB: keycloak
        POSTGRES_USER: keycloak
        POSTGRES_PASSWORD: password
  keycloak:
      image: jboss/keycloak
      environment:
        DB_VENDOR: POSTGRES
        DB_ADDR: postgres
        DB_DATABASE: keycloak
        DB_USER: keycloak
        DB_SCHEMA: public
        DB_PASSWORD: password
        KEYCLOAK_USER: admin
        KEYCLOAK_PASSWORD: Pa55w0rd
        # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
        #JDBC_PARAMS: "ssl=true"
      ports:
        - 8080:8080
      depends_on:
        - postgres

You can simply run it with:

docker-compose up

In this tutorial we have covered how to configure Keycloak Identity Provider with a Database. Check this Github page for more examples of Docker-compose files for various Databases: https://github.com/keycloak/keycloak-containers/tree/master/docker-compose-examples

Keycloak quickstart example using CLI

In this tutorial we will learn how to create a quickstart Java EE application secured with Keycloak using its command line interface (kcadm).

The requirements to run this tutorial are:

  • A Keycloak server
  • A WildFly Application Server with Keycloak plugin installed

You can check this tutorial for more details about the set up of Keycloak on WildFly: Introduction to Keycloak

What we will learn now is how to use kcadm shell which is available in the bin folder of the Keycloak installation.

First of all, we need to login using the Admin credentials of Keycloak. If your username and password are both “admin”, then you can log in with:

$ ./kcadm.sh config credentials --server http://localhost:8180/auth --realm master --user admin --password admin

Now let’s create a Realm named “wildfly-realm”:

$ ./kcadm.sh create realms -s realm=wildfly-realm -s enabled=true -o

Then we add one user for this realm:

$ ./kcadm.sh create users -r wildfly-realm -s username=customer-admin -s enabled=true

$ ./kcadm.sh set-password -r wildfly-realm --username customer-admin --new-password admin

We add one Client, which will use a Public Login/Password challenge, redirecting to our application Web Context (“helloworld”):

$ ./kcadm.sh create clients -r wildfly-realm -s clientId=customer-manager-client -s publicClient="true"  -s "redirectUris=[\"http://localhost:8080/helloworld/*\"]" -s enabled=true

Finally, we add a role for our user, that will match with the Role in the Java EE App:

$ ./kcadm.sh create roles -r wildfly-realm -s name=customer-manager

$ ./kcadm.sh add-roles --uusername customer-admin --rolename customer-manager -r wildfly-realm

That’s all. We will now connect an example application to our Keycloak module.

Within our applicaton, we will add the keycloak.json file, which can be retrieved from the Client Tab:

Here is it:

{
  "realm": "wildfly-realm",
  "auth-server-url": "http://localhost:8180/auth",
  "ssl-required": "external",
  "resource": "customer-manager-client",
  "public-client": true,
  "confidential-port": 0
}

Then, we specify in the web.xml descriptor that we are using KEYCLOAK as auth-method and we are restricting all pages to the Role “customer-manager”:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
     
    <security-constraint>
        <web-resource-collection>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>customer-manager</role-name>
        </auth-constraint>
    </security-constraint>
 
    <login-config>
        <auth-method>KEYCLOAK</auth-method>
        <realm-name>wildfly-realm</realm-name>
    </login-config>
 
    <security-role>
        <role-name>customer-manager</role-name>
    </security-role>
 
</web-app>

That’s all. Our minimalist Web application will expose just a REST Service which produces some text:

@Path("/hello")
public class HelloService {
	@GET
	@Path("/text")
	public String getHello () 
	{
		return "hello world!";
	} 
	@GET
	@Path("/json")
	@Produces(MediaType.APPLICATION_JSON)
	public SimpleProperty getPropertyJSON ()
	{
        SimpleProperty p = new SimpleProperty("key","value");
		return p;
	}
	@GET
	@Path("/xml")
	@Produces(MediaType.APPLICATION_XML)
	public SimpleProperty getPropertyXML () 
	{
        SimpleProperty p = new SimpleProperty("key","value");
		return p;
	}
}

You can check for the full source code of this application here:

https://github.com/fmarchioni/mastertheboss/tree/master/keycloak/helloworld

Build and deploy the application, then check one available endpoint. For example: http://localhost:8080/helloworld/rest/hello/text

A login challenge will be sent:

Enter the username/password for the user we have just created (customer-admin/admin). You will be redirected by Keycloak to the endpoint selected.

That’s all. Enjoy WildFly and Keycloak!

Securing a MicroProfile application with Keycloak

In this tutorial we will learn how to secure a Microprofile application running with Thorntail runtime and Keycloak.

 

Keycloak is an Identity and Access Management Server for Modern Applications and Services. In this tutorial we will learn how to delegate a bash Web application authentication (running on WildFly) to a KeyCloak server.

First of all, download the latest stable build of Keycloak from http://keycloak.jboss.org/keycloak/downloads

Starting Keycloak

Keycloak ships bundled in a WildFly installation. We will start it with an offset of 100 in order to avoid conflicts with our default Thorntail runtime (that will be bound with 0 offset), where our application will run:

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

Now log into the Administration Console, available at: http://localhost:8180

In your first Login, you will be requested to create an administration user:

Next, login with the admin user you have just created:

Create your Keycloak Realm, Roles and Users

The core concept in Keycloak is a Realm. A realm secures and manages security metadata for a set of users, applications, and registered oauth clients. Users can be created within a specific realm within the Administration console. Roles (permission types) can be defined at the realm level and you can also set up user role mappings to assign these permissions to specific users.

Let’s start by creating a new Realm by clicking on the Add Realm Button, located on the left side bar:

Enter the Realm Name, for example MyRealm and click on Create:

Now we will define a Role. The Role will be used by your applications to define which users will be authorized to access the application. Click on the “Roles” left link and choose “Add Role“:

We have added a Role named “Manager” that will be authorized to access our application. So far we don’t have any User, besides the admin user. We will create another one to be used by our application. Click on the “Users” left option and choose to Add a new User:

The User named “frank” will be added by clicking on Save. Now select the User from the list: we need to perform two actions on it.

The first one will be setting a password for it so click on Credentials and set a new Password for the user:

Next we will include the User as part of the Manager Role. Click on Role Mappings and assign the User to the Manager Role by selecting the Manager Role and clicking on Add selected:

Define Client policies

Done with User and Realms. We need to define which applications are mapped to our Users/Roles. In the earlier versions of KeyCloak you had to click on the “Applications” left link. Now applications are categorized as “Clients” so click on that link on the left:

Choose to Create a new Client. The most important settings are the application Root URL (that will be appended to the URI path) and the Redirect URIs where request will be forwarded after login. In our case, we will create a web application named “keydemo” therefore we will use the following settings:

Click on Save. Once saved, the last step will be generating a public key for your realm that will be bundled in your application. From the Clients perspective, click on the Installation link and choose to generate a JSON authorization code for your application:

Download the JSON or simply copy it in an editor, we will use it in a minute.

Securing a Microprofile application with Keycloak

We will be creating a simple JAX-RS application that exposes an “/hello” resource. We therefore need the jaxrs and keycloak fraction in our configuration:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.thorntail.examples</groupId>
   <version>1.0</version>
   <artifactId>example-keycloak</artifactId>
   <name>Thorntail Examples: Keycloak</name>
   <description>Thorntail Examples: Keycloak</description>
   <packaging>war</packaging>
   <properties>
      <version.thorntail>2.4.0.Final</version.thorntail>
   </properties>
   <build>
      <plugins>
         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
               <failOnMissingWebXml>false</failOnMissingWebXml>
            </configuration>
         </plugin>
         <plugin>
            <groupId>io.thorntail</groupId>
            <artifactId>thorntail-maven-plugin</artifactId>
            <executions>
               <execution>
                  <id>package</id>
               </execution>
            </executions>
         </plugin>
      </plugins>
   </build>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>io.thorntail</groupId>
            <artifactId>bom-all</artifactId>
            <version>${version.thorntail}</version>
            <scope>import</scope>
            <type>pom</type>
         </dependency>
      </dependencies>
   </dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>io.thorntail</groupId>
         <artifactId>jaxrs</artifactId>
      </dependency>
      <dependency>
         <groupId>io.thorntail</groupId>
         <artifactId>keycloak</artifactId>
      </dependency>
   </dependencies>
</project>

Here is our Application class that activates the REST resource:

package com.demo;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/")
public class SecuredApplication extends Application {
}

Ans our minimal JAX-RS endpoint:

package com.demo;

import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
 
@Path("/hello")
public class HelloWorldEndpoint {
 
  @GET
  @Produces("text/plain")
  public Response doGet() {
    return Response.ok("Hello from Thorntail!").build();
  }
}

Now, we need to specify in our Thorntail configuration (src/main/resources/project-defaults.yml) that we will be using KEYCLOAK Authentication for our Web application:

thorntail:
  deployment:
    example-keycloak-1.0.war:
      web:
        login-config:
          auth-method: KEYCLOAK
        security-constraints:
          - url-pattern: /*
            methods: [GET]
            roles: [Manager]

The last thing we need to add, in the WEB-INF folder, is the keycloak.json with that contains the JSON descriptor we have just generated.

{
  "realm": "MyRealm",
  "auth-server-url": "http://localhost:8180/auth",
  "ssl-required": "external",
  "resource": "demo-keycloak",
  "credentials": {
    "secret": "86f1644f-b686-4011-8c05-31ca7245f94a"
  },
  "confidential-port": 0
}

Save and deploy the application. If you try to access your application at http://localhost:8080/hello the Keycloak login authentication UI will prompt:

Enter your User’s credentials with the “Manager” Role and verify that you can access the pages contained in your application.

That’s all! We have covered how to secure a Microprofile application using Keycloak.

Google Social Login with KeyCloak

In this tutorial we will learn how to create a Social Login with Keycloak using Google Identity Brokering

An Identity broker is responsible for creating a trust relationship with an external Identity provider in order to use its identities to access internal services exposed by service providers. The identity provider is usually based on a specific protocol that is used to authenticate and communicate authentication and authorization information to their users. It can be a social provider such as Facebook, Google or Twitter.

In this example, we will learn how to use Google as Identity Provider. Here are the steps required to get started with it:

Create a new Realm Definition

Login into Keycloak administration console and create a new Realm definition. For example, create the Realm Google-Auth

Create a Google Application

Next, move to Google APIs Portal: https://console.developers.google.com amd define a new API.

Now click on the Create Credentials button and choose OAuth Client ID

In the following window, select Web application as Application type and, in the Authorized Redirect URI, you have to specify your Keycloak URI, relative to your Realm, in our case http://localhost:8080/auth/realms/Google-Auth/broker/google/endpoint

In the end, when you save, the ClientID and Secret will be generated (Keet it safe!)

Create an Identity Provider in Keycloak

Now switch back to the Keycloak Administration console and click on Identity Providers. From there, in the combobox located in the top right corner, choose to Add Provider and as Social select “Google”. Here you will have to insert the ClientID and Secret that was just generated:

Great. Now you need generating a Client application.

Create a Client Application

From the Administration console, add a new Client and specify the settings related to the Web context:

In our case, the application named googledemo.war will be available on localhost:8180, therefore set the Redirect URIs accordingly.

Great, install the realm via the JSON file or as a subsystem (See this tutorial for more info about it: Introduction to Keycloak )

Let’s rollup!

Now, as you deploy your googledemo.war application you will be able to use the Google identity provider- just click on the Google+ button and login with your Google Account:

Great! We were able to secure a Web application using a Social identity provider. More examples are available on github at: https://github.com/keycloak/keycloak/tree/master/examples/demo-template