Security with KeyCloak and Google Services on Android

The KeyCloak project is a phenomenal resource for authentication and authorization services for almost any application. The default use case for it involves using OAuth redirects to send a client to a web page hosted by KeyCloak or a trusted Identity Provider, perform a log in, and the exchange tokens on the client application. This prevents potentially untrusted clients from stealing logins from users while also allowing trustworthy applications to log in using a third party. This is how websites are able to use social logins from Google, Facebook, Github, etc. However on Android the operating system provides many ways to manage log ins locally via an account picker. Google goes one step further and can provide tokens via its client sdk.

Because Google will provide a application with a token directly, we can bypass the website redirect skip on Android with Keycloak by using “External to Internal Token Exchange“. The Keycloak documentation will walk you through setting up the IdP, but you have to make sure that you configure the Google IdP as a “OpenID Connect v1.0” provider and not as a “Google” provider. Fortunately you can use Google’s well-known OpenID configuration to prepopulate most of the fields. One thing I had to change was flipping “Disable User Info” to “ON”. In order to fetch the user info, Google needs an bearer token that Keycloak does not provide.

I’ve made a simple Android application which exchanges a Google token for a Keycloak token here. The source code is on my GitHub and a demo is on my YouTube channel.

AeroGear Unified Push and OpenShift Origin

Introduction

For people who are making mobile applications, managing the various server components and technologies is a challenge.
This post will demonstrate how to use OpenShift Origin to host an instance of Aerogear Unified Push Server and then start development on an Android application on your development machine.
AeroGear Unified Push Server is a project that provides a single service to manage multiple push networks for your mobile applications. OpenShift Origin is a container management platform build on Kubernetes and Docker technologies. Both are Open Source and sponsored by RedHat.

Getting and Starting OpenShift Origin

Prerequisites

Before you can use Origin you need to have Docker installed on your computer as well as configure its to use OpenShift’s internal Docker registry. You can do this by passing the following parameter to Docker when the service starts --insecure-registry 172.30.0.0/16. System specific details can be found here.

You will also need the tool oc. It can be found on the Origin’s GitHub releases page.

Launching OpenShift Origin

oc cluster up.

Yup that is all you need. Now you can browse to https://127.0.0.1:8443/console and login as developer:developer.

Deploying AeroGear UPS

We will use the Unified Push Server image found on Docker Hub. Reviewing that page we see that it needs two MySQL instances named “unifiedpush” and “keycloak”. We can create those in Origin, deploy UnifiedPush, and then add a route for our Android emulator.

Deploying MySQL containers

oc new-app mysql MYSQL_USER=unifiedpush MYSQL_PASSWORD=unifiedpush MYSQL_DATABASE=keycloak --name=keycloak

oc new-app mysql MYSQL_USER=unifiedpush MYSQL_PASSWORD=unifiedpush MYSQL_DATABASE=unifiedpush --name=unifiedpush

You can watch both systems come online in your console, or view their status with oc status.

Deploying AeroGear UnifiedPush

oc new-app aerogear/unifiedpush-wildfly \
 UNIFIEDPUSH_PORT_3306_TCP_ADDR=unifiedpush \
 UNIFIEDPUSH_PORT_3306_TCP_PORT=3306 \
 UNIFIEDPUSH_ENV_MYSQL_DATABASE=unifiedpush \
 KEYCLOAK_PORT_3306_TCP_ADDR=keycloak \
 KEYCLOAK_PORT_3306_TCP_PORT=3306 \
 KEYCLOAK_ENV_MYSQL_DATABASE=keycloak \
 UNIFIEDPUSH_ENV_MYSQL_USER=unifiedpush \
 UNIFIEDPUSH_ENV_MYSQL_PASSWORD=unifiedpush \
 KEYCLOAK_ENV_MYSQL_USER=unifiedpush \
 KEYCLOAK_ENV_MYSQL_PASSWORD=unifiedpush \
 --name=unifiedpush-wildfly

This command will deploy UnifiedPush and connect it to your MySQL containers. If you are work with Docker then the environment variables we use should be familiar; that is because this is a plain Docker container.

Adding Routes to the UnifiedPush application

By default OpenShift applications are not routable. This means that we can not point a web browser to UnifiedPush to configure it nor can an Android device connect to it to receive push messages. We will add two routes to enable both of these behaviors.

oc expose service unifiedpush-wildfly --hostname=ups.127.0.0.1.nip.io --port=8080-tcp --name=ups-local-unsecured
oc expose service unifiedpush-wildfly --hostname=ups.10.0.2.2.nip.io --port=8080-tcp --name=ups-android-unsecured

The first route exposes UPS on the local machine’s IP address 127.0.0.1, and the second exposes on 10.0.2.2 which is the hardcoded IP address for the host of an Android emulator. These hostnames use nip.io to fake the DNS lookup.

Fixing Keycloak Linking

UPS uses an embedded Keycloak server to handle its authentication. Right now there is an issue when the UPS pod starts up it can’t route to Keycloak using the public route. To work around this you will need to use the OpenShift web console to navigate to the unifiedpush-wildfly pod and execute “wget http://localhost:8080/ag-push/index.html” in the terminal after the application loads.

Configuring UnifiedPush

You should be able to navigate to http://ups.127.0.0.1.nip.io/ag-push now and set up UnifiedPush. The full instructions for configuring this can be found on aerogear.org.

