OpenID Connect with Keycloak

This blog shows how to use Keycloak for OAuth 2.0 and OpenID Connect. Keycloak is an identity and access management solution. Among its list of supported authentication mechanisms are SAML 2.0 and OpenID Connect. It is open source and can be installed via Docker. I wrote how to install Keycloak via Docker in a separate blog. The content of this blog was created as a side effect of configuring NetWeaver ABAP with Keycloak for SAML 2.0 and OAuth 2.0.

Here I will detail the steps to create an OAuth client in Keycloak, assign an OAuth 2.0 scope to it and how to get the OpenID Connect tokens for the client. For a better readability the steps are available as independent blogs / articles.

  1. Create OAuth client in Keycloak
  2. Create OAuth scope
  3. Add OAuth scope to client
  4. Get OpenID Connect tokens
Let the world know

Get OpenID Connect tokens from Keycloak

After creating an OAuth 2.0 scope and client and assigning the scope to the client, we can test the configuration. To do this, we need to log on in Keycloak as the OAuth 2.0 client. Keycloak will then validate the client and provide the Access Tokens and the scope(s) assigned to the client.

I will use Postman to test the setup. The Postman requests can be found in my GitLab repository. The request is as following:

  • Type: POST
  • URL: http://localhost:8080/auth/realms/master/protocol/openid-connect/token
  • Header: Content-Type application/x-www-form-urlencoded
  • Body: grant_type=client_credentials&client_id=oidclient&client_secret=7bc40a29-3eba-4c01-a9f1-9ebbb2eb8e9c

To authenticate, you need to send the client_id and client secret. These are the same values as for the client in Keycloak.

client_id: oidclient
client_secret: 7bc40a29-3eba-4c01-a9f1-9ebbb2eb8e9c

The parameter grant_type informs Keycloak about the authentification type we want. Client_credentials means that we send the client secret, and together with the client id this authenticates the client. Make sure to protect the client secret! This also explains why HTTPS is a minimum requirement.

grant_type: client_credentials

Result

Keycloak returns the JWT, including the access and refresh token as well as the scope. The assigned scope ZDEMO_CDS_SALESORDERITEM_CDS_0001 is included, allowing the client to access resources that are assigned to that scope.

