Over the summer of 2020 to 2021, I was given the opportunity to work with Catalyst’s GIS team in Christchurch. In my introductory email, it was mentioned that I was going to be working with GIS software. I was not sure exactly what GIS was except for the fact that it had something to do with maps and geographical data, but that did not scare me as I was excited to learn something new. Going into this internship I had only finished my third year of university and had one other internship where I worked as a full-stack developer. Over this summer I learnt so much and was very grateful to have this experience with Catalyst.
Integrating single sign-on into GIS via Keycloak
I was very fortunate to work with another intern this summer. Our project was to integrate Keycloak single sign-on into GeoNode, GeoServer, and MapStore. Even though it felt like a massive task at the beginning, our team leader did a great job in breaking down the big problem into multiple small and more approachable ones.
Learning about dockers, containers, and image
My first step in understanding Keycloak was to learn how our dev environment ran all the different GIS software. To understand that we had a quick tutorial on how dockers, containers and images interact. In the tutorial, I learnt that a container requires an image to build and how a docker can activate that container and run extra terminal functions within it. Once the basic knowledge was understood I had the opportunity to alter a docker-compose file that had multiple containers in it. Each container was responsible for GIS software, such as GeoServer; and one container was for the database. My job was to make a container for Keycloak that connected to the database. At the start, it was very confusing but after reading the documentation and the other containers within the docker-compose it became clear how I should create the container for Keycloak.
Once Keycloak was running, the next step was to follow a tutorial on how to set up Keycloak sign-on with GeoServer on the GeoServer documentation. The tutorial was straight forward, and I was able to log into GeoServer via Keycloak. Now it was time to start on the project and dig into more challenging tickets.
Setting up Keycloak with GeoNode
-> GeoNode sign-in via Keycloak
The first step to sign in to GeoNode via Keycloak was to enable Keycloak as an Auth provider for GeoNode. That involved me setting up a GeoNode Keycloak client that would redirect a user when signing in through Keycloak. If the user did not exist within GeoNode but would within Keycloak then a new user would automatically be created for GeoNode. For this process, the big part was to select the right Keycloak extension. It took three attempts to find the Keycloak extension that worked with GeoNode. The extension that I selected was from Django-allauth that was already incorporated within GeoNode. Which meant that it already had most of the required add-ons to the settings file. The tutorial that I found for setting up Django-allauth Keycloak extension had a URL in it that did not work but once I figured out what was wrong and fixed the URI signing in via Keycloak was just as easy as with GeoServer.
-> Synchronizing Keycloak roles with GeoNode
This part of my project was probably the most challenging. For me to synchronize roles from the Keycloak GeoNode client into GeoNode I had to create a Django application that would do that for me. I had no idea what a Django app was and did not have a clue on how GeoNode worked. After reading through multiple tutorials on how to set up a Django application and reading through the code base of GeoNode, I found some examples of Django apps that were already present within GeoNode. The tutorials were very helpful but, in the end, I ended up using the Django documentation to guide my way through making a Django Keycloak role application as well as help from my GIS teammates. I learnt from this experience - that sometimes reading documentation or a tutorial can take time and effort but will always have a beneficial outcome instead of just trialling ideas out.
-> Enabling SSO implementation into GeoNode
Setting up a silent SSO check for GeoNode using Keycloak was probably the simplest task that seemed complex at the start. To implement SSO I had to import the Keycloak-JS extension that was used to create a Keycloak instance. That instance can be could use to set up a silent SSO check and retrieved the Keycloak token. From this task I learnt to look at the problem more positively and not go straight into negative thoughts and trapping myself thinking it’s too hard to do if something goes wrong.
-> Packaging the Django application and adding it to GeoNode-contrib repository
It is always the best feeling when finishing up with a project that makes you proud and which succeeds. When creating the Django application, I had to add the SSO functionality to it which caused some issue at the start but worked at the end as I had to modify the settings file for GeoNode. I wrote up a detailed README that contained the instructions to set up the Keycloak role syncing as well as the SSO integration. For the application to be complete I tested it and cleaned up the code so that it followed the GeoNode styling structure. Nevertheless, I was very proud to finally create a stand-alone Django application. It was very tedious to test it as I had to go through the process of downloading GeoNode from scratch, but it was all worth it. Towards the end of my internship, my pull request into geonode-contribs repository was accepted and now my name is displayed as one of the contributors.
Implementing SSO and Bearer Authentication on WMS Layers within MapStore using GeoServer
Working with MapStore was a challenge. A challenge was MapStore taking a very long time to load the front page. Since MapStore was a much larger project than GeoNode any changes that I would implement would take a long time to load in. After working with GeoNode I was quite comfortable with the size of MapStore. Yes, it was way larger, but I felt like I knew what I was doing. My confidence was rising and so I was not intimidated by the size of MapStore.
My first step was to integrate silent SSO check just like with GeoNode and set the token. Thus, allowing me to access the Keycloak token from anywhere in the project. The process was very similar to the one in GeoNode. For me to set the bearer authentication header of WMS layers I created a helper file that handled creating a request and setting the header of a given tile. I used this helper file in both OpenLayers and Leaflet layer, which are just different type of map within MapStore that both contain WMS layers.
Finally, to test my bearer authentication header I created WMS layers within GeoServer. And to each of the layers, I created a GeoFence rule that allowed only authenticated users to view some of them. So, when going onto MapStore and retrieving those WMS layers and adding them to the map. Each tile from the layers contained a bearer authentication header. Since the GeoFence rules were created only authenticated users could view all the layers.
Creating Custom Keycloak Login Theme
I really enjoyed creating a custom Login GIS Catalyst theme for Keycloak. It was very simple and just a fun exercise. This theme was added to the Keycloak container so that it would be included within Keycloak website theme settings.
Even though I have had experience with Git from university and my previous internship, it never prepares you to fully work and use Git every day. I learnt a few new tricks such as squashing git commits, forking and changing repositories. I very much appreciate all the work I do with Git as the more I understand how Git works the more confident I become. I do also appreciate the extra hand from my team leader when I needed it so that I do not override the history at any point.
Overall, this opportunity working on GIS team was wonderful. I learnt so much and by the end, I felt like I had a grip on the GIS software. I appreciated all the learning opportunities that Catalyst provided and all the learning opportunities that I received from my team leader. I felt very welcomed from the beginning of this journey till the very end and am looking forward to what the future might bring.