Configuring you Android Push Application

You can follow the HelloPush tutorial here. The only change is you will use “http://ups.10.0.2.2.nip.io/ag-psuh” as your push URL.

Integrating Stack Exchange and JIRA

Introduction

We are working to get the Red Hat Mobile Application Platform (RHMAP for brevity) Open-Sourced as FeedHenry and have discussed the usual array of community support options : mailing-lists, IRC, GitHub, JIRA, etc. However, the community is already using Stack Overflow to ask questions and get help from one another.

This leads to a question though : how do we integrate Stack Overflow monitoring with our current workflows? Enter so-monitor, a simple node.js application to watch Stack Overflow for questions and track their status in a JIRA. The project creates a ticket when a question is asked using a tag we monitor and then will close the JIRA ticket when the question is marked as answered.

Setup of Development Environment

I decided to write the monitor as a Node.js application, and that I would use Visual Studio Code as my IDE. Being a Java developer I am used to many tooling features: intellisense, robust debugging, etc. Also being a Java developer I had heard that most of these things were just not as mature in the Node.js ecosystem. While I feel this is still true, VS Code and [Definitely Typed|http://definitelytyped.org/] have closed the gap significantly. If you are interested in learning more about this setup I suggest following MS’s blog post. It was very helpful to me.

Consuming the Stack Exchange API

The Stack Exchange API is pretty standard as far as RESTful APIs go. There is a public API that with a limited quota expands more once you get an API key. The biggest difficulty I had was with their filters concept. Basically in Stack Exchange sites you can create a filter for your API calls that lives on their servers and then reference it with a stable, public ID.

I used Moveo’s Stack Exchange API wrapper to access the API and it worked rather well.

JIRA’s black magic

For as simple as Stack Overflow was, JIRA was not. However, JIRA is 100% scriptable and you can configure it to respond to nearly any requirement you may have. Putting a question into JIRA was basically four steps

  • Create the ticket
  • Formatting the question as a issue
  • Tagging my team
  • Closing the issue when the question was answered.

To wrap the JIRA REST API I used steve’s node jira library.

The trickiest part of the process was keeping the issue and the question states in sync. I used a custom field to track the question id returned by the Stack Exchange APIs, but managing the state hit an unexpected snag.

JIRA uses a transitions metaphor for changing the state of a ticket. This means there isn’t a “close issue” API call, but instead you have to upload a “transition” object to the issue endpoint that defines which transition you wish the issue to have taken. This means that you have to either a) check the state of the JIRA issue, lookup a transition, and execute that one or b) create a “Any State” -> “Close” transition in JIRA and hard code that. I chose “b”. For more information I encourage you to read JIRA’s API docs. They are really good and it is a very different pattern than Stack Exchange uses.

Conclusion

While the Stack Exchange and JIRA APIs were the main meat of the monitor project, there were many small “learnings” I had above and beyond that. VS Code and typings is a wonderful JavaScript experience. Using Q promises and wrapping node calls in Promises with simple one liners made my main code much easier to follow. Node.js and the JavaScript ecosystem has come phenomenally far in four years and it is finally as productive as more “Enterprisey” technologies like .Net and Java.

JRebel and WildFly Swarm in NetBeans

I’m not a great company man; I use NetBeans instead of RedHat’s JBDS. However, I am at least a GOOD company man because I am using WildFly Swarm instead of Sprint Boot. I also use JRebel because I don’t like wasting my time waiting on my projects to build. The combination of the three, however, gave me quite a headache today.

First, NetBeans is the only IDE that gets Maven correct. A Maven project is almost always a valid NetBeans project without any extra configuration. On top of this NetBeans makes it very easy to configure custom Maven goals and map them to your standard IDE actions. Second, WildFly Swarm is an awesome project that is basically Spring Boot but with real, rightsized Java EE. It also has awesome Maven support and I can’t say enough good things about how it. Finally, JRebel should need no introduction. It hot deploys Java code to just about anything and makes the write -> run -> debug cycle as fast as it can be.

My problems began when I imported my Swarm project into NetBeans. NetBeans recognized the fact the project was a war file and offered to deploy it to my installed WildFly server instead of running the Swarm plugin’s run goal. I created a custom NetBeans action to run the Swarm goal. This worked perfectly and all that was missing was JRebel.

JRebel did not want to play nice with the Swarm run goal. I’m not sure why, but eventually I decided to give running the project using the maven exec goal and passing in the Swarm Main class. This worked, but NetBeans wasn’t loading JRebel right out of the box. Finally, I copied over the exec arguments from a working Jar project into my custom run goal and JRebel successfully started (with errors that don’t seem to matter). Hot deploy worked!

If you are wondering here is my configuration :

Execute Goals : process-classes org.codehaus.mojo:exec-maven-plugin:1.2.1:exec
Set Properties : exec.args=-Dexec.args=-Drebel.env.ide.plugin.version=6.5.1 -Drebel.env.ide.version=8.2 -Drebel.env.ide.product=netbeans -Drebel.env.ide=netbeans -Drebel.base=/home/summers/.jrebel -Drebel.notification.url=http://localhost:17434 -agentpath:/home/summers/netbeans-8.2/java2/griffin/lib/libjrebel64.so -classpath %classpath org.wildfly.swarm.Swarm
exec.executable=java

So with that all working my Project Properties looks like this :

screenshot-from-2016-10-14-23-06-42