{
   "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICIyeFlIOWNnTThaSzl2Rm1nSEN3QzFiMlRWQzdCZGNldWIyTjB0SGRjU3dZIn0.eyJqdGkiOiIzODM1ODk0My1jMDRmLTRhMTktOTVkMS0wMjY5YTYwNGUyYmUiLCJleHAiOjE1NzQzNDAwNDIsIm5iZiI6MCwiaWF0IjoxNTc0MzM2NDQyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6IjBlMmQxMGIyLTQwOTMtNGUzNi1iMjJiLTQ0MTg4MTE5NjVjOCIsInR5cCI6IkJlYXJlciIsImF6cCI6Im9pZGNsaWVudCIsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9zdGF0ZSI6Ijc2Y2QxOTY1LTFhYjgtNDM1ZC05NThiLWNiNDQxOGM1OWIwOCIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiWkRFTU9fQ0RTX1NBTEVTT1JERVJJVEVNX0NEU18wMDAxIHByb2ZpbGUgZW1haWwiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImNsaWVudEhvc3QiOiIxNzIuMTcuMC4xIiwiY2xpZW50SWQiOiJvaWRjbGllbnQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJzZXJ2aWNlLWFjY291bnQtb2lkY2xpZW50IiwiY2xpZW50QWRkcmVzcyI6IjE3Mi4xNy4wLjEiLCJlbWFpbCI6InNlcnZpY2UtYWNjb3VudC1vaWRjbGllbnRAcGxhY2Vob2xkZXIub3JnIn0.CTrO-XuNM0pxa3xrJNZqGTkPzd88_AcvVKtbG7dy6cMwg_n8f1P2k2afoQMG-sN6JQzQ-Ei_0OIGkXrV6TGWLZqBI3Tgu3NKDoLMWu1PS7N9YA1ubXJN_277L91usWzqmaE_9o5Q6ubenh319tyBL5JUqe5veEfv5WabzwsbPqbx7BfiTf3iE0_xEyWrdXCT64s60hGRSUZqC8Pgz2qLKArfDF_Bs_w20R7Cr50qHx3WJQNO-w_X2DiufmgKD5Cb8Ue8TlpA9o5F88ZKzce-GVplJKY8d35Wjr07DuDTVFQzSWsBSM0Oi0FKuBYGy4mfXjcz8g0tKtcplf2UFurqmA",
    "expires_in": 3600,
    "refresh_expires_in": 1800,
   "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJmZmI5NDQ5ZS02MGIxLTQyZTMtYmEwYy1iNjQ0NDc0MjZiNDQifQ.eyJqdGkiOiJkMDc2Yzk3NS04ODA0LTRhNDUtODE3NS1jMmYxZDJjYzExZjIiLCJleHAiOjE1NzQzMzgyNDIsIm5iZiI6MCwiaWF0IjoxNTc0MzM2NDQyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvYXV0aC9yZWFsbXMvbWFzdGVyIiwiYXVkIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL2F1dGgvcmVhbG1zL21hc3RlciIsInN1YiI6IjBlMmQxMGIyLTQwOTMtNGUzNi1iMjJiLTQ0MTg4MTE5NjVjOCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJvaWRjbGllbnQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI3NmNkMTk2NS0xYWI4LTQzNWQtOTU4Yi1jYjQ0MThjNTliMDgiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoiWkRFTU9fQ0RTX1NBTEVTT1JERVJJVEVNX0NEU18wMDAxIHByb2ZpbGUgZW1haWwifQ.blSzmr6gHXIhHY2ikAEXDiBfVQ17eVJsiWFdly8Krkk",
    "token_type": "bearer",
    "not-before-policy": 0,
    "session_state": "76cd1965-1ab8-435d-958b-cb4418c59b08",
    "scope": "ZDEMO_CDS_SALESORDERITEM_CDS_0001 profile email"
}

The content is encoded. Using a site like jwt.io, the content of the tokens can be decoded. For the access token:

{
	"jti": "38358943-c04f-4a19-95d1-0269a604e2be",
	"exp": 1574240042,
	"nbf": 0,
	"iat": 1574136442,
	"iss": "http://localhost:8080/auth/realms/master",
	"aud": "account",
	"sub": "0e2d10b2-4093-4e36-b22b-4418811965c8",
	"typ": "Bearer",
	"azp": "oidclient",
	"auth_time": 0,
	"session_state": "76cd1965-1ab8-435d-958b-cb4418c59b08",
	"acr": "1",
	"realm_access": {
		"roles": [
			"offline_access",
			"uma_authorization"
		]
	},
	"resource_access": {
		"account": {
			"roles": [
				"manage-account",
				"manage-account-links",
				"view-profile"
			]
		}
	},
	"scope": "ZDEMO_CDS_SALESORDERITEM_CDS_0001 profile email",
	"email_verified": false,
	"clientHost": "168.192.0.1",
	"clientId": "oidclient",
	"preferred_username": "service-account-oidclient",
	"clientAddress": "172.17.0.1",
	"email": "service-account-oidclient@placeholder.org"
}
Let the world know

Add OAuth 2.0 scope to client in Keycloak

After performing the previous steps in Keycloak, an OAuth 2.0 scope and client is available. To get the scope after the OAuth 2.0 client authenticates against Keycloak, you need to assign the scope to the client.

Log on to Keycloak and go to clients and select oidclient. This is the client created earlier.

Go to tab “Client Scopes”

Assign the previously created scope to the client.

Result

The scope is assigned to the client. Now the client can authenticate and Keycloak will issue the OIDC tokens and include the given scope.

Let the world know

