Nginx Basic Authentication against Keycloak

Due to some updates in our infrastructure, I was looking for a means to authenticate nginx against a keycloak backend. I found some solutions, using Lua or commercial plugins.

I thought, that this might be doable with “pure nginx means” only, and I think, to some degree, I succeeded.

Lets just skip the explanation, and show some code, where we want to protect location “/” by basic auth forwarded to keycloak

# nginx.conf
location / {
    root /var/html;
    satisfy any;
    auth_request /auth_keycloak;
}

location /auth_keycloak {
		proxy_pass https://keycloak.com/realms    
                           /myRealm/protocol/openid-connect
                           /token;
		proxy_method POST;
		proxy_pass_header Authorization;	
		proxy_set_header Content-Type 
                           "application/x-www-form-urlencoded";
		proxy_set_body "client_id=clientId&
                           client_secret=clientSecret&
                           grant_type=password";
}

We delegate the authentication in “/” to the location “/auth_keycloak” and as mentioned in the documentation: If the subrequest returns a 2xx response code, the access is allowed. If it returns 401 or 403, the access is denied with the corresponding error code.

So we need to fix a client in keycloak, that will answer correctly to the given request. Formally the passed request is a “direct access grant” request. But there is a slight change. No username and password are passed, instead these are passed via proxy_pass_header Authorization.

How can this be achieved? The secret is in the supported flows. I assume that you are familiar with keycloak basics, thus I only show the relevant parts:

I override the Direct Grant Flow with a http challenge flow, which removes the requirement for the username and password passing as form value, and reads the Authorization header.

Also I deactive the other non-required capabilities!

Now, at least for me, with this reduced solution, I managed to do Nginx Basic Authentication backed by a keycloak service.

Java 11, JAXB and osgi

Starting with Java 11, several packages have been “hard-removed” from the JRE itself (For Java 9 and 10 they were simply re-activateable by using a parameter) – one of those being the javax.xml.bind package, which used to provide (together with others) the JAXB implementation.

Updating our product to become Java 11 compatible, proved to be a major task, but finally it seems I managed to do it. So here are the effective steps resp. pitfalls that one will run into:

  • The JAXB packages are not available anymore – how to find them?
  • My bundles have to run on both Java 8 and Java >8 – how to achieve this?
  • Tycho is reluctant to build this, i miss packages
  • The concrete JAXB implementation seems not to be found, because OSGi – how to fix this?

The missing JAXB packages

In order to find replacements for the now missing bundles, we have to find the right set applicable for OSGi. I managed to identify the following maven bundles:

com.sun.activation:javax.activation:1.2.0
javax.xml.bind:jaxb-api:2.4.0-b180830.0359
com.sun.xml.bind:jaxb-osgi:2.4.0-b180830.04

You can use a maven tool like p2-maven-plugin to create a p2 repository with these requirements for later inclusion. Have a look at our own dependency repo for an example.

Run ’em on both Java 8 and Java >8

OSGi R7 introduced the support for multi-release jars. These are bundles, where, dependent on the java version you use, different manifest information is to be applied.

The following picture shows an example where for Java >=9 the Import-Package of the original manifest is replaced to import com.sun.xml.bind.v2. The resp. Import-Package will not be used for Java <=8. In order to activate this, the main manifest has to be extended with Multi-Release: true

The MANIFEST.MF in versions/9/OSGI-INF extends the original manifest for Java > 8

Tycho: com.sun.source where are you?

Caveat Building with Java 11 does not yet work – all builds are done using Java 8

While com.sun.xml.bind.jaxb-osgi 2.4.0.b180830_0438 works fine within the IDE, when building your product trouble is on the horizon.

com.sun.xml.bind.jaxb-osgi 2.4.0.b180830_0438 formally requires the packages com.sun.source.tree and com.sun.source.util which are not provided to OSGi as they are expected to be made available by the JRE. At runtime, org.eclipse.osgi_3.13.100.v20180827-1536 cares for this but at build and package time it is not satisfied.

