# request.getUserPrincipal() Typecasting



## Matti (17. Feb 2016)

Hallo Leute,

ich versuche gerade die Nutzer-Authentisierung einer Webapp, welche auf einem Apache Tomcat Server läuft, über einen entfernten Server zu realisieren. Dazu verwende ich als Lösung Keycloak und als Protokoll SAML. Dies funktioniert auch soweit alles problemlos. Ein Tomcat Adapter von Keycloak leitet User auf den entfernten Server um und wieder zurück zur Webapp, sobald diese sich erfolgreich angemeldet haben. Die notwendigen "Logindaten" werden als XML nach der SAML Spezifikation via POST-Binding mit übertragen.

Soweit zum notwendigen Sachverhalt, nun zu meinem eigentlichen Java-Problem: Der User hat zwar Zugriff auf die Webapp, die Webapp selbst muss nun jedoch noch wissen um welchen User es sich handelt. Der Keycloak Adapter liest die dafür notwendigen Informationen aus der SAML XML und erstellt daraus ein Objekt der Klasse SamlPrincipal. Das Objekt ist danach über die Methode getUserPrincipal() von der Klasse HttpServletRequest abrufbar.

Das entsprechende Objekt lässt sich als Principal problemlos abfragen:

```
Principal principal = request.getUserPrincipal()
```

Leider bietet das normale Principal Interface nicht die notwendigen Methoden um auf die, für meine Zwecke wichtigen Attribute zuzugreifen.

Laut der offiziellen Dokumentation soll man eine Typumwandlung nach SamlPrincipal durchführen.


> After a successful SAML login, your application code may want to obtain attribute
> values passed with the SAML assertion. HttpServletRequest.getUserPrincipal returns
> a Principal object that you can typecast into a Keycloak specific class called
> org.keycloak.adapters.saml.SamlPrincipal. This object allows you to look at the raw
> assertion and also has convenience functions to look up attribute values.


Und daran scheiterte ich im Moment. Die Dokumentation gibt an dieser Stelle leider bis auf diesen Absatz keine weiteren Informationen her.

Wenn ich eine Typumwandlung folgendermaßen versuche..

```
SamlPrincipal samlPrincipal = (SamlPrincipal) request.getUserPrincipal()
```
..erhalte ich leider folgende Exception:

```
java.lang.ClassCastException: org.keycloak.adapters.saml.SamlPrincipal cannot be cast to org.keycloak.adapters.saml.SamlPrincipal
```

Die notwendigen .jar Dateien, welche die Keycloak Klassen bereitstellen habe ich im "lib" Verzeichnis des Tomcat Servers und im WebContent\WEB-INF\lib meiner Webapp hinterlegt.

Da ich mich leider erst seit kurzen mit Java beschäftige und eigentlich bei anderen Programmiersprachen beheimatet bin kann es sein, dass ich hier einfach einen offensichtlichen Fehler mache, ich finde ihn jedoch leider nicht.

Für jede Art von Anregungen oder Hilfestellungen möchte ich mich bereits im voraus bedanken.

Zur Übersicht die komplette Servlet Klasse meiner Beispielwebapp:

```
package hallo.welt.pack;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.keycloak.adapters.saml.SamlPrincipal;

@WebServlet("/HalloWeltServlet")
public class HalloWeltServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;

  public HalloWeltServlet() {
  // TODO Auto-generated constructor stub
  }

   protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     SamlPrincipal samlprincipal = (SamlPrincipal) request.getUserPrincipal();
     response.getWriter().append(samlprincipal.getName());
   }

   protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
     doGet(request, response);
   }
}
```


----------



## Matti (18. Feb 2016)

Hallo Leute,

mittlerweile konnte ich das Problem lösen. Dadurch das die entsprechende Klasse SamlPrincipal sowohl in der Webapp als auch im Tomcat eingebunden war gab es die TypeCastException.

Dies liegt wohl daran, dass der Tomcat die Klassen doppelt lädt, was grundsätzlich kein Problem ist, jedoch zu unerwarteten Fehlern während der Laufzeit führen kann. Es sollte also vermieden werden die selben .jar Files sowohl im Tomcat als auch in der Webapp vorzuhalten. Wenn möglich alles nötige mit in die Webapp packen und darauf verzichten den Tomcat mit weiteren .jar Files zu erweitern.

In meinem Fall war dies jedoch nicht möglich da die .jar Files zwingend Tomcat weit vorhanden sein mussten, da der SAML Adapter diese benötigt. Dadurch musste ich darauf achten während des Build-Vorgangs die genutzten .jar Files nicht mit ins .war File zu packen, nach dem "deployen" werden dann die globalen Klassen vom Tomcat genutzt.


----------