Update PHP version on Amazon EC2

It was time to update the PHP version on my WordPress server. WordPress gave me warnings; the site health plugin gave me a warning. Plugins gave me warnings. PHP, IT news sites, the internet, warnings everywhere.

I knew that my PHP version was very old. But still supported. At least until beginning of 2019. When I configured the server for the first time several years ago, the installed PHP version was already not the latest. It was what yum install php gave me. Updating software is crucial, so I decided to finally touch my running system.

WordPress provides a site explaining how to update your PHP version. The update process in the documentation goes like: write an email to your hoster. Or: Not working in my case. For those that want to know how to update PHP on a Amazon AMI EC2 instance, here are the stops and my lessons learned.

Preparations

First, do a backup. Update WordPress and the plugins. Check that the plugins are compatible with PHP 7.2

  • Backup: See my blog on how to create a snapshot of a EC2 instance.
  • Update WordPress and plugins: Easy: just do as always and keep it up-to-date.
  • Check plugins for compatibility: A plugin is available to check the installed plugins and files for compatibility with PHP 7.x. Install and activate it and run a test.

The PHP Compatibility plugin is started from the WP Admin site. Hint: in my case, the plugin worked fine, but also crashed the server. After running it and saving the results, uninstall it.

This gives as an output an evaluation of the plugins and their compatibility status.

Update

Next step is to update PHP. Use the package manager for this. I’ll split the installation process in two parts: PHP and the additional packages.

sudo yum update
sudo yum install php72
sudo yum install php72-opcache php72-mysqlfnd php72-gd php72-pecl-imagick php72-bcmath

Result installation PHP 7.2

Result Installation of additional PHP packages

Activate PHP

After installing PHP 7.2 it must be activated. The old PHP version is still the default one, meaning that calling php is not calling php 7.2. To change the paths, run alternative. It will show the available alternatives and asks which one you want to use. I am going to use php 7.2, so the input here was 2.

alternatives --config php

php -version

Now PHP 7.2 is installed and activated. After restarting Apache WordPress will run on a newer PHP version.

Let the world know

Create OAuth 2.0 scope in Keycloak

OAuth uses scopes to restrict access to resources. “Scope is a mechanism in OAuth 2.0 to limit an application’s access to a user’s account. An application can request one or more scopes, this information is then presented to the user in the consent screen, and the access token issued to the application will be limited to the scopes granted.” [link]

A service is assigned to a scope, therefore without being allowed to access a scope, you cannot access the resource. You can create scopes independently from the resource, that is: first create a scope, then assign the scope to a service you want to access. In reality, you should first create the service and then assign a scope to it.

After knowing the scope, log in to Keycloak and create a client scope. Later this scope will be assigned to a client. If the client authenticates then in Keycloak, the scope is assigned to it and the client can access the service.

Click on create

In the following form, enter the data for the OAuth scope:

  • Name: Scope for service. Here I used ZDEMO_CDS_SALESORDERITEM_CDS_0001, a scope for a CDS Service. Don’t worry, it’s just an example, Gateway does not work with OpenId Connect.
  • Description: SAP Gateway OData service
  • Protocol: openid-connect
  • Display on Consent Screen: off

Save

The OAuth scope is created. It can now be assigned to a client.

Note

When you change the scope of the service, you need to update the scope information here too.

Let the world know

Add OAuth 2.0 client in Keycloak

In this article I will show how to add an OAuth 2.0 client in Keycloak.

Log in to Keycloak and select a realm. In a new (empty) installation of Keycloak, the realm Master is selected by default. The realm name is important, as it is part of the URL used later for OAuth authentication.

To create a new OAuth 2.0 client, click on create.

Insert your information for the client. Make sure the openid-connect is selected as client protocol.

Client ID: oidclient
Client Protocol: openid-connect

Click on save and the client configuration screen is shown. Here you can add and alter additional information.