This can be fixed by providing a special fragment with Fragment-Host: system.bundle; extension:=framework which may then be included to your feature.

See https://github.com/eclipse-ee4j/jaxb-api/issues/92 for the detailed problem description and http://blog.meschberger.ch/2008/10/osgi-bundles-require-classes-from.html for infos on its solution.

My own solution to this problem is shown in the following image:

Providing com.sun.source.tree and com.sun.source.util to the OSGi environment

Implementation of JAXB-API has not been found

At runtime javax.xml.bind.ContextFinder.newInstance is used to create a JAXB object that is actually performing the work. ContextFinder is part of the java-api bundle, and the actual JAXB implementation it tries to find is provided by com.sun.xml.bind.jaxb-osgi.

Now in OSGi we face the problem of the classloaders per bundle being separate. In https://github.com/eclipse-ee4j/jaxb-api/issues/78 the problem of jaxb-api not able to find the real jaxb api implementation is documented.

The exception that identifies this problem looks like this

[java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory]


Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:269) ~[na:na]
… 93 common frames omitted

Caused by: java.lang.ClassNotFoundException: com.sun.xml.bind.v2.ContextFactory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583) ~[na:na]
… 97 common frames omitted

As far as I know, there are currently 2 solutions to this problem:

1. Add Import-Package for com.sun.xml.bind.v2 for each bundle and adapt JAXBContext.newInstance to use a bundle local classloader

2. Provide a fragment bundle for java-api that adds the dependency to the jaxb-api implementation package.

After trying the first approach, I though that I have to modify to much of the existing code – hence I moved to the second approach.

The first image in this blog post actually shows this fragment.

The pain of configuring JSP in Jetty OSGi

As part of a recent project I want to run mitreid connect server embedded within the Elexis-Server Neon.3 based Jetty instance (that is version 9.3.9.v20160517).

Despite the excellent Jetty documentation on this version, I faced major trouble on getting to run this right.

My status / approach was this: First of, I want to run the plain war file provided within a WebAppContext of the Jetty container. This did not prove to be much of a problem, a simple Activator like this achieved this:

@Override
public void start(BundleContext context) throws Exception {
	WebAppContext webapp = new WebAppContext();
	Dictionary props = new Hashtable();
	props.put("war", "lib/openid-connect-server-webapp.war");
	props.put("contextPath", "/openid");
	props.put("managedServerName", "defaultJettyServer");
	context.registerService(ContextHandler.class.getName(), webapp, props);
}

But now the real trouble started – J S P !

The trouble can be broken down into three steps

  1. Configuring the JSP implementation
  2. Setting up the JSTL (Standard Tag Library)
  3. Configuring the WebAppContext to use all of this

Configuring JSP (Apache Jasper implementation)

This is pretty much straightforward, as documented in Using JSPs.
Just one thing is a little hidden – you additionally need apache aries.

Here goes a (hopefully) complete list

      id="javax.servlet.jsp.jstl"
      id="org.apache.aries.spifly.dynamic.bundle"
      id="org.apache.aries.util"
      id="org.eclipse.core.commands"
      id="org.eclipse.core.expressions"
      id="org.eclipse.core.filesystem"
      id="org.eclipse.core.resources"
      id="org.eclipse.jdt.core"
      id="org.eclipse.jetty.apache-jsp"
      id="org.eclipse.jetty.osgi.boot.jsp"
      id="org.eclipse.text"
      id="org.glassfish.web.javax.servlet.jsp.jstl"
      id="org.mortbay.jasper.apache-el"
      id="org.mortbay.jasper.apache-jsp"
      id="org.objectweb.asm"
      id="org.objectweb.asm.commons"
      id="org.objectweb.asm.tree"

Setting up the JSTL (Glassfish approach)