Important

  • Access Type: confidential. This will require the OAuth 2.0 client to send a client secret to authenticate itself.
  • Service Accounts Enabled: On

  • Valid Redirect URIs: set to a valid one, like /

All other parameters should work as given.

Switch to tab Credentials

Here you can see the OAuth 2.0 client secret. As in the settings tab the access type was set to confidential, the client must send its client id and secret to Keycloak to authenticate itself. The client id is the name of the client (oidclient), and here you can see the secret: 7bc40…

You can now add the OAuth 2.0 scopes to the client.

Let the world know

Presentation SITMUC 2018

Event information

  • Location: SITMUC 2018, Einstein Kultur
  • Date: 13.10.2018
  • Site: Event website
  • Title: Creating apps with UI5
  • Presentation: PDF

Additional information

  • Make sure to select a language that supports the team, not just you.
  • App development is not just coding: that’s why the presentation is about creating apps. It’s a team effort.
  • Demo apps are mostly for myself and to make my life easier
  • Cognitive Leave Request was developed by BridgingIT in partnership with Microsoft. More information about the project: Tobias und Martin entwickeln. (Video in German)
  • Testing is important. Several tools from and for UI5 are available that can be used or other tools. Just use them if you can.
Let the world know

Presentation 3. HANA Tech Nights

Event information

  • Location: MAFINEX-Technologiezentrum, Mannheim
  • Date: 01.10.2019
  • Site: SAP Community Wiki, Meetup.com
  • Title: ABAP is DEAD – long live CAPM
  • Presentation: PDF

Additional information

  • EOL for NetWeaver 31.12.2025 is for the on premise version, as listed by SAP PAM.
  • S/4HANA is running on NetWeaver ABAP, therefore, ABAP will stay the base technology for SAP.
  • CAP and RAP helps you to keep the core clean. To make this possible for all SAP customers, the options you have a independent of the technology skills the developers have: Java, JavaScript, ABAP.
  • Fiori Elements or “pure” Fiori app development: this is not either nor situation, both are valid and can complement each other. Important is to have the backend services made ready for Fiori; as SAP does since the beginning for their official Fiori Apps.
  • Fruit Checker App is not a productive app. It is a showcase with the intention to make people think about the possibilities: what can you do today, value that combination of services can bring, etc.
  • Possibilities CAP may offer depend solely on SAP. It’s their product and its features and roadmap are controlled 100% by SAP.
Let the world know

Import OVA as Proxmox VM

OVA is a virtual appliance, ready to run on a hypervisor. With an OVA file, you can import the image into VirtualBox, VMWare, etc and all needed information is loaded from the file and you can start the VM. This works as long as your hypervisor is capable of reading an OVA file. Proxmox does not understand OVA, and you cannot use the image out of the box. Reading the provided VM definition is not possible. As an OVA file contains the VM disk, you can add the disk to a VM.

First, create a new virtual machine definition in Proxmox. You are going to import the disk image from the ova file, not the virtual machine definition. Therefore, you must first create a VM, this creates the necessary information in Proxmox, and then you are adding a disk to this VM.

The overall steps to add OVA image to Proxmox are :

  1. Create VM
  2. Delete associated disk
  3. Import OVA
  4. Assign OVA to VM

Create a new VM definition

In Proxmox, add a new VM. Note the VM ID. You need this later when importing the OVA disk.

Go through the wizard to create a normal new VM.

It seems that you have to add a disk. The disk will be deleted later, the configuration entered here is not important.

I’ll use a CPU with 2 cores.

I am using the VM for SAP HXE, therefore I am going to use a little bit more RAM: 24 GB RAM in total.

After going through the wizard, the VM definition is ready and you can let Proxmox create the VM.

The new VM will appear in the list of available VMs in your server. Note the ID: 101 and the available storage locations.

Delete associated disk

Open the VM configuration and got to Hardware. The disk you added in the wizard is listed. This disk must be removed.

Remove the disk

  1. Detach from VM

Select the disk and click on Detach. The disk state will change to unused.

  1. Remove disk from VM