This is where I started to have problems. Documentation says to include org.glassfish.web:javax.servlet.jsp.jstl-1.2.2.jar which did not work out using Java 8. Eclipse complained with

I could track this down and reverted to org.glassfish.web:javax.servlet.jsp.jstl-1.5.0-b03.jar to solve this.

Configuring the WebAppContext to use all of this

At least the dependencies seemed to be satifisied by now – but did it start? No – but
a new Exception occured


2018-01-18 15:21:13,280 WARN  o.e.jetty.servlet.ServletHandler - 
org.apache.jasper.JasperException: Unable to compile class for JSP
	at org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:600) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:363) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:396) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
...
Caused by: java.lang.NullPointerException: null
	at org.apache.jasper.JspCompilationContext.getTldResourcePath(JspCompilationContext.java:551) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]
	at org.apache.jasper.compiler.Parser.parseTaglibDirective(Parser.java:420) ~[org.mortbay.jasper.apache-jsp_8.0.33.jar:2.3]

This post left me with some
hints on what could be the problem. It breaks down to the JettyJasperInitializer#onStartup not being called and some configurations missing.

Some more searches brought me to the embedded-jetty-jsp sample project where this was initialized. (I had to use the non-jetty-annotations approach, as I also use org.eclipse.gemini.naming in the container, already providing a JNDI implementation).

I extracted the JspStarter from the mentioned project, and modified the Activator

webapp.addBean(new JspStarter(webapp.getServletContext().getContextHandler()));

and now it works – the journey continues! Hope this blog spares somebody else some trouble!

e4 RAP and trimless fullscreen windows

After starting to set up an e4 based RAP application, one of the thirst things that popped into my eyes was the Windows in Windows Problem. That is, you have your browser opening the e4 rap application and you see a window title (which effectively exists for both Window and TrimmedWindow) which does not make much of a sense. For RAP based on 3.x here is the solution. For e4 based RAP it required some investigation, so here goes the solution.

Add a TrimmedWindow or Window element, and provide the tag shellMaximized and the persistentState value styleOverride (thanks to Lars Vogel for pointing this out) where the value is determined like you would set it programmatically with


int val = SWT.NO_TRIM;
System.out.println(val);

thats just like in the following example:
fullscreenRAP

JFace Databinding with PojoProperties on Boolean

Consider the following Pojo Foo


public class Foo {
  boolean boolProp;

  public void setBoolProp(boolean boolProp){
    this.boolProp = boolProp;
  }

  public boolean isBoolProp() {
    return boolProp;
  }
}

then you might assume, that you can databind that with master-detail pattern given a SWT.Button with the following code

IObservableValue uiObs = WidgetProperties.selection().observe(button);
IObservableValue prescObs = PojoProperties.value("boolProp", Boolean.class).
    observeDetail(observable);
dbc.bindValue(uiObs, prescObs);

Well this will not work, you actually have to have a method

  public boolean getBoolProp() {
    return isBoolProp();
  }

in your Pojo to make it work.

I am not sure, why this is the case, as one tries to programm according to bean style, where you have the isX and setX for Boolean properties. I am also not sure wether this is different for newer versions of JFace (this is 3.8.0). Just find it worth mentioning, and am hoping for some comments on this 🙂

Oomph and github pull request task lists

After Eds and Eikes nice talk on Oomph at EclipseCon 2014, I decided to give it another try for our Elexis project. Turns out that its a bit tricky to come in.

One thing is that I want to configure the pull requests available in the github repo as tasks within Eclipse, and this is what I did to do so

githubPullRequests

I found out about the correct connector kind when diving into my workspaces .metadata/.mylyn directory having a look at repositories.xml.zip. This also showed me that I have to add the attribute state=open:: in order to have fully configured task lists on the open pull requests.

e4: Updating UI contributions on context switch

During the implementation of a new project, I want to harness the capabilities of the Eclipse application model when it comes to changes in the Eclipse context, or more accurate the de-/activation of context specific handlers.