After the disk is detached, remove it from the VM. This will delete the disk file.

Import OVA

The next step is to import the OVA disk and assign it to the VM. As Proxmox uses LVM for managing its storage, a provided tool must be used to import the disk to LVM and assign it to the VM. Copy ova file to Proxmox server. Unzip OVA file. OVA is a zip file, you can simply unzip it to see its content. It contains the VM definition (ovf) and the vm disk (vmdk).

tar -xzvf hxexsa.ova

To import the image, you need to specify the VM and location where the disk is imported to. This information is available in Proxmox. You can see a list when looking at the server at the left menu. I am going to use local-lvm and VM HXE with id 101.

qm importdisk 101 hxexsa-disk1.vmdk local-lvm -format qcow2

This starts the import process. Basically, the vmdk file is copied to the storage local-lvm. After the import finishes, the disk is listed in Proxmox.

Assign OVA to VM

The disk is now available in Proxmox and added to the VM, but not usable. The disk must be assigned to the VM. To do so, open the VM definition and go to hardware.

Click on Edit.

Here you can specify how the disk is accessed by the VM. SCSI should work. If you get errors, try IDE, etc. As result, the disk is added to VM and can be used.

Note: SAP HANA Express Edition

To get the disk shipped with SAP HXE working, I had to use SATA, not SCSI.

Add the disk as SATA.

Make sure the boot order is set to SATA.

Starting the server should now work and you should see the configuration dialog.

Let the world know

Increase EC2 (root) file system size

Some years ago I create a new instance in EC2 with the minimal configuration needed. The disk size of the root device and partition is set to 8 GB. Today I am reaching the limit of the disk size and need more space. Having the server in the cloud allows me to “simply” increase the size without having to buy a new HDD.

To increase the size of an EBS volume, you need to execute three tasks:

  1. Take snapshot
  2. Resize volume
  3. Resize file system

The commands to resize partition and file system are (gp2, ext4, t2):

sudo growpart /dev/xvda 1
sudo resize2fs /dev/xvda1

Take snapshot

Before starting, create a snapshot of the volume. See my blog on how to do this.

Resize volume

AWS documentation

You can use the EC2 console or CLI to extend a volume. I’ll use EC2 console. The volume used as root device for my EC2 instance is based on Elastic Block Store (EBS) and type gp2. This step is very easy to do, as you inform AWS that you need more storage and you get more storage assigned. You won’t be able to make use of that new storage as long as the file system isn’t resized.

Go to EBS > Volumes

A list of volumes is shown. Find the correct one using the volume ID. The root volume of my instance has 8GB size and type gp2.

To modify the volume, select the volume and then click on Actions > Modify Volume

The current configuration of the volume is shown. Last chance to verify you are changing the right volume.

I’ll only modify the size of the volume. From 8GB to 20 GB.

Confirm the change. Click on Yes.

In case AWS was able to assign more storage to your volume, a confirmation message is shown.

The size of the volume is now shown as 20 GB in the volume table.

Resize file system

AWS documentation

Assigning more storage to the volume is one step. To make use of the new disk space, the partition and filesystem must be resized. To see the available partition:

sudo file -s /dev/xvd*

Resize partition

The size of the volume is adjusted. The partition on the disk must be resized to make use of that space. To see the size of the disk and partition:

lsblk

The available space is 20G in total, with the partition xvda1 taking 8G only. Increase size of partition

sudo growpart /dev/xvda 1

The check if the partition was resized, run lsblk again. The partition xvda1 should now be 20G large.

lsblk

Resize file system

Resizing the EBS volume and partition is not resizing the file system. The file system still thinks it only has 8GB available.

df -h

To change size, the file system must be resized. My root file system is using EXT4 (see output above), therefore I can use resize2fs to adjust it.

sudo resize2fs /dev/xvda1

After resize2fs finishes, the file system can now use the new 20G of the EBS volume.

df -h

Let the world know