What does that mean? Lets have a look at the following application model:

contextswitchmodel1 is the global definition of our testCommand, 2 and 3 are perspectives in our application where for the given command a separate handler gets activated due to the context switch from perspectiveA to perspectiveB and vice-versa. 4 is the UI contribution of the command visible to the user in the top window trim.

The resulting application looks like testAppshown on the left hand side. Where the UIContribution 4 is marked with a red arrow. Now the task of the handlers is to toggle between the perspectives and update the UI contribution to either show perspectiveA or perspectiveB.

As described in stackoverflow and the Eclipse forum I did not, at first, find an obvious approach to this (remark in Eclipse 3.x this could be implemented by using an IElementUpdater). After some more analysis I found a way to do so. The source for the following example is certainly available.

Lets fix the example by having a look at HandlerA


public class HandlerA {
    
    @Execute
    public void execute(EPartService partService,
             EModelService modelService, MApplication application) {
        MPerspective perspective = (MPerspective) modelService.find(
                "perspectiveB", application);
        partService.switchPerspective(perspective);
    }

    @Inject
    public void bla(
            @Optional @Active @Named("handler::testCommand") Object value,
            EModelService modelService, MApplication application) {
        if (value == null)
            return;
        List<MHandledItem> findElements = modelService.findElements(
                application, null, MHandledItem.class, null);
        for (MHandledItem mHandledItem : findElements) {
            mHandledItem.setLabel("perspectiveA");
            mHandledItem.setTooltip("perspectiveA now active");
        }
    }
}

The @Execute method does the simple task of toggling the perspective. The updating itself happens in lines 12-23. This method does listen to property changes of handler::testCommand which is the global command (see 1 in the above app model). Each time a context switch happens we get injected the current handler through Object value. So we may act accordingly. Here we act by using the modelService to find all contribution elements subsequently setting a new Label and Tooltip.

If more commands and handlers are in your application you should do a more intelligent search and/or filter on the value to act correct.

This approach, however, is not perfect, as you have to implement this method in both handlers in order to always be able to act upon the change. There are other feasible approaches like creating an Addon where you put the @Inject part, you would have to do this for each command separately, however.

I would prefer to be able to define a class within the MCommand element to put the respective code into which would always be notified in any change that happens related to it. So imagine that a MCommand has an option Class Uri and the respective referenced class could look like this

public class TestCommand {

    @Inject
    EModelService modelService;

    @Inject
    MApplication application;

    @Inject
    public void bla(@Optional @Active MHandler activeHandler,
            @Active MCommand command) {
        if (activeHandler == null)
            return;
        List<MHandledItem> findElements =
                modelService.findElements(
                application, null, MHandledItem.class, null);
        for (MHandledItem mHandledItem : findElements) {
            mHandledItem.setLabel("perspectiveA");
            mHandledItem.setTooltip("perspectiveA now active");
        }
    }
}

Where the injection will happen on change of the activeHandler and I also get the MCommand itself injected. This way one could also efficiently store the given UiContribution elements and limit the searches ….

What do you think? Eager to hear your opinion 🙂

Setting Java for Eclipse on OS X …

It already bothered me for some time, that one constantly seems to have Eclipse running with the wrong Java version. That is, if you’re doing heavy development you might have Java 6, 7 and 8 installed on your machine.

In order to switch the main JVM Eclipse will run with you have to follow these instructions, which involves manually changing the .ini file each time you want to change the version. This is quite cumbersome, so I decided to learn some Apple Automator.

After some insatisfying approaches to generate a service, I generated an application that works as follows:

  1. Drag an OS X Eclipse.app onto it
  2. The application browses all JDK installations in /Library/Java/JavaVirtualMachines and prompts you to select one, which it will then configure within the resp. ini file

The app is completely realized in Automator, with some perl, I had to zip it to distribute it over Dropbox. It is in a very early stage … feedback always welcome 🙂 Here goes a short demo video: