initial Commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8550c70
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+.git
+.idea/**/*.xml
+.settings
+.classpath
+target
+/.idea/compiler.xml
+/.idea/*.xml
+/.idea/modules.xml
+/.idea/vcs.xml
+/bin/
+.iml
+.project
+.classpath
+.idea
+/portal.iml
diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml
new file mode 100644
index 0000000..c506da6
--- /dev/null
+++ b/api/swagger/swagger.yaml
@@ -0,0 +1,13 @@
+swagger: "2.0"
+info:
+	version: "1.0.0"
+	title: eLogbook API
+host: localhost:3000
+basePath: /
+schemes:
+	- http
+consumes:
+	- application/json
+produces:
+	- application/json
+paths:
\ No newline at end of file
diff --git a/deploy/HowToDeploy.txt b/deploy/HowToDeploy.txt
new file mode 100644
index 0000000..4e9ec6f
--- /dev/null
+++ b/deploy/HowToDeploy.txt
@@ -0,0 +1,31 @@
+Deployment der Anwendung oK Betriebstagebuch
+________________________________________________
+22.03.2017 _fd                     first Version
+________________________________________________
+
+
+Allgemein
+_________________________________________________
+
+Datenbank einrichten
+____________________
+
+....
+
+Datenquelle auf Apache Tomcat einrichten
+________________________________________
+Im "conf"-Unterverzeichnis des Tomcat (<TOMCAT>/conf) befindet sich die Datei context.xml.
+Diese muss um den Bereich "<Resource>..." aus der Datei (/deploy/context.xml) ergänzt werden.
+Der Datenbank-Treiber (deploy/lib/postgresql-xxx.jar) muss nach ""<TOMCAT>/lib" kopiert werden.
+
+
+Backend-Installieren
+____________________
+Die Datei "betriebstagebuch.war" muss in das Verzeichnis "<TOMCAT>/webapps" kopiert werden. Sollte
+dort bereits ein Verzeichnis "betriebstagebuch" vorhanden sein, so muss dieses zuvor gelöscht werden.
+
+
+
+Frontend-Installieren
+_____________________
+....
\ No newline at end of file
diff --git a/deploy/conf/context.xml b/deploy/conf/context.xml
new file mode 100644
index 0000000..eff12ed
--- /dev/null
+++ b/deploy/conf/context.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<!-- The contents of this file will be loaded for each web application -->
+
+
+<!-- jdbc:oracle:thin:@entbwora1:1521:dboetng4  -->
+<Context>
+
+    <!-- Default set of monitored resources -->
+    <WatchedResource>WEB-INF/web.xml</WatchedResource>
+
+    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
+
+    <!--Manager pathname=""/>
+
+
+    <Parameter name="environment" override="false" value="Development"/-->
+
+    <Parameter name="OK_PORTAL_ENVIRONMENT" override="false" value="DevLocal"/>
+
+
+    <!-- Uncomment this to enable Comet connection tacking (provides events
+         on session expiration as well as webapp lifecycle) -->
+    <!--
+    <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
+    -->
+
+</Context>
diff --git a/deploy/lib/postgresql-42.0.0.jar b/deploy/lib/postgresql-42.0.0.jar
new file mode 100644
index 0000000..b89509b
--- /dev/null
+++ b/deploy/lib/postgresql-42.0.0.jar
Binary files differ
diff --git a/doc/build.txt b/doc/build.txt
new file mode 100644
index 0000000..737e8a3
--- /dev/null
+++ b/doc/build.txt
@@ -0,0 +1,23 @@
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+Backend:
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+Voraussetzungen:
+----------------
+Java 1.8 JDK
+Maven
+
+Bauen:
+------
+Im Rootpath des Backend-Projektes:
+>mvn clean install
+
+(Erzeugt in Target das WAR, die surefire-reports und das jacoco.exec für die Codecoverage-Analyse)
+Im Sonarqube schließen wir folgende Files von der CodeCoverageAnalyse aus:
+
+
+**/de/pta/openkonsequenz/betriebstagebuch/common/Globals.java
+**/rest/*.java
+**/LoggerUtil.java
+**/dao/*.java
+**/dao/interfaces/*.java
diff --git a/doc/doc_eLogbook_Rest.docx b/doc/doc_eLogbook_Rest.docx
new file mode 100644
index 0000000..14201c8
--- /dev/null
+++ b/doc/doc_eLogbook_Rest.docx
Binary files differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..cfc62a9
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>openk.pta.de</groupId>
+    <artifactId>portal</artifactId>
+    <version>1.0.0</version>
+    <packaging>war</packaging>
+
+    <properties>
+        <skip.asciidoc>false</skip.asciidoc>
+        <httpclient.version>4.5.3</httpclient.version>
+        <jersey-bundle.version>1.19.3</jersey-bundle.version>
+        <org.json.version>20160810</org.json.version>
+        <jersey.server.version>1.19.3</jersey.server.version>
+        <gson.version>2.8.0</gson.version>
+        <log4j.version>1.2.17</log4j.version>
+        <commons-io.version>2.5</commons-io.version>
+        <junit.version>4.12</junit.version>
+        <easymock.version>3.4</easymock.version>
+        <powermock-api-easymock.version>1.6.6</powermock-api-easymock.version>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <servlet-api>2.5</servlet-api>
+        <maven.test.skip>false</maven.test.skip>
+        <jacoco-maven-plugin.version>0.7.9</jacoco-maven-plugin.version>
+        <sonar-maven-plugin.version>3.0.2</sonar-maven-plugin.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>${org.json.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>resteasy-jaxrs</artifactId>
+            <version>3.0.21.Final</version>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.resteasy</groupId>
+            <artifactId>jaxrs-api</artifactId>
+            <version>3.0.12.Final</version>
+        </dependency>
+
+        <dependency>
+          <groupId>javax.servlet</groupId>
+          <artifactId>javax.servlet-api</artifactId>
+          <version>3.0.1</version>
+        </dependency>
+        <dependency>
+          <groupId>com.auth0</groupId>
+          <artifactId>java-jwt</artifactId>
+          <version>3.2.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-core</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-adapter-core</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-adapter-spi</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-servlet-adapter-spi</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-servlet-filter-adapter</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-common</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-model-jpa</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+        <dependency>
+          <groupId>org.keycloak</groupId>
+          <artifactId>keycloak-services</artifactId>
+          <version>3.2.0.Final</version>
+        </dependency>
+
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+            <version>${gson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+            <version>${log4j.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.sun.jmx</groupId>
+                    <artifactId>jmxri</artifactId>
+                </exclusion>
+
+                <exclusion>
+                    <groupId>com.sun.jdmk</groupId>
+                    <artifactId>jmxtools</artifactId>
+                </exclusion>
+
+                <exclusion>
+                    <groupId>javax.jms</groupId>
+                    <artifactId>jms</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>eclipselink</artifactId>
+            <version>2.6.4</version>
+        </dependency>
+        <dependency>
+            <groupId>postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>9.1-901-1.jdbc4</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>${junit.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <version>${easymock.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-module-junit4</artifactId>
+            <version>${powermock-api-easymock.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.powermock</groupId>
+            <artifactId>powermock-api-easymock</artifactId>
+            <version>${powermock-api-easymock.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jacoco</groupId>
+            <artifactId>jacoco-maven-plugin</artifactId>
+            <version>${jacoco-maven-plugin.version}</version>
+        </dependency>
+
+    </dependencies>
+
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>3.0.2</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>2.1</version>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-project-info-reports-plugin</artifactId>
+                <version>2.7</version>
+            </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>sonar-maven-plugin</artifactId>
+                <version>${sonar-maven-plugin.version}</version>
+            </plugin>
+            <plugin>
+                <groupId>org.jacoco</groupId>
+                <artifactId>jacoco-maven-plugin</artifactId>
+                <version>${jacoco-maven-plugin.version}</version>
+                <configuration>
+                    <skip>${maven.test.skip}</skip>
+                    <output>file</output>
+                    <append>true</append>
+                    <excludes>
+                        <exclude>**/Globals.*</exclude>
+                        <exclude>**/dao/**/*Dao*.java</exclude>
+                        <exclude>**/controller/BackendController.java</exclude>
+                    </excludes>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>jacoco-initialize</id>
+                        <goals>
+                            <goal>prepare-agent</goal>
+                        </goals>
+                    </execution>
+                    <execution>
+                        <id>jacoco-site</id>
+                        <phase>verify</phase>
+                        <goals>
+                            <goal>report</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.asciidoctor</groupId>
+                <artifactId>asciidoctor-maven-plugin</artifactId>
+                <version>1.5.3</version>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.asciidoctor</groupId>
+                        <artifactId>asciidoctorj-pdf</artifactId>
+                        <version>1.5.0-alpha.11</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.jruby</groupId>
+                        <artifactId>jruby-complete</artifactId>
+                        <version>1.7.21</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.asciidoctor</groupId>
+                        <artifactId>asciidoctorj</artifactId>
+                        <version>1.5.4</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.asciidoctor</groupId>
+                        <artifactId>asciidoctorj-diagram</artifactId>
+                        <version>1.5.4.1</version>
+                    </dependency>
+                </dependencies>
+                <configuration>
+                    <sourceDirectory>src/main/asciidoc</sourceDirectory>
+                    <requires>
+                        <require>asciidoctor-diagram</require>
+                    </requires>
+                    <attributes>
+                        <imagesoutdir>${project.build.directory}/generated-docs/images</imagesoutdir>
+                        <imagesDir>${project.build.directory}/generated-docs/images</imagesDir>
+                    </attributes>
+                </configuration>
+                <executions>
+
+                    <execution>
+                        <id>output-html</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>process-asciidoc</goal>
+                        </goals>
+                        <configuration>
+                            <skip>${skip.asciidoc}</skip>
+                            <imagesDir>${project.build.directory}/generated-docs/images</imagesDir>
+                            <requires>
+                                <require>asciidoctor-diagram</require>
+                            </requires>
+                            <sourceHighlighter>coderay</sourceHighlighter>
+                            <backend>html</backend>
+                            <doctype>book</doctype>
+                            <imagesDir>./images</imagesDir>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc b/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc
new file mode 100644
index 0000000..f19fa9a
--- /dev/null
+++ b/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc
@@ -0,0 +1,925 @@
+openKonsequenz - Architecture of the module "portal@openK"
+==========================================================
+:Author: Frank Dietrich
+:Email: frank.dietrich@pta.de
+:Date: 2017-09-18
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+This documentation bases on ARC42-Template (v7.0):
+
+*About arc42*
+
+arc42, the Template for documentation of software and system architecture.
+
+By Dr. Gernot Starke, Dr. Peter Hruschka and contributors.
+
+Template Revision: 7.0 EN (based on asciidoc), January 2017
+
+© We acknowledge that this document uses material from the arc 42 architecture template, http://www.arc42.de.
+Created by Dr. Peter Hruschka & Dr. Gernot Starke.
+
+<<<
+
+== Introduction and Goals
+
+=== Requirements Overview
+
+   [...]
+
+
+=== Quality Goals
+
+   [...]
+
+=== Stakeholders
+
+.Stakeholders
+[options="header,footer"]
+|=========================================================
+|Role/Name|Contact|Expectations
+|Product Owner (represents the Distribution System Operators)|Gordon Pickford, Oliver Tantu|The software must fulfil their functional and nonfunctional Requirements.
+|Module Developer|Michel Allessandrini, Jonas Tewolde, Frank Dietrich|All relevant business and technical information must be available for implementing the software.
+|External Reviewer (represents the AC/QC)|Martin Jung, Anja Berschneider|The software and the documentation is realized according the Quality and Architecture Handbook of openKONSEQUENZ.
+|System Integrator||A documentation for the integration of the module in the DSO specific environments must be available.
+|=========================================================
+
+== Architecture Constraints
+
+The main architecture constraints are:
+
+   [...]
+
+=== Technical Constraints
+
+The following technical constraints are given:
+
+.Technical Contraints
+[options="header,footer"]
+|========================================================
+|Component|Constraints
+|Basis components of the reference platform|
+- Application Server Tomcat
+- JPA EclipseLink
+- Database PostgreSQL
+
+|Enterprise Service Bus|
+* ESB Talend
+* Communication via RESTful Webservices
+
+|Programming Language Frontend
+a|* Angular
+* Bootstrap
+* jQuery
+* REST/JSON Interfaces
+
+|GUI design
+a|* According to oK-GUI-Styleguide
+
+|Java QA environment|Sonarqube 5.6.6
+
+|Programming Language
+a|* Backend: Java 1.8
+* Frontend: Angular 4.0.0 (Javascript, Typescript, HTML5, CSS3)
+
+|IDE
+a|* Not restricted (Eclipse, IntelliJ, Microsoft Developer Studio, Microsoft Visual Code ...)
+
+|Build system
+a|* Backend: Maven
+* Frontend: NodeJS + Angular/cli
+
+|Libraries, Frameworks,Components
+a|* Used Libraries/Frameworks have to be compatible to the Eclipse Public License
+|Architecture Documentation|* According ARC42-Template
+|========================================================
+
+
+=== Technical Dependencies
+
+The following libraries are used:
+
+.Libraries
+[options="header,footer"]
+|=========================================================
+|Name of the library|Version|Artefact-id|Usage|License|Tier
+|org.apache.httpcomponents.httpclient|4.5.3
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.apache.httpcomponents</groupId>
+    <artifactId>httpclient</artifactId>
+    <version>4.5.3</version>
+</dependency>
+----
+|Backend, Http-Client|Apache 2.0|Backend
+
+|org.json.json|20160810
+
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.json</groupId>
+    <artifactId>json</artifactId>
+    <version>20160810</version>
+</dependency>
+----
+|Backend - Json functionality|Json|Backend
+
+|org.jboss.resteasy.resteasy-jaxrs|3.0.21_Final
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.jboss.resteasy</groupId>
+    <artifactId>resteasy-jaxrs</artifactId>
+    <version>3.0.21.Final</version>
+</dependency>
+----
+|Backend - RestServer|Apache 2.0 / CC0.1.0/ Public|Backend
+
+|org.jboss.resteasy.jaxrs-api|3.0.12.Final
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.jboss.resteasy</groupId>
+    <artifactId>jaxrs-api</artifactId>
+    <version>3.0.12.Final</version>
+</dependency>
+----
+|Rest-Server|Apache 2.0|Backend
+
+|javax.servlet.servlet-api|3.0.1
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>javax.servlet</groupId>
+    <artifactId>servlet-api</artifactId>
+    <version>3.0.1</version>
+</dependency>
+----
+|Backend - Logging Servlet |CDDL GLP 2.0|Backend
+
+|com.google.code.gson.gson|2.8.0
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>com.google.code.gson</groupId>
+    <artifactId>gson</artifactId>
+    <version>2.8.0</version>
+</dependency>
+----
+|Backend Json de-serialization|Apache 2.0|Backend
+
+|log4j.log4j|1.2.17
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>log4j</groupId>
+    <artifactId>log4j</artifactId>
+    <version>1.2.17</version>
+</dependency>
+----
+|Backend logging|Apache 2.0|Backend
+
+|commons-io|2.5
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>commons-io</groupId>
+    <artifactId>commons-io</artifactId>
+    <version>2.5</version>
+</dependency>
+----
+|IO utils|Apache 2.0| Backend
+
+|junit.junit|4.12
+
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>junit</groupId>
+    <artifactId>junit</artifactId>
+    <version>4.12</version>
+</dependency>
+----
+|Unit testing|EPL 1.0|Backend
+
+|org.easymock.easymock|3.4
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.easymock</groupId>
+    <artifactId>easymock</artifactId>
+    <version>3.4</version>
+</dependency>
+----
+|Unit testing|Apache 2.0|Backend
+
+|org.powermock.powermock-api-easymock|1.6.6
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.powermock</groupId>
+    <artifactId>powermock-api-easymock</artifactId>
+    <version>1.6.6</version>
+</dependency>
+----
+|Unit testing|Apache 2.0|Backend
+
+|org.jacoco.jacoco-maven-plugin|0.7.9
+a|
+[source,xml]
+----
+<dependency>
+    <groupId>org.jacoco</groupId>
+    <artifactId>jacoco-maven-plugin</artifactId>
+    <version>0.7.9</version>
+</dependency>
+----
+|Test coverage|EPL 1.0|Backend
+
+|=========================================================
+
+== System Scope and Context
+
+=== Business Context
+
+ [...]
+
+=== Technical Context
+
+ [...]
+
+=== Solution Strategy
+
+<TODO>
+
+== Building Block View
+
+=== Whitebox Overall System
+
+The module Auth&Auth consists of the following components:
+
+.Module components
+[plantuml]
+....
+interface authAndAuthAPI
+
+node AuthAndAuthEnvironment {
+
+    component portalBE [
+        portalBackend
+    ]
+
+    component portalFE [
+        portalFrontend
+    ]
+
+    component keycloak [
+        KeyCloak
+    ]
+
+    portalFE-(0-portalBE
+    portalBE-(0-keycloak
+}
+
+node openKModule [
+    openKonsequenz module
+]
+
+
+portalBE #--authAndAuthAPI
+openKModule->authAndAuthAPI
+
+....
+
+
+. *portalFrontend* - The user interface of the portal. Consists of the login page and the module overview grid
+. *portalBackend* - Provides the services for its frontend.
+. *authAndAuthAPI* - Additionally the portalBackend provides general user and security services for
+for all openKonsequenz-Modules.
+. *KeyCloak* - KeyCloak implements most of the security aspects for the portal application and the modules.
+It provides an userinterface for user and role management of the modules and generates the JSON Web Token (JWT)
+for the session and access control.
+
+
+
+==== Auth&Auth-API
+
+The Auth&Auth needs information from the system Keycloak. Therefore, it must provide an interface for receiving the according data, see figure 1.
+
+=== Level 2
+
+==== portalFE – SPA (Frontend tier)
+
+
+The frontend component implements the concept of a single-page application (SPA). The framework used is Angular2. It divides the portalFE into three layers:
+
+
+1.Components - The components (Pages, Lists, Dialogs, Common Comp.) represent the presentation layer and the control layer. A component contains the control logic (.ts-file), an HTML-fragment as presentation description (.html-file) and a style definition (.css-file).
+
+
+2.Services - The service component communicates with the interfaces of the backend via HTTP requests by using the model component.
+
+
+3.Model - The model corresponds to the View-Model of the backend tier.
+
+.Frontend tier
+[plantuml]
+....
+
+node Backend-portalBE {
+
+    component RESTServices
+    component ViewModel
+}
+
+RESTServices.>ViewModel
+
+node Frontend-portalFE {
+
+    component services
+
+    node Components {
+        component pages
+        component commonComp
+        component dialogs
+
+    }
+    component model
+
+
+}
+
+services-(0-RESTServices
+model<->ViewModel
+services.>model
+Components.>services
+
+....
+
+
+
+==== portal.war (Backend tier)
+
+The backend tier contains five components which can be summarized in three layers:
+
+. *Presentation layer* - Represented by
+ .. REST-Srv
+ .. View Model
+. *Controller layer* - Represented by
+ ..	Controller
+.	*Model layer* - Represented by
+ ..	auth2 (Connection to "KeyCloak")
+
+
+.Backend tier
+[plantuml]
+....
+
+node PortalFrontend [
+    PortalFrontend
+]
+
+node ESB {
+    interface Auth_n_auth
+}
+
+
+node BackendLAN {
+    left to right direction
+
+    node KeyCloak {
+        component KeyCloakImplementation
+    }
+
+    node Backend-Portal {
+
+        skinparam rectangle {
+            roundCorner 25
+        }
+        rectangle "Presentation layer" {
+            component RESTServices
+            component ViewModel
+        }
+        rectangle "Controller layer" {
+            component Controller
+        }
+        rectangle "Model layer" {
+            component auth2
+        }
+
+        RESTServices.>Controller
+        RESTServices.>ViewModel
+        Controller.>auth2
+
+    }
+
+    RESTServices -- Auth_n_auth
+
+
+
+    interface OAuth2
+    interface KeyCloakAdmin
+
+    KeyCloak -- KeyCloakAdmin
+    KeyCloak -- OAuth2
+
+
+    auth2 -> OAuth2
+    auth2 -> KeyCloakAdmin
+
+}
+
+
+
+
+PortalFrontend-->Auth_n_auth
+
+
+node openKModule [
+    openKModule
+]
+
+
+openKModule --> Auth_n_auth
+
+....
+
+KeyCloak provides different interfaces. The backend uses the *OAuth2*-Interface for authentication
+and the *KeyCloak-admin* interface for other tasks (for example for getting users). The component *auth2* provides
+functionality for the access to KeyCloak. The Presentation layer consists of the *RESTServices* and the
+*ViewModel*. The *RESTServices* access the *Controller layer* in order to perform their tasks.
+
+The whole backend provides the *Auth&Auth* interface which is used by the *portalFrontend* and
+other *openKonsequenz-Modules* for authentication and other related tasks. The *Auth&Auth* interface is
+to be exported via ESB.
+
+
+
+== Runtime View
+=== Login / Authentication
+
+.Login sequence
+[plantuml]
+....
+actor User
+participant PortalFrontend
+participant PortalBackend
+participant KeyCloak
+
+User->PortalFrontend: Login page
+PortalFrontend->PortalBackend: /login(loginCredentials)
+PortalBackend->KeyCloak: /.../realms/.../protocol/openid-connect/token(?loginInfo)
+KeyCloak --> PortalBackend: return JWT
+PortalBackend -> PortalBackend: Create Session with JWT
+PortalBackend --> PortalFrontend: return JWT
+PortalFrontend -> PortalFrontend: store JWT
+PortalFrontend --> User: Navigate to ModuleGrid
+
+....
+
+=== Logout
+
+.Logout sequence
+[plantuml]
+....
+actor User
+participant oK_Module
+participant PortalBackend
+
+
+User->oK_Module: logout
+oK_Module->PortalBackend: /logout with JWT
+PortalBackend->PortalBackend: Remove Session with JWT
+PortalBackend-->oK_Module:
+oK_Module->oK_Module: Navigate to Logout/closing page
+oK_Module-->User
+
+....
+
+=== Check authorization
+
+.CheckAuth sequence
+[plantuml]
+....
+actor User
+participant oK_Module
+participant PortalBackend
+
+
+User->oK_Module: Any action that requires an auth check
+oK_Module->PortalBackend: /checkAuth with JWT
+
+group authorize
+    PortalBackend->PortalBackend: Check if valid session with JWT exists
+
+    group check failed
+        PortalBackend-->oK_Module: raise HttpCode "Unauthorized 401"
+    end
+
+    group check succeeded
+        PortalBackend-->oK_Module: return HttpCode "Success 200"
+    end
+end
+
+oK_Module->oK_Module: react on HttpCode
+oK_Module-->User:
+
+....
+
+=== Get users for role
+.GetUsersForRole sequence
+[plantuml]
+....
+actor User
+
+participant oK_Module
+participant KeyCloak
+participant PortalBackend
+
+actor Timer_cycl
+
+group refresh usersWithRoles cache
+    Timer_cycl->PortalBackend: Get userWithRoles
+
+    PortalBackend->KeyCloak: Login with admin user
+    KeyCloak-->PortalBackend
+    PortalBackend->KeyCloak: Get realm users
+    KeyCloak-->PortalBackend
+
+    group repeat for each user
+        PortalBackend->KeyCloak:Get role-mapping for user
+    KeyCloak-->PortalBackend
+    end
+    PortalBackend->PortalBackend: update cache
+    PortalBackend-->Timer_cycl
+end
+...
+
+
+User->oK_Module: Any action that needs all users having a role
+oK_Module->PortalBackend: /usersForRole/{userRole}
+PortalBackend->PortalBackend: evaluate from usersWithRoles cache
+PortalBackend-->oK_Module: return result
+oK_Module-->User
+
+....
+
+
+
+=== Open module in portal frontend
+.Start module sequence
+[plantuml]
+....
+actor User
+
+participant PortalFE
+participant openKModule
+
+User->PortalFE: User (logged in) opens module
+PortalFE->openKModule: Open configured URL in new browser tab, providing the JWT
+....
+
+
+
+== Deployment View
+
+The Auth&Auth application consists of 3 parts regarding the deployment.
+
+. Frontend: "portalFE"-Directory
+. Backend: "portal.war"
+. Keycloak: OAuth2 and JWT Service implementation
+
+=== Deployment of the application components
+
+==== Deployment of the frontend
+
+The Frontend SPA is built as a folder, that contains all the required files for
+the application. When deploying the frontend application, the content of the "dist"-folder
+within the Frontend development-directory has to be copied into the
+target-directory of the apache-tomcat:
+
+ <Apache-Tomcat>/webapps/portalFE
+
+If the target folder does not exist, it has to be created manually.
+
+==== Deployment of the backend
+The backend REST-services are built in form of a "WAR"-file (to be found
+in the "target"-directory of the MAVEN-directory structure).
+For deployment, this file has to be copied to the directory
+
+ <Apache-Tomcat>/webapps
+
+==== Deployment of Keycloak
+
+
+. Get "Keycloak 3.2.1 Final" ("keycloak-3.2.1.Final.zip") from the Keycloak download page. +
+Download "Server Standalone server distribution": http://www.keycloak.org/archive/downloads-3.2.1.html
+
+. Extract the content.
+. To create an initial admin account for Keycloak run the script `add-user-keycloak.sh` with username 'admin'
+and a strong password.
+
+ <Keycloak-Directory>/bin/add-user-keycloak.sh -r master -u <username> -p <password>
+
+. To start Keycloak create a *Linux-Service which executes* the `standalone.sh` script to be found in the Keycloak `bin`
+directory.
+
+ <Keycloak-Directory>/bin/standalone.sh
+
+
+TIP: Keycloaks default port is 8080 you can change it to for example to port 1234 with the following
+execution parameter: -Djboss.http.port=1234
+
+ <Keycloak-Directory>/bin/standalone.sh -Djboss.http.port=1234
+
+==== Configuration of the system
+
+===== Configuration of the webserver
+
+There exists the file *context.xml* in the "conf" subdirectory (*<TOMCAT>/conf*) of the target apache tomcat installation.
+Add the following parameter and resource in order to access the correct backend configurations and to
+gain access to the database (see "Configuration of the backend" below):
+
+.context.xml
+[source,xml]
+----
+[...]
+    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
+
+    <!--Manager pathname=""/>
+
+
+    <Parameter name="environment" override="false" value="Development"/-->
+
+   <Parameter name="OK_PORTAL_ENVIRONMENT" override="false" value="Production"/>
+
+    <!-- Uncomment this to enable Comet connection tacking (provides events
+         on session expiration as well as webapp lifecycle) -->
+[...]
+----
+
+
+===== Configuration of the backend
+
+After the backend war file has been deployed and unpacked inside of the *<TOMCAT>/webapps* folder there are different
+ backend config files to be found in the folder *<TOMCAT>/webapps/elogbook/WEB-INF/classes*
+
+* backendConfig*.json
+* moduleConfig*.json
+
+The active configuration is chosen by parameter *OK_PORTAL_ENVIRONMENT* (see context.xml above).
+Possible values are:
+
+* *Custom* (for backendConfigCustom.json and moduleConfigCustom.json)
+* *DevLocal* (for backendConfigDevLocal.json and moduleConfigDevLocal.json)
+* *DevServer* (for backendConfigDevServer.json and moduleConfigDevServer.json)
+* *Production* (for backendConfigProduction.json and moduleConfigProduction.json)
+
+After choosing an environment the corresponding json files have to be configured:
+
+.backendConfigXXX.json
+[source,json]
+----
+{
+  "internalSessionLengthMillis": 46800000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://localhost:8080/",
+  "keycloakRealm": "OpenKRealm",
+  "keycloakClient": "OpenKClient",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "adminpwd"
+}
+----
+* *internalSessionLengthMillis* - Maximum allowed duration of inactivity, before a session ends
+* *reloadUsersInSec* - Polling interval for getting all users from keycloak
+* *authServerUrl* - Base url of the keycloak instance
+* *keycloakRealm* - Configured realm on keycloak
+* *keycloakClient* - Configured client on keycloak
+* *keycloakAdmin* - user for admin access on keycloak
+* *keycloakPW* - password of the admin user
+
+
+.moduleConfigXXX.json
+[source,json]
+----
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://172.18.22.160:8880/elogbookFE",
+    "pictureLink": "https://www.openkonsequenz.de/.../m_logbuch_2443636.jpg",
+    "requiredRole": "elogbook-access"
+
+  },
+  {
+    "name": "Bereitschaftsplanung",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/..../94-bereitschaftsplan",
+    "pictureLink": "https://www.openkonsequenz.de/medien/.../l_bereitschaftsplan_57882047.jpg",
+    "requiredRole": "planning-access"
+  },
+
+  ...
+
+]
+
+----
+
+* *name* - Name/description of the module
+* *cols* - always "1"
+* *rows* - always "1"
+* *color* - always "#ffffff"
+* *link* - URL for the module
+* *pictureLink* - URL for picture belonging to the module
+* *requiredRole* - Name of the role (on keycloak) the user must have to access the module
+
+
+===== Configuration of Keycloak
+
+. Login in Keycloak
+
+.. Go to http://<KEYCLOAK-SERVER-IP>:<CONFIGURED-KEYCLOAK-PORT>/ +
+Hit the `Administration Console` -Link and login with admin account created during the Keycloak-deployment
+(see above).
+
+. Add a new realm: `MainDonauNetz`
+
+.Add a new realm overview
+[options="header,footer"]
+image::newRealm1.png[new Realm]
+
+.Add a new realm
+[options="header,footer"]
+image::newRealm2.png[new Realm]
+
+[start=3]
+. Create a client with client ID `elogbook-backend`.
+
+.Create a client overview
+[options="header,footer"]
+image::createClient.png[create Client]
+
+.Add a client
+[options="header,footer"]
+image::addClient.png[add Client]
+
+[start=4]
+. Set the client settings accordingly:
+
+.Client settings of elogbook-backend
+[options="header,footer"]
+image::clientSettings.png[Client settings]
+
+[start=5]
+. Add the roles under `Roles` press `Add Role`. Add the following Roles:
+- elogbook-normaluser
+- elogbook-superuser
+- elogbook-access
+- planning-access
+- feedin-management-access
+- planned-policies-access
+
+. Configuring elogbook-superuser role. Hit elogbook-superuser or press `Edit`
+.. Switch `Composite Roles` to on.
+.. Add the Realm Role 'elogbook-normaluser' from the `Available Roles`
+.. Select from the `Client Roles` Dropdown-List 'realm-management' and add the role 'view-users'.
+
+.Elogbook superuser composite role
+[options="header,footer"]
+image::rolesSuperUser.png[Elogbook superuser composite role]
+
+[start=7]
+. Adding users under `Users` press `Add User`.
+
+.Add a user
+[options="header,footer"]
+image::addingUsers.png[Add a User]
+
+.. Fill in username, First Name, Last Name, else is default and save it.
+.. Go to the `Credentials` tab and type in a new password and the confirmation as well, disable `Temporary`. Press `Reset Password`.
+Press `Change Password`.
+
+.Credentials tab
+[options="header,footer"]
+image::credentials.png[Credentials tab]
+
+[start=3]
+.. Go to the `Role Mappings` tab. +
+Here you grant rights/roles to the users:
+Select the from the previously created roles in `Available Roles` and hit `Add selected`. +
+... User right in the distinct modul elogbook (`elogbook-access` required of course):
+- elogbook-normaluser = standard user in the elogbook-app
+- elogbook-superuser = admin user in the elogbook-app
+
+... Access rights to the specific modul:
+- elogbook-access
+- planning-access
+- feedin-management-access
+- planned-policies-access
+
+.Role Mappings tab
+[options="header,footer"]
+image::roleMappings.png[Role Mapping]
+
+
+[start=4]
+.. Go back to the `Details` tab and make sure `Recquired User Actions` is empty. Delete anything which is in there with a press on the little cross.
+
+[start=8]
+. Add an admin user. (Mandatory) +
+Same procedure like adding a User (see 7.) but with the role 'elogbook-superuser' instead of
+'elogbook-normaluser'.
+
+IMPORTANT: We use this admin account (username & password) also to configure the backend. +
+See "Configuration of the backend",
+username & password from here is keycloakAdmin & keycloakPW there.
+
+
+
+=== CI- and CD-Components
+
+==== GIT-Repository
+
+<TODO>
+
+==== Hudson
+
+<TODO>
+
+==== Sonar
+
+<TODO>
+
+==== Code-Coverage of the Frontend - Karma-Istanbul-Output
+
+<TODO>
+
+=== Continuous Deployment
+
+
+
+== Design Decisions
+
+All architecture decisions based on the Architecture Committee Handbook. There are no deviations.
+ 
+
+== Quality Requirements
+
+TODO: Muss noch beschrieben werden
+
+=== Quality Tree
+
+TODO: Muss noch beschrieben werden
+
+=== Quality Scenarios
+
+TODO: Muss noch beschrieben werden
+
+
+
+== Risks and Technical Debts
+
+(Muss noch beschrieben werden)
+
+<<<
+
+== Glossary
+
+=== Technical Constraints
+
+.Technical Contraints
+[options="header,footer"]
+|========================================================
+|Short|Long|German|Description
+|AC|Architecture Committee|Architektur-Komittee|Gives Framework and Constraints according to architecture for oK projects.
+|CNCU|Central Network Control Unit||
+|DAO|Data Access Objects||
+|DSO|Distribution System Operator|Verteilnetz-betreiber (VNB)|Manages the distribution network for energy, gas or water.
+|EPL|Eclipse Public License||Underlying license model for Eclipse projects like elogbook@openK
+|ESB|Enterprise Service Bus||Central instance for exchange of data to overcome point-to-point connections.
+|oK|openKONSEQUENZ|openKONSEQUENZ|Name of the consortium of DSOs
+|QC|Quality Committee|Qualitätskomitee|Gives framework and constraints according to quality for oK projects.
+|SCADA|Supervisory Control and Data Acquisition|Netzleitsystem|System, that allows DSOs view/control actual parameters of their power grid.
+|========================================================
+
+
+
diff --git a/src/main/asciidoc/images/BackendTier.png b/src/main/asciidoc/images/BackendTier.png
new file mode 100644
index 0000000..3b626ec
--- /dev/null
+++ b/src/main/asciidoc/images/BackendTier.png
Binary files differ
diff --git a/src/main/asciidoc/images/DatabaseTier.png b/src/main/asciidoc/images/DatabaseTier.png
new file mode 100644
index 0000000..6225be2
--- /dev/null
+++ b/src/main/asciidoc/images/DatabaseTier.png
Binary files differ
diff --git a/src/main/asciidoc/images/DistributionOfComponents1.png b/src/main/asciidoc/images/DistributionOfComponents1.png
new file mode 100644
index 0000000..44bd6c8
--- /dev/null
+++ b/src/main/asciidoc/images/DistributionOfComponents1.png
Binary files differ
diff --git a/src/main/asciidoc/images/FrontendTier.png b/src/main/asciidoc/images/FrontendTier.png
new file mode 100644
index 0000000..d820cc5
--- /dev/null
+++ b/src/main/asciidoc/images/FrontendTier.png
Binary files differ
diff --git a/src/main/asciidoc/images/SolutionArchitecture.png b/src/main/asciidoc/images/SolutionArchitecture.png
new file mode 100644
index 0000000..bc731ac
--- /dev/null
+++ b/src/main/asciidoc/images/SolutionArchitecture.png
Binary files differ
diff --git a/src/main/asciidoc/images/SystemContext.png b/src/main/asciidoc/images/SystemContext.png
new file mode 100644
index 0000000..cd194ce
--- /dev/null
+++ b/src/main/asciidoc/images/SystemContext.png
Binary files differ
diff --git a/src/main/asciidoc/images/addClient.png b/src/main/asciidoc/images/addClient.png
new file mode 100644
index 0000000..039414b
--- /dev/null
+++ b/src/main/asciidoc/images/addClient.png
Binary files differ
diff --git a/src/main/asciidoc/images/addingUsers.png b/src/main/asciidoc/images/addingUsers.png
new file mode 100644
index 0000000..5e3511c
--- /dev/null
+++ b/src/main/asciidoc/images/addingUsers.png
Binary files differ
diff --git a/src/main/asciidoc/images/ba.png b/src/main/asciidoc/images/ba.png
new file mode 100644
index 0000000..fdf8327
--- /dev/null
+++ b/src/main/asciidoc/images/ba.png
Binary files differ
diff --git a/src/main/asciidoc/images/clientSettings.png b/src/main/asciidoc/images/clientSettings.png
new file mode 100644
index 0000000..44f80ab
--- /dev/null
+++ b/src/main/asciidoc/images/clientSettings.png
Binary files differ
diff --git a/src/main/asciidoc/images/createClient.png b/src/main/asciidoc/images/createClient.png
new file mode 100644
index 0000000..ea86c6d
--- /dev/null
+++ b/src/main/asciidoc/images/createClient.png
Binary files differ
diff --git a/src/main/asciidoc/images/credentials.png b/src/main/asciidoc/images/credentials.png
new file mode 100644
index 0000000..b15c2f8
--- /dev/null
+++ b/src/main/asciidoc/images/credentials.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/caution.png b/src/main/asciidoc/images/icons/caution.png
new file mode 100644
index 0000000..9a8c515
--- /dev/null
+++ b/src/main/asciidoc/images/icons/caution.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/important.png b/src/main/asciidoc/images/icons/important.png
new file mode 100644
index 0000000..be685cc
--- /dev/null
+++ b/src/main/asciidoc/images/icons/important.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/note.png b/src/main/asciidoc/images/icons/note.png
new file mode 100644
index 0000000..7c1f3e2
--- /dev/null
+++ b/src/main/asciidoc/images/icons/note.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/tip.png b/src/main/asciidoc/images/icons/tip.png
new file mode 100644
index 0000000..f087c73
--- /dev/null
+++ b/src/main/asciidoc/images/icons/tip.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/warning.png b/src/main/asciidoc/images/icons/warning.png
new file mode 100644
index 0000000..d41edb9
--- /dev/null
+++ b/src/main/asciidoc/images/icons/warning.png
Binary files differ
diff --git a/src/main/asciidoc/images/newRealm1.png b/src/main/asciidoc/images/newRealm1.png
new file mode 100644
index 0000000..0c28a5e
--- /dev/null
+++ b/src/main/asciidoc/images/newRealm1.png
Binary files differ
diff --git a/src/main/asciidoc/images/newRealm2.png b/src/main/asciidoc/images/newRealm2.png
new file mode 100644
index 0000000..b039e1b
--- /dev/null
+++ b/src/main/asciidoc/images/newRealm2.png
Binary files differ
diff --git a/src/main/asciidoc/images/roleMappings.png b/src/main/asciidoc/images/roleMappings.png
new file mode 100644
index 0000000..5528b29
--- /dev/null
+++ b/src/main/asciidoc/images/roleMappings.png
Binary files differ
diff --git a/src/main/asciidoc/images/roleSuperUser.png b/src/main/asciidoc/images/roleSuperUser.png
new file mode 100644
index 0000000..413d285
--- /dev/null
+++ b/src/main/asciidoc/images/roleSuperUser.png
Binary files differ
diff --git a/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc b/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc
new file mode 100644
index 0000000..d72f38e
--- /dev/null
+++ b/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc
@@ -0,0 +1,352 @@
+authAndAuth@openK - Backend REST-Service documentation
+======================================================
+:Author: Frank Dietrich
+:Email: frank.dietrich@pta.de
+:Date: 2017-07-12
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+
+== Base-URL
+
+----
+http://<host>:<port>/<name-of-war>/rest/beservice
+----
+
+== Common Features
+All services may return the following http status codes:
+
+.Http-Status-Codes
+[options="header,footer"]
+|=========================================================
+|Code|Description|Usage within the application
+|200|OK|-
+|400|Bad Request|The structure of the request (for example a JSON within a post request) is not correct
+|401|Unauthorized|Login-credentials are wrong or there is an invalid session token
+|500|Internal Server Error|An unexpected error occurred
+|=========================================================
+
+If there is a special service behavior regarding the returned http status code, then it will be explained within the service description.
+
+== Protection
+
+The protection of services is implemented by a security token following the JWT (JSON Web Token) specification:
+https://jwt.io/
+
+The *“login”*-service provides a JWT, when called with valid user-credentials.
+The security token (access token) (which is part of the JWT) has always to be provided with the
+HTTP-Header-Parameter "Authorization", in order to access a secured services later on.
+
+
+=== JSON Web Token
+
+The token has several purposes. A typical client of the Auth&Auth-Service needs to use
+the following features:
+
+. *access token* to access functions of a secured service
+. *user-information* to get extended information about the own user
+. *user-roles* of the own user.
+
+Even though JWT is a defined standard, we only will describe those features inside this document,
+which are directly used by the Auth&Auth-Service.
+
+Generally JWT uses *base64-encoding*. The data, that is stored in a token is always
+encoded with *base64*.
+
+[IMPORTANT]
+====
+The data in the examples has been shortened. Real examples would be very long and hard to read.
+====
+
+==== Access token
+The *access token* can be directly found in the field "access_token" within the JWT.
+
+
+
+Example:
+[source,json]
+----
+{
+    "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAixxxIn0.eyBBB.eydkk",
+    "expires_in":300,
+    "refresh_expires_in":1800,
+    "refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAixxxIn0.eyJqdGwLTQyMTYtOD.eydkk",
+    "token_type":"bearer",
+    "id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2l.eyJqdGkLTRjZTItYT.oUkke",
+    "not-before-policy":1502453751,
+    "session_state":"8b4e6979-1d51-4086-9db5-d296f70b4b65"
+}
+
+----
+
+
+==== User-Information/UserRoles
+
+The 2nd part (between the first and the second period *"."* - in this example "'eyBBB'") of the access-token is called the *"access-token-payload"*. When decoded from Base64 it could
+look like this:
+
+[source,json]
+----
+{
+    "jti":"a3d15ccf-c0e3-4534-a05a-f18b3a7c778b",
+    "exp":1505736257,
+    "nbf":0,
+    "iat":1505735957,
+    "iss":"http://authserver:8080/auth/realms/elogbook",
+    "aud":"elogbook-backend",
+    "sub":"c4b78aa7-91d2-45d7-8ca3-163156d9ee40",
+    "typ":"Bearer",
+    "azp":"elogbook-backend",
+    "auth_time":0,
+    "session_state":"59ae4a68-595b-4345-873d-aadf0a3efc94",
+    "acr":"1",
+    "allowed-origins":["*"],
+    "realm_access":{"roles":["elogbook-normaluser","uma_authorization"]},
+    "resource_access":{"account":{"roles":["manage-account","manage-account-links","view-profile"]}},
+    "name":"Hugo Boss",
+    "preferred_username":"hugo",
+    "given_name":"Hugo",
+    "family_name":"Boss"
+}
+----
+
+The configured roles of the user can be determined from the json array:
+
+ * *realm_access"*
+
+Extended
+user information can be found in the fields:
+
+ * *"name"*
+ * *"perferred_username"*
+ * *"given_name"*
+ * *"family_name"*.
+
+
+== Services
+=== Receive Version Information
+This service returns the current version of the backend implementation and the version of the database structure.
+
+*URL:* /versionInfo
+
+*Method:* GET
+
+*Request-Headers*:
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+{
+    "backendVersion": "0.1.1-Snapshot"
+}
+----
+
+*Protection*: none
+
+*Remarks*:
+
+=== Login
+This service receives login credentials in order to perform the authentication. If the login succeeds,
+it provides a valid JWT, used for accessing other services later on.
+
+*URL:* /login
+
+*Method:* POST
+
+*Request-Body*:
+[source,json]
+----
+{
+  "userName": "Mustermann",
+  "password": "clearpassword"
+}
+----
+
+*Produces*: application/json
+
+*Response*:
+
+JWT (JSON Web Token)
+
+*Remarks*: See chapter "*JWT*" for detailed informations about the features of the returned token.
+
+
+=== Logout
+This services kills the server session belonging to the the given session token.
+
+*URL:* /logout
+
+*Method:* POST
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+
+*Remarks*:
+
+=== CheckAuthorization
+This services receives a JWT in the "Authorization" Http header and checks, if its still valid.
+If it is valid, it resets the inactivity time for that token.
+
+*URL:* /checkAuth
+
+*Method:* GET
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+{
+  "ret": "OK"
+}
+----
+
+*Remarks*: This service return OK when the provided token is still valid. Otherwise it returns a 401 - "Unauthorized" Http Code.
+
+=== Get user modules for the current user
+This service returns the modules for which the user is authorized.
+
+*URL:* /userModulesForUser
+
+*Method:* GET
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+[
+    {
+        "name":"Betriebstagebuch",
+        "cols":1,
+        "rows":1,
+        "color":"#ffffff",
+        "link":"http://172.18.22.160:8880/elogbookFE",
+        "pictureLink":"https://www.openkonsequenz.de/xxxelogbuch_2443636.jpg",
+        "requiredRole":"elogbook_access"
+    }
+    ,
+    {
+        "name":"Bereitschaftsplanung",
+        "cols":1,
+        "rows":1,
+        "color":"#ffffff",
+        "link":"https://www.openkonsequenz.de/anwender/xxxx/94-bereitschaftsplan",
+        "pictureLink":"https://www.openkonsequenz.de/medien/xxx/l_bereitschaftsplan_57882047.jpg",
+        "requiredRole":"planning_access"
+    }
+    ,
+    {
+    ...
+    }
+]
+----
+
+*Remarks*: This service checks if the currently logged in user has the role "requiredRole" in its JWT and
+returns the modules he is authorized for.
+
+
+=== Get all users for a specific role
+This service returns all users belonging to the specified role.
+
+*URL:* /usersForRole/{userRole}
+
+*Method:* GET
+
+*Path-Parameter*: userRole
+
+* The role name like it is defined in Keycloak
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+[
+    {
+        "id": "359ef9c9-77df-4a3d-a9c9-f96d837d2d57",
+        "createdTimestamp": 1501594173784,
+        "username": "admin",
+        "enabled": true,
+        "totp": false,
+        "emailVerified": false,
+        "firstName": "Administrator",
+        "lastName": "Administratowich",
+        "realmRoles": [
+            "elogbook-superuser",
+            "elogbook_access",
+            "uma_authorization",
+            "elogbook-normaluser"
+        ],
+        "disableableCredentialTypes": [
+            "password"
+        ],
+        "requiredActions": [],
+        "access": {
+            "manageGroupMembership": false,
+            "view": true,
+            "mapRoles": false,
+            "impersonate": false,
+            "manage": false
+        }
+    },
+    {
+        "id": "c4b78aa7-91d2-45d7-8ca3-163156d9ee40",
+        "createdTimestamp": 1501594239066,
+        "username": "hugo",
+        "enabled": true,
+        "totp": false,
+        "emailVerified": false,
+        "firstName": "Hugo",
+        "lastName": "Boss",
+        "realmRoles": [
+            "elogbook_access",
+            "elogbook-normaluser"
+        ],
+        "disableableCredentialTypes": [
+            "password"
+        ],
+        "requiredActions": [],
+        "access": {
+            "manageGroupMembership": false,
+            "view": true,
+            "mapRoles": false,
+            "impersonate": false,
+            "manage": false
+        }
+    },
+    {
+      ...
+    }
+]
+----
+
+*Remarks*:
+
+
+
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java
new file mode 100644
index 0000000..09e655f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java
@@ -0,0 +1,12 @@
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+
+public class JwtAccount {
+    private List<String> roles;
+
+    public List<String> getRoles() {
+        return roles;
+    }
+    public void setRoles(List<String> roles) { this.roles = roles; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java
new file mode 100644
index 0000000..7b53747
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java
@@ -0,0 +1,14 @@
+package org.eclipse.openk.portal.auth2.model;
+
+public class JwtHeader {
+    private String alg;
+    private String typ;
+    private String kid;
+
+    public String getAlg() { return alg; }
+    public void setAlg(String alg) { this.alg = alg; }
+    public String getTyp() { return typ; }
+    public void setTyp(String typ) { this.typ = typ; }
+    public String getKid() { return kid; }
+    public void setKid(String kid) { this.kid = kid; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java
new file mode 100644
index 0000000..5a516cd
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java
@@ -0,0 +1,100 @@
+package org.eclipse.openk.portal.auth2.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+
+public class JwtPayload {
+
+    //No Sonar because variables are wrong due to jwt definition
+
+    private String jti;
+    private long exp;
+    private long nbf;
+    private long iat;
+    private String iss;
+    private String aud;
+    private String sub;
+    private String typ;
+    private String azp;
+    private String nonce;
+    private Integer auth_time; //NOSONAR
+    private String session_state; //NOSONAR
+    private String acr;
+
+    @JsonProperty("allowed-origins")
+    private List<String> allowedOrigins;
+    private JwtRealmAccess realm_access; //NOSONAR
+    private JwtResourceAccess resource_access; //NOSONAR
+
+    private String name;
+    private String preferred_username; //NOSONAR
+    private String given_name; //NOSONAR
+    private String family_name; //NOSONAR
+
+    public String getJti() { return jti; }
+    public void setJti(String jti) { this.jti = jti; }
+
+    public long getExp() { return exp; }
+    public void setExp(long exp) { this.exp = exp; }
+
+    public long getNbf() { return nbf; }
+    public void setNbf(long nbf) { this.nbf = nbf; }
+
+    public long getIat() { return iat; }
+    public void setIat(long iat) { this.iat = iat; }
+
+    public String getiss() { return iss; }
+    public void setiss(String iss) { this.iss = iss; }
+
+    public String getaud() { return aud; }
+    public void setaud(String aud) { this.aud = aud; }
+
+    public String getsub() { return sub; }
+    public void setsub(String sub) { this.sub = sub; }
+
+    public String gettyp() { return typ; }
+    public void settyp(String typ) { this.typ = typ; }
+
+    public String getAzp() { return azp; }
+    public void setAzp(String azp) { this.azp = azp; }
+
+    public String getNonce() { return nonce; }
+    public void setNonce(String nonce) { this.nonce = nonce; }
+
+    public Integer getAuthTime() { return auth_time; }
+    public void setAuthTime(Integer auth_time) { this.auth_time = auth_time; } //NOSONAR
+
+    public String getSessionState() { return session_state; }
+    public void setSessionState(String session_state) { this.session_state = session_state; } //NOSONAR
+
+    public String getAcr() { return acr; }
+    public void setAcr(String acr) { this.acr = acr; }
+
+    public List<String> getAllowedOrigins() {
+        return allowedOrigins;
+    }
+    public void setAllowedOrigins(List<String> allowedOrigins) { this.allowedOrigins = allowedOrigins; }
+
+    public JwtRealmAccess getRealmAccess() { return realm_access; }
+    public void setRealmAccess(JwtRealmAccess realm_access) { this.realm_access = realm_access; } //NOSONAR
+
+    public JwtResourceAccess getResourceAccess() { return resource_access; }
+    public void setResourceAccess(JwtResourceAccess resource_access) { this.resource_access = resource_access; } //NOSONAR
+
+    public String getName() { return name; }
+    public void setName(String name) { this.name = name; }
+
+    public String getPreferredUsername() { return preferred_username; }
+    public void setPreferredUsername(String preferred_username) { this.preferred_username = preferred_username; } //NOSONAR
+
+    public String getGivenName() { return given_name; }
+    public void setGivenName(String given_name) { this.given_name = given_name; } //NOSONAR
+
+    public String getFamilyName() { return family_name; }
+    public void setFamilyName(String family_name) { this.family_name = family_name; } //NOSONAR
+
+    public boolean isInRole(String role) {
+        return this.realm_access != null && this.realm_access.isInRole(role);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java
new file mode 100644
index 0000000..1b689a9
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java
@@ -0,0 +1,17 @@
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+
+public class JwtRealmAccess {
+    private List<String> roles;
+
+    public List<String> getRoles() {
+        return roles;
+    }
+    public void setRoles(List<String> roles) { this.roles = roles; }
+
+
+    public boolean isInRole(String role) {
+        return this.roles != null && this.roles.contains(role);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java
new file mode 100644
index 0000000..878b10e
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java
@@ -0,0 +1,8 @@
+package org.eclipse.openk.portal.auth2.model;
+
+public class JwtResourceAccess {
+    private JwtAccount account;
+
+    public JwtAccount getAccount() { return account; }
+    public void setAccount(JwtAccount account) { this.account = account; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java
new file mode 100644
index 0000000..2580825
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java
@@ -0,0 +1,32 @@
+package org.eclipse.openk.portal.auth2.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class JwtToken {
+
+    //No Sonar because variables are wrong due to jwt definition
+
+    private String access_token; //NOSONAR
+    private String refresh_token; //NOSONAR
+    private String token_type; //NOSONAR
+    private String session_state; //NOSONAR
+    private Integer expires_in; //NOSONAR
+    private Integer refresh_expires_in; //NOSONAR
+    @JsonProperty("not-before-policy")
+    private Integer not_before_policy; //NOSONAR
+
+    public String getAccessToken() { return access_token; }
+    public void setAccessToken(String access_token) { this.access_token = access_token; } //NOSONAR
+    public String getRefreshToken() { return refresh_token; }
+    public void setRefreshToken(String refresh_token) { this.refresh_token = refresh_token; } //NOSONAR
+    public String getTokenType() { return token_type; }
+    public void setTokenType(String token_type) { this.token_type = token_type; } //NOSONAR
+    public String getSessionState() { return session_state; }
+    public void setSessionState(String session_state) { this.session_state = session_state; } //NOSONAR
+    public Integer getExpiresIn() { return expires_in; }
+    public void setExpiresIn(Integer expires_in) { this.expires_in = expires_in; } //NOSONAR
+    public Integer getRefreshExpiresIn() { return refresh_expires_in; }
+    public void setRefreshExpiresIn(Integer refresh_expires_in) { this.refresh_expires_in = refresh_expires_in; } //NOSONAR
+    public Integer getNotBeforePolicy() { return not_before_policy; }
+    public void setNotBeforePolicy(Integer not_before_policy) { this.not_before_policy = not_before_policy; } //NOSONAR
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java
new file mode 100644
index 0000000..7b8e868
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java
@@ -0,0 +1,68 @@
+package org.eclipse.openk.portal.auth2.model;
+
+public class KeyCloakRole {
+
+  private String id;
+  private String name;
+  private Boolean scopeParamRequired;
+  private Boolean composite;
+  private Boolean clientRole;
+  private String containerId;
+
+  public KeyCloakRole(String id, String name, Boolean scopeParamRequired, Boolean composite, Boolean clientRole, String containerId) {
+    this.id = id;
+    this.name = name;
+    this.scopeParamRequired = scopeParamRequired;
+    this.composite = composite;
+    this.clientRole = clientRole;
+    this.containerId = containerId;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public Boolean getScopeParamRequired() {
+    return scopeParamRequired;
+  }
+
+  public void setScopeParamRequired(Boolean scopeParamRequired) {
+    this.scopeParamRequired = scopeParamRequired;
+  }
+
+  public Boolean getComposite() {
+    return composite;
+  }
+
+  public void setComposite(Boolean composite) {
+    this.composite = composite;
+  }
+
+  public Boolean getClientRole() {
+    return clientRole;
+  }
+
+  public void setClientRole(Boolean clientRole) {
+    this.clientRole = clientRole;
+  }
+
+  public String getContainerId() {
+    return containerId;
+  }
+
+  public void setContainerId(String containerId) {
+    this.containerId = containerId;
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java
new file mode 100644
index 0000000..e9f8b10
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java
@@ -0,0 +1,86 @@
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+import java.util.Map;
+
+public class KeyCloakUser {
+    private String id;
+    private long createdTimestamp;
+    private String username;
+    private boolean enabled;
+    private boolean totp;
+    private boolean emailVerified;
+    private String firstName;
+    private String lastName;
+    private List<String> realmRoles;
+    private Map<String, List<String>> clientRoles;
+
+    private List<String> disableableCredentialTypes;
+    private List<String> requiredActions;
+    private KeyCloakUserAccess access;
+
+    public String getId() { return id; }
+    public void setId(String id) { this.id = id; }
+
+    public long getCreatedTimestamp() { return createdTimestamp; }
+    public void setCreatedTimestamp(long createdTimestamp) { this.createdTimestamp = createdTimestamp; }
+
+    public String getUsername() { return username; }
+    public void setUsername(String username) { this.username = username; }
+
+    public boolean getEnabled() { return enabled; }
+    public void setEnabled(boolean enabled) { this.enabled = enabled; }
+
+    public boolean getTotp() { return totp; }
+    public void setTotp(boolean totp) { this.totp = totp; }
+
+    public boolean getEmailVerified() { return emailVerified; }
+    public void setEmailVerified(boolean emailVerified) { this.emailVerified = emailVerified; }
+
+    public String getFirstName() { return firstName; }
+    public void setFirstName(String firstName) { this.firstName = firstName; }
+
+    public String getLastName() { return lastName; }
+    public void setLastName(String lastName) { this.lastName = lastName; }
+
+    public List<String> getDisableableCredentialTypes() {
+        return disableableCredentialTypes;
+    }
+    public void setDisableableCredentialTypes(List<String> disableableCredentialTypes) { this.disableableCredentialTypes = disableableCredentialTypes; }
+
+    public List<String> getRequiredActions() {
+        return requiredActions;
+    }
+    public void setRequiredActions(List<String> requiredActions) { this.requiredActions = requiredActions; }
+
+    public KeyCloakUserAccess getAccess() { return access; }
+    public void setAccess(KeyCloakUserAccess access) { this.access = access; }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public boolean isTotp() {
+        return totp;
+    }
+
+    public boolean isEmailVerified() {
+        return emailVerified;
+    }
+
+    public List<String> getRealmRoles() {
+        return realmRoles;
+    }
+
+    public void setRealmRoles(List<String> realmRoles) {
+        this.realmRoles = realmRoles;
+    }
+
+    public Map<String, List<String>> getClientRoles() {
+        return clientRoles;
+    }
+
+    public void setClientRoles(Map<String, List<String>> clientRoles) {
+        this.clientRoles = clientRoles;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java
new file mode 100644
index 0000000..26020c3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java
@@ -0,0 +1,20 @@
+package org.eclipse.openk.portal.auth2.model;
+
+public class KeyCloakUserAccess {
+    private boolean manageGroupMembership;
+    private boolean view;
+    private boolean mapRoles;
+    private boolean impersonate;
+    private boolean manage;
+
+    public boolean getManageGroupMembership() { return manageGroupMembership; }
+    public void setManageGroupMembership(boolean manageGroupMembership) { this.manageGroupMembership = manageGroupMembership; }
+    public boolean getView() { return view; }
+    public void setView(boolean view) { this.view = view; }
+    public boolean getMapRoles() { return mapRoles; }
+    public void setMapRoles(boolean mapRoles) { this.mapRoles = mapRoles; }
+    public boolean getImpersonate() { return impersonate; }
+    public void setImpersonate(boolean impersonate) { this.impersonate = impersonate; }
+    public boolean getManage() { return manage; }
+    public void setManage(boolean manage) { this.manage = manage; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java b/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java
new file mode 100644
index 0000000..48e4855
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java
@@ -0,0 +1,180 @@
+package org.eclipse.openk.portal.auth2.util;
+
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.openk.portal.auth2.model.JwtHeader;
+import org.eclipse.openk.portal.auth2.model.JwtPayload;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Type;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Base64;
+import java.util.List;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+
+public class JwtHelper {
+
+  private static final Logger logger = Logger.getLogger(JwtHelper.class.getName());
+
+  private JwtHelper() {
+  }
+
+  public static JwtToken login(String user, String password) throws PortalInternalServerError {
+    String token = sendPost(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" +
+            BackendConfig.getInstance().getKeycloakRealm() + "/protocol/openid-connect/token",
+        "username=" + user + "&password=" + password + "&client_id=" + BackendConfig.getInstance().getKeycloakClient() + "&grant_type=password");
+    return getJwtTokenFromJson(token);
+  }
+
+  public static List<KeyCloakUser> getUsers(JwtToken jwtToken) throws PortalInternalServerError {
+    String users = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users",
+        MediaType.APPLICATION_JSON, jwtToken.getAccessToken());
+    return getUserListFromJson(users);
+  }
+
+  public static List<KeyCloakRole> getRolesForUser(JwtToken jwtToken, String id) throws PortalInternalServerError {
+    String roles = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users/" + id + "/role-mappings/realm",
+        MediaType.APPLICATION_JSON, jwtToken.getAccessToken());
+    return getRolesListFromJson(roles);
+  }
+
+  public static JwtHeader getJwtHeaderFromJson(String json) {
+    return JsonGeneratorBase.getGson().fromJson(json, JwtHeader.class);
+  }
+
+  public static JwtPayload getJwtPayloadFromJson(String json) {
+    return JsonGeneratorBase.getGson().fromJson(json, JwtPayload.class);
+  }
+
+  public static JwtToken getJwtTokenFromJson(String json) {
+    return JsonGeneratorBase.getGson().fromJson(json, JwtToken.class);
+  }
+
+  public static List<KeyCloakUser> getUserListFromJson(String json) throws PortalInternalServerError {
+    try {
+      Type listType = new TypeToken<List<KeyCloakUser>>() {
+      }.getType();
+      return JsonGeneratorBase.getGson().fromJson(json, listType);
+    } catch (JsonSyntaxException ex) {
+      logger.error("Error in getUserListFromJson", ex);
+      throw new PortalInternalServerError("JsonSyntaxException");
+    }
+  }
+
+  public static List<KeyCloakRole> getRolesListFromJson(String json) throws PortalInternalServerError {
+    try {
+      Type listType = new TypeToken<List<KeyCloakRole>>() {
+      }.getType();
+      return JsonGeneratorBase.getGson().fromJson(json, listType);
+    } catch (JsonSyntaxException ex) {
+      logger.error("Error in getRolesListFromJson", ex);
+      throw new PortalInternalServerError("JsonSyntaxException");
+    }
+  }
+
+  public static JwtPayload getPayLoad(JwtToken token) {
+    String[] parts = token.getAccessToken().split("[.]");
+
+    //parts[0] is the jwtHeader
+    String jwtPayload = parts[1];
+    //parts[2] is the jwtVerifySignature
+
+    // decode
+    byte[] decoded = Base64.getDecoder().decode(jwtPayload);
+    jwtPayload = new String(decoded, StandardCharsets.UTF_8);
+    logger.info(jwtPayload);
+    return getJwtPayloadFromJson(jwtPayload);
+  }
+
+  private static HttpURLConnection getHttpConnection(String targetUrl) throws PortalInternalServerError {
+    try {
+      URL url = new URL(targetUrl);
+      return (HttpURLConnection) url.openConnection();
+    } catch (IOException e) {
+      logger.error(e);
+      throw new PortalInternalServerError("HttpURLConnection IOException");
+    }
+  }
+
+  private static String sendGet(String targetUrl, String accept, String token) throws PortalInternalServerError {
+    logger.info("sendGet");
+
+    HttpURLConnection con = getHttpConnection(targetUrl);
+    StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
+
+    try (AutoCloseable conc = con::disconnect) {
+      con.setRequestMethod("GET");
+      con.setRequestProperty("Accept", accept);
+      con.setInstanceFollowRedirects(false);
+      if (token != null) // is authenticated
+      {
+        con.setRequestProperty("Authorization", "Bearer " + token);
+      }
+      InputStream is = con.getInputStream();
+      try (BufferedReader rd = new BufferedReader(new InputStreamReader(is))) {
+        String line;
+        while ((line = rd.readLine()) != null) {
+          response.append(line);
+          response.append('\r');
+          logger.info("Got line -> " + line);
+        }
+      }
+      logger.info("sendGet was successful");
+      return response.toString();
+    } catch (Exception e) {
+      logger.error("Error occured in sendGet: " + e);
+      return null;
+    }
+  }
+
+  private static String sendPost(String targetUrl, String urlParameters) throws PortalInternalServerError {
+    logger.info("sendPost");
+
+    HttpURLConnection con = getHttpConnection(targetUrl);
+    StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
+
+    try (AutoCloseable conc = con::disconnect) {
+      con.setRequestMethod("POST");
+      con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
+      con.setRequestProperty("Accept", MediaType.APPLICATION_JSON);
+      con.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length));
+      con.setInstanceFollowRedirects(false);
+      con.setDoOutput(true);
+      // Send request
+      try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
+        wr.writeBytes(urlParameters);
+      }
+      // Get Response
+      InputStream is = con.getInputStream();
+
+      try (BufferedReader rd = new BufferedReader(new InputStreamReader(is))) {
+        String line;
+        while ((line = rd.readLine()) != null) {
+          response.append(line);
+          response.append('\r');
+        }
+      }
+
+      return response.toString();
+    } catch (Exception e) {
+      logger.error("Error occured in sendPost: " + e);
+      return null;
+    }
+  }
+
+  public static String formatToken(String accessToken) {
+    return accessToken != null ? accessToken.replace("Bearer", "").trim() : "";
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java b/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java
new file mode 100644
index 0000000..eec4219
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java
@@ -0,0 +1,65 @@
+package org.eclipse.openk.portal.common;
+
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+
+public class BackendConfig {
+    private static String configFileName = "backendConfigDevLocal.json";
+    private Integer internalSessionLengthMillis;
+    private Integer reloadUsersInSec;
+    private String authServerUrl;
+    private String keycloakRealm;
+    private String keycloakClient;
+    private String keycloakAdmin;
+    private String keycloakPW;
+
+    private static BackendConfig instance;
+
+    private BackendConfig() {}
+
+    public static synchronized BackendConfig getInstance() {
+        if (instance == null) {
+            String jsonConfig = loadJsonConfig();
+            instance = JsonGeneratorBase.getGson().fromJson(jsonConfig, BackendConfig.class);
+        }
+
+        return instance;
+    }
+
+    private static String loadJsonConfig() {
+        ResourceLoaderBase resourceLoaderBase = new ResourceLoaderBase();
+        return resourceLoaderBase.loadStringFromResource(configFileName);
+    }
+
+    public Integer getInternalSessionLengthMillis() { return internalSessionLengthMillis; }
+
+    public Integer getReloadUsersInSec() { return reloadUsersInSec; }
+
+    public String getAuthServerUrl() {
+        return authServerUrl;
+    }
+
+    public String getKeycloakClient() {
+        return keycloakClient;
+    }
+
+    public String getKeycloakAdmin() {
+        return keycloakAdmin;
+    }
+
+    public String getKeycloakPW() {
+        return keycloakPW;
+    }
+
+    public String getKeycloakRealm() {
+        return keycloakRealm;
+    }
+
+
+    public static String getConfigFileName() {
+        return configFileName;
+    }
+
+    public static void setConfigFileName(String configFileName) {
+        BackendConfig.configFileName = configFileName;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/Globals.java b/src/main/java/org/eclipse/openk/portal/common/Globals.java
new file mode 100644
index 0000000..db79c17
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/Globals.java
@@ -0,0 +1,41 @@
+package org.eclipse.openk.portal.common;
+
+
+public final class Globals {
+    public static final String OK_STRING = "OK";
+    public static final String SESSION_TOKEN_TAG = "X-XSRF-TOKEN";
+    public static final String SESSION_COOKIE_TOKEN_TAG = "COOKIESESSION-TOKEN";
+    public static final int MAX_CREDENTIALS_LENGTH = 500;
+    public static final int MAX_NOTIFICATION_LENGTH = 16384;
+
+    public static final int HTTPSTATUS_OK = 200;
+    public static final int HTTPSTATUS_BAD_REQUEST = 400;
+    public static final int HTTPSTATUS_UNAUTHORIZED = 401;
+    public static final int HTTPSTATUS_FORBIDDEN = 403;
+    public static final int HTTPSTATUS_NOT_FOUND = 404;
+    public static final int HTTPSTATUS_GONE = 410;
+    public static final int HTTPSTATUS_LOCKED = 423;
+    public static final int HTTPSTATUS_INTERNAL_SERVER_ERROR = 500;
+    public static final int HTTPSTATUS_NOT_AVAILABLE = 503;
+    public static final int HTTPSTATUS_POLICY_NOT_FULFILLED = 420;
+    public static final int HTTPSTATUS_CONFLICT = 409;
+    public static final int HTTPSTATUS_DECISION = 900;
+
+    //For Branches: for later use in a configurable json
+    public static final String ELECTRICITY_MARK = "S";
+    public static final String GAS_MARK = "G";
+    public static final String DISTRICT_HEAT_MARK = "F";
+    public static final String WATER_MARK = "W";
+
+    //Errormessage
+    public static final String DATA_OUTDATED = "Data is outdated!";
+
+    //Suggestion: An input field on search mask as better solution? Can only be adapted by code changes.
+    public static final int FAST_SEARCH_NUMBER_OF_DAYS_BACK = -200;
+
+    //KeyCloak configuration
+    public static final String KEYCLOAK_AUTH_TAG = "Authorization";
+
+    private Globals() {}
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java b/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java
new file mode 100644
index 0000000..e049bc6
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java
@@ -0,0 +1,40 @@
+package org.eclipse.openk.portal.common;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Type;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class GsonUTCDateAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
+
+    private final DateFormat dateFormat;
+
+    public GsonUTCDateAdapter() {
+        dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);      //This is the format I need
+        dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));                               //This is the key line which converts the date to UTC which cannot be accessed with the default serializer
+    }
+
+    @Override
+    public synchronized JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
+        return new JsonPrimitive(dateFormat.format(date));
+    }
+
+    @Override
+    public synchronized Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) {
+        try {
+            return dateFormat.parse(jsonElement.getAsString());
+        } catch (ParseException e) {
+            throw new JsonParseException(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java b/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java
new file mode 100644
index 0000000..74a2249
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java
@@ -0,0 +1,50 @@
+package org.eclipse.openk.portal.common;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+public class InitBackendConfig extends HttpServlet {
+
+    private static final long serialVersionUID = -7882117179312471533L;
+
+    private static final Logger LOGGER = Logger.getLogger(InitBackendConfig.class.getName());
+
+    @Override
+    public void init() throws ServletException {
+        String environment = getServletContext().getInitParameter("OK_PORTAL_ENVIRONMENT");
+        setConfigFiles(environment);
+    }
+
+    private void setConfigFiles(String environment ) {
+        String env = (environment == null ? "Production": environment);
+
+        String backendConfigFile;
+        String moduleConfigFile;
+        switch (env){
+            case "DevLocal":
+                backendConfigFile="backendConfigDevLocal.json";
+                moduleConfigFile="moduleConfigDevLocal.json";
+                break;
+            case "DevServer":
+                backendConfigFile="backendConfigDevServer.json";
+                moduleConfigFile="moduleConfigDevServer.json";
+                break;
+            case "Custom":
+                backendConfigFile="backendConfigCustom.json";
+                moduleConfigFile="moduleConfigCustom.json";
+                break;
+            default:
+                backendConfigFile="backendConfigProduction.json";
+                moduleConfigFile="moduleConfigProduction.json";
+        }
+
+        BackendConfig.setConfigFileName(backendConfigFile);
+        UserModule.setConfigFileName(moduleConfigFile);
+        LOGGER.info("Portal backendendenviroment is: " +environment+ ". Setting backendConfig accordingly to: "+ backendConfigFile);
+        LOGGER.info("Portal backendendenviroment is: " +environment+ ". Setting moduleConfig accordingly to: "+ moduleConfigFile);
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java b/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java
new file mode 100644
index 0000000..b98dba7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java
@@ -0,0 +1,23 @@
+package org.eclipse.openk.portal.common;
+
+import java.util.Timer;
+import java.util.TimerTask;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import org.apache.log4j.Logger;
+
+public class InitUserCacheJob extends HttpServlet {
+
+    private static final long serialVersionUID = 8671326157376987023L;
+
+    private static final Logger LOGGER = Logger.getLogger(InitUserCacheJob.class.getName());
+
+
+    @Override
+    public void init() throws ServletException {
+        LOGGER.info("InitUserCacheJob called");
+        TimerTask timerTask = new UserCacheTimerTask();
+        Timer timer = new Timer();
+        timer.scheduleAtFixedRate(timerTask, 500, BackendConfig.getInstance().getReloadUsersInSec()*1000L);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java b/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java
new file mode 100644
index 0000000..70d21cc
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java
@@ -0,0 +1,15 @@
+package org.eclipse.openk.portal.common;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.util.Date;
+
+public class JsonGeneratorBase {
+    private JsonGeneratorBase() {}
+    public static Gson getGson() {
+        return new GsonBuilder()
+                .registerTypeAdapter(Date.class, new GsonUTCDateAdapter())
+                .disableHtmlEscaping()
+                .create();
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java b/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java
new file mode 100644
index 0000000..abaf567
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java
@@ -0,0 +1,51 @@
+package org.eclipse.openk.portal.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimerTask;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.controller.TokenManager;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+
+public class UserCacheTimerTask extends TimerTask {
+
+  private static final Logger LOGGER = Logger.getLogger(TokenManager.class.getName());
+
+  @Override
+  public void run() {
+    LOGGER.debug("UserCacheTimerTask started");
+    try {
+      JwtToken token = JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW());
+
+      List<KeyCloakUser> allUsersWithRoles = getKeyCloakUsersFromToken(token);
+
+      UserCache.getInstance().setKeyCloakUsers(allUsersWithRoles);
+
+    } catch (PortalInternalServerError portalInternalServerError) {
+      LOGGER.error(portalInternalServerError);
+    }
+
+    LOGGER.debug("UserCacheTimerTask finished");
+  }
+
+  private List<KeyCloakUser> getKeyCloakUsersFromToken(JwtToken token) throws PortalInternalServerError {
+    List<KeyCloakUser> allUsers = JwtHelper.getUsers(token);
+    List<KeyCloakUser> allUsersWithRoles = new ArrayList<>();
+
+    for (KeyCloakUser user : allUsers) {
+      List<String> rolesList = new ArrayList<>();
+      List<KeyCloakRole> rolesForUser = JwtHelper.getRolesForUser(token, user.getId());
+      for (KeyCloakRole keyCloakRole : rolesForUser) {
+        rolesList.add(keyCloakRole.getName());
+      }
+      user.setRealmRoles(rolesList);
+      allUsersWithRoles.add(user);
+    }
+    return allUsersWithRoles;
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java b/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java
new file mode 100644
index 0000000..b562e01
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java
@@ -0,0 +1,21 @@
+package org.eclipse.openk.portal.common.util;
+
+import java.security.MessageDigest;
+import org.apache.commons.codec.binary.Hex;
+
+public final class HashingAlgo {
+    private HashingAlgo() {}
+
+    public static String hashIt(String pwdClear) {
+        MessageDigest cript;
+        try {
+            cript = MessageDigest.getInstance("SHA-1");
+            cript.reset();
+            cript.update(pwdClear.getBytes("utf8"));
+            return new String(Hex.encodeHex(cript.digest()));
+
+        } catch (Exception e) { //NOSONAR
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java b/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java
new file mode 100644
index 0000000..68098ad
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java
@@ -0,0 +1,71 @@
+package org.eclipse.openk.portal.common.util;
+
+import java.io.IOException;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.log4j.Appender;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Layout;
+import org.apache.log4j.Level;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.net.SyslogAppender;
+import org.apache.log4j.spi.RootLogger;
+import org.apache.log4j.xml.DOMConfigurator;
+
+/**
+ * <b>LoggerConfig</b><br>
+ * Logging Implementierung
+ */
+public final class LoggerUtil extends HttpServlet {
+    /**
+     * serialVersionUID.
+     */
+    private static final long serialVersionUID = 1L;
+
+    /*
+     * (non-Javadoc)
+     * @see javax.servlet.GenericServlet#init()
+     */
+    @Override
+    public void init() {
+        final ServletContext context = getServletContext();
+
+        if (Boolean.valueOf(context.getInitParameter("param.syslog.use"))) {
+            // configure for syslog using parameters specified in configuration descriptor
+            BasicConfigurator.resetConfiguration();
+
+            final String level = context.getInitParameter("param.syslog.level");
+            RootLogger.getRootLogger().setLevel(Level.toLevel(level));
+
+            final String host = context.getInitParameter("param.syslog.host");
+            final String facility = context.getInitParameter("param.syslog.facility");
+            final Layout layout = new PatternLayout("[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n");
+            final Appender syslogAppender = new SyslogAppender(layout, host,
+                    SyslogAppender.getFacility(facility));
+            BasicConfigurator.configure(syslogAppender);
+
+        } else {
+            // configure using parameters specified in xml file
+            final String prefix = context.getRealPath("/");
+            final String file = getInitParameter("log4j-init-file");
+
+            if (prefix != null && file != null) {
+                DOMConfigurator.configure(prefix + file);
+            }
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
+     * javax.servlet.http.HttpServletResponse)
+     */
+    @Override
+    protected void doGet(final HttpServletRequest req, final HttpServletResponse resp)
+            throws ServletException, IOException {
+        // Nothing done on purpose.
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java b/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java
new file mode 100644
index 0000000..2ace7b3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java
@@ -0,0 +1,25 @@
+package org.eclipse.openk.portal.common.util;
+
+import java.io.InputStream;
+import java.io.StringWriter;
+import org.apache.commons.io.IOUtils;
+
+public class ResourceLoaderBase {
+    private String stream2String(InputStream is) {
+        StringWriter writer = new StringWriter();
+        try {
+            IOUtils.copy(is, writer, "UTF-8");
+        } catch (Exception e) { // NOSONAR
+            return "";
+        }
+        return writer.toString();
+
+
+    }
+
+    public String loadStringFromResource(String filename) {
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        InputStream jsonstream = classLoader.getResourceAsStream(filename);
+        return stream2String(jsonstream);
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/BackendController.java b/src/main/java/org/eclipse/openk/portal/controller/BackendController.java
new file mode 100644
index 0000000..ad3ddfe
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BackendController.java
@@ -0,0 +1,110 @@
+
+package org.eclipse.openk.portal.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.LoginCredentials;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BackendController {
+    private static final Logger LOGGER = Logger.getLogger(BackendController.class.getName());
+    private final InputDataValuator inputDataValuator = new InputDataValuator();
+
+    public List<KeyCloakUser> getUsers() throws PortalInternalServerError {
+        JwtToken token = JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(),
+            BackendConfig.getInstance().getKeycloakPW());
+        return JwtHelper.getUsers(token);
+    }
+
+    public List<KeyCloakUser> getUsersForRole(String roleToCheck) {
+        List<KeyCloakUser> usersWithRole = new ArrayList<>();
+        List<KeyCloakUser> keyCloakUsers = UserCache.getInstance().getKeyCloakUsers();
+
+        for (KeyCloakUser user : keyCloakUsers) {
+            List<String> realmRoles = user.getRealmRoles();
+            if (realmRoles ==  null) {
+                continue;
+            }
+
+            for (String realmRole : realmRoles) {
+                if(realmRole.equals(roleToCheck)){
+                    usersWithRole.add(user);
+                    break;
+                }
+            }
+        }
+
+        return usersWithRole;
+    }
+
+
+    public JwtToken authenticate(String credentials) throws PortalException {
+        LOGGER.info("authenticate() is called");
+
+        // valuator will throw an exception if not valid
+        inputDataValuator.checkCredentials(credentials);
+
+        LoginCredentials loginCredentials = JsonGeneratorBase.getGson().fromJson(credentials, LoginCredentials.class);
+
+        JwtToken token = null;
+        String inputUsername = loginCredentials.getUserName().toLowerCase();
+        String inputPassword = loginCredentials.getPassword();
+
+        // obtain a token from keycloak
+        token = JwtHelper.login(inputUsername, inputPassword);
+
+        if( token == null ) {
+            LOGGER.debug(credentials);
+            throw new PortalUnauthorized("Unknown User/Password");
+        }
+
+        LOGGER.info("authenticate() succeeded.");
+        return token;
+    }
+
+    public VersionInfo getVersionInfo() {
+        LOGGER.info("getVersionInfo() is called");
+
+        String version = getClass().getPackage().getImplementationVersion();
+        VersionInfo vi = new VersionInfo();
+        vi.setBackendVersion(version);
+
+        LOGGER.info("getVersionInfo() is finished");
+        return vi;
+    }
+
+    public List<UserModule> getUserModuleList() {
+        LOGGER.info("getUserModuleList() is called");
+        List<UserModule> umList = new ArrayList<>();
+
+        for (int i=0; i<UserModule.getInstance().length; i++)
+        {
+            UserModule um = new UserModule();
+            um.setModuleName(UserModule.getInstance()[i].getModuleName());
+            um.setCols(UserModule.getInstance()[i].getCols());
+            um.setRows(UserModule.getInstance()[i].getRows());
+            um.setColor(UserModule.getInstance()[i].getColor());
+            um.setLink(UserModule.getInstance()[i].getLink());
+            um.setPictureLink(UserModule.getInstance()[i].getPictureLink());
+            um.setRequiredRole(UserModule.getInstance()[i].getRequiredRole());
+
+            umList.add(um);
+        }
+
+        LOGGER.info("getUserModuleList() is finished");
+        return umList;
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java b/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java
new file mode 100644
index 0000000..5ac8a63
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java
@@ -0,0 +1,28 @@
+package org.eclipse.openk.portal.controller;
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.exceptions.PortalException;
+
+
+public abstract class BackendInvokable {
+
+  private String modUser;
+  private int userId;
+
+  public int getUserId() {
+    return userId;
+  }
+
+  public void setUserId(int userId) {
+    this.userId = userId;
+  }
+
+  public String getModUser() {
+    return modUser;
+  }
+
+  public void setModUser(String modUser) {
+    this.modUser = modUser;
+  }
+
+  public abstract Response invoke() throws PortalException;
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java b/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java
new file mode 100644
index 0000000..cb027f0
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java
@@ -0,0 +1,67 @@
+package org.eclipse.openk.portal.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.ws.rs.core.Response;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalExceptionMapper;
+
+public abstract class BaseWebService {
+    private final Map<String, Long> currentTimeMeasures = new HashMap<>();
+    private final Logger logger;
+
+    public BaseWebService(Logger logger) {
+        this.logger = logger;
+    }
+
+    protected abstract void assertAndRefreshToken(String token, boolean refresh) throws PortalException;
+
+    private void startProcessing(String methodName) {
+        Long lStartingTime = System.currentTimeMillis();
+        String lookupName = buildLookupId(methodName);
+        currentTimeMeasures.put(lookupName, lStartingTime);
+
+        logger.info(this.getClass().getName() + "." + lookupName + ": Start processing...");
+    }
+
+    protected AutoCloseable perform(final String methodName) {
+        startProcessing(methodName);
+        return () -> endProcessing(methodName);
+    }
+
+    private String buildLookupId(String func) {
+        return func + "@@" + Thread.currentThread().getId();
+    }
+
+    private void endProcessing(String methodName) {
+        String lookupName = buildLookupId(methodName);
+        if (currentTimeMeasures.containsKey(lookupName)) {
+            Long lStartingTime = currentTimeMeasures.get(lookupName);
+            currentTimeMeasures.remove(lookupName);
+
+            logger.info(this.getClass().getName() + "." + lookupName + ": Finished processing in " + (System.currentTimeMillis() - lStartingTime) + " ms");
+        }
+
+    }
+
+    protected Response invoke(String sessionId, boolean refresh, BackendInvokable invokable)
+    {
+        try (AutoCloseable ignored = perform(invokable.getClass().getName() + ".Invoke()")) { // NOSONAR
+
+            assertAndRefreshToken(sessionId, refresh);
+
+            return invokable.invoke();
+        } catch (PortalException bee) {
+            logger.info("Caught BackendException: " + bee.getClass().getSimpleName());
+            return Response.status(bee.getHttpStatus()).entity(PortalExceptionMapper.toJson(bee))
+                    .build();
+
+        } catch (Exception e) {
+            logger.error("Unexpected exception", e);
+            return Response.status(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR).build();
+        }
+
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java b/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java
new file mode 100644
index 0000000..5618c0a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java
@@ -0,0 +1,102 @@
+package org.eclipse.openk.portal.controller;
+
+
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalExceptionMapper;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+
+public class ControllerImplementations
+{
+    private ControllerImplementations() {}
+
+    public static class GetUsers extends BackendInvokable {
+
+        public GetUsers() {}
+
+        @Override
+        public Response invoke() throws PortalException {
+            List<KeyCloakUser> keyCloakUserList = UserCache.getInstance().getKeyCloakUsers();
+            return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(keyCloakUserList));
+        }
+    }
+
+    public static class GetVersionInfo extends BackendInvokable {
+        private BackendController backendController;
+        
+        public GetVersionInfo(BackendController backendController) {
+            this.backendController = backendController;
+        }
+        
+        @Override
+        public Response invoke() throws PortalException {
+            VersionInfo vi = backendController.getVersionInfo();
+            return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(vi));
+        }
+    }
+
+    public static class Logout extends BackendInvokable {
+        private String accessToken;
+
+        public Logout(String accessToken) {
+            this.accessToken = accessToken;
+        }
+
+        @Override
+        public Response invoke() throws PortalException {
+            TokenManager.getInstance().logout(accessToken);
+            return ResponseBuilderWrapper.INSTANCE.buildOKResponse(PortalExceptionMapper.getGeneralOKJson());
+        }
+    }
+
+    public static class CheckAuth extends BackendInvokable {
+
+        public CheckAuth() {
+            /* the implemented invoke method is only called after a successfully
+            pass of assertAndRefreshToken method of the BaseWebService class which checks
+            if the Token is active and valid */
+        }
+
+        @Override
+        public Response invoke() throws PortalException {
+		        //see constructor above
+		        return ResponseBuilderWrapper.INSTANCE.buildOKResponse(PortalExceptionMapper.getGeneralOKJson());
+        }
+    }
+
+    public static class GetUserModulesForUser extends BackendInvokable {
+        private BackendController backendController;
+
+        public GetUserModulesForUser(BackendController backendController) {
+            this.backendController = backendController;
+        }
+
+        @Override
+        public Response invoke() throws PortalException {
+            List<UserModule> um = backendController.getUserModuleList();
+            return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(um));
+        }
+    }
+
+    public static class GetUsersForRole extends BackendInvokable {
+        private BackendController backendController;
+        private String userRole;
+
+        public GetUsersForRole(BackendController backendController, String userRole) {
+            this.backendController = backendController;
+            this.userRole = userRole;
+        }
+
+        @Override
+        public Response invoke() throws PortalException {
+            List<KeyCloakUser> keyCloakUserList = backendController.getUsersForRole(userRole);
+            return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(keyCloakUserList));
+        }
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java b/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java
new file mode 100644
index 0000000..3a15df5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java
@@ -0,0 +1,58 @@
+package org.eclipse.openk.portal.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalBadRequest;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.LoginCredentials;
+
+public class InputDataValuator {
+    private static final Logger LOGGER = Logger.getLogger(InputDataValuator.class.getName());
+
+    private static final String WHITELIST = "[^a-zA-ZäÄöÖüÜß?0-9().,-:;_+=!%§&/'#<>\" ]";
+
+    private void checkCredentialsRaw(String credentials) throws PortalUnauthorized {
+        if (credentials == null || credentials.isEmpty()) {
+            throw new PortalUnauthorized("No credentials provided");
+        }
+        if (credentials.length() > Globals.MAX_CREDENTIALS_LENGTH) {
+            LOGGER.warn("MaxLength of credentials exceeded");
+
+            throw new PortalUnauthorized("Invalid credentials");
+        }
+    }
+
+    public void checkCredentials(String credentials) throws PortalUnauthorized {
+        checkCredentialsRaw(credentials);
+
+        LoginCredentials obj;
+        try {
+            obj = JsonGeneratorBase.getGson().fromJson(credentials, LoginCredentials.class);
+            checkWhitelistChars(obj.getPassword());
+            checkWhitelistChars(obj.getPassword());
+        } catch (Exception e) { // NOSONAR
+            obj = null;
+        }
+        if (obj == null || obj.getUserName() == null || obj.getUserName().isEmpty()) {
+            LOGGER.warn("Invalid credentials provided. ");
+            throw new PortalUnauthorized("Invalid credentials");
+        }
+    }
+
+    private void checkWhitelistChars(String txt) throws PortalBadRequest {
+        checkWhitelistChars(txt, false);
+    }
+
+    private void checkWhitelistChars(String txt, boolean logTextOnError) throws PortalBadRequest {
+        // empty String is ok
+        if (txt == null || txt.isEmpty()) {
+            return;
+        }
+        String tx2 = txt.replaceAll(WHITELIST, "");
+        if (!tx2.equals(txt)) {
+            LOGGER.warn("Invalid text not matching whitelist" + (logTextOnError ? ":" + txt : ""));
+            throw new PortalBadRequest("Invalid text data");
+        }
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java b/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java
new file mode 100644
index 0000000..2cb66ae
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java
@@ -0,0 +1,49 @@
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+
+import javax.ws.rs.core.Response;
+import java.io.UnsupportedEncodingException;
+
+public enum ResponseBuilderWrapper {
+    INSTANCE;
+
+    public Response.ResponseBuilder getResponseBuilder( String json ) throws PortalInternalServerError {
+        return getResponseBuilder(jsonStringToBytes( json ));
+
+    }
+
+    private Response.ResponseBuilder getResponseBuilder(byte[] json) {
+        return Response.status(Globals.HTTPSTATUS_OK).entity(json)
+                .header("Content-Type", "application/json; charset=utf-8")
+                .header("X-XSS-Protection", "1; mode = block")
+                .header("X-DNS-Prefetch-Control", "off")
+                .header("X-Content-Type-Options", "nosniff")
+                .header("X-Frame-Options", "sameorigin")
+                .header("Strict-Transport-Security", "max-age=15768000; includeSubDomains")
+                .header("Cache-Control", "no-cache; no-store; must-revalidate")
+                .header("Pragma", "no-cache")
+                .header("Expires", "0")
+                .header("Access-Control-Allow-Origin", "*");
+    }
+
+    private byte[] jsonStringToBytes( String jsonString ) throws PortalInternalServerError {
+        try {
+            return jsonString.getBytes("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new PortalInternalServerError("Unexpected Error", e);
+        }
+    }
+
+    public Response buildOKResponse(String jsonString) throws PortalException {
+        return getResponseBuilder( jsonStringToBytes( jsonString)).build();
+    }
+
+
+    public Response buildOKResponse(String jsonString, String sessionToken) throws PortalException {
+        return getResponseBuilder(jsonStringToBytes(jsonString)).header(Globals.SESSION_TOKEN_TAG, sessionToken).build();
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java b/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java
new file mode 100644
index 0000000..6d9d68a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java
@@ -0,0 +1,136 @@
+package org.eclipse.openk.portal.controller;
+
+
+import org.eclipse.openk.portal.auth2.model.JwtPayload;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import java.util.HashMap;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.UserAuthentication;
+
+public class TokenManager {
+    private static final Logger LOGGER = Logger.getLogger(TokenManager.class.getName());
+
+    private static long internalSessionLengthOffsetPerc = 0L;
+
+    public static class SessionItem {
+        private long sessionCreationTime;
+        private long sessionLastAccessTime;
+
+        private String sessionId;
+        private String cookieToken;
+        private UserAuthentication user;
+        private JwtToken jwtToken;
+
+        public SessionItem(long sessionCreationTime) {
+            this.sessionCreationTime = this.sessionLastAccessTime = sessionCreationTime;
+        }
+
+        public long getSessionCreationTime() {
+            return sessionCreationTime;
+        }
+
+        public void setSessionCreationTime(long sessionCreationTime) {
+            this.sessionCreationTime = sessionCreationTime;
+        }
+
+        public long getSessionLastAccessTime() {
+            return sessionLastAccessTime;
+        }
+
+        public void setSessionLastAccessTime(long sessionLastAccessTime) {
+            this.sessionLastAccessTime = sessionLastAccessTime;
+        }
+
+        public UserAuthentication getUser() {
+            return user;
+        }
+
+        public void setUser(UserAuthentication user) {
+            this.user = user;
+        }
+
+        public JwtToken getJwtToken() {
+            return jwtToken;
+        }
+
+        public void setJwtToken(JwtToken jwtToken) {
+            this.jwtToken = jwtToken;
+        }
+
+        public String getSessionId() {
+            return sessionId;
+        }
+
+        public void setSessionId(String sessionId) {
+            this.sessionId = sessionId;
+        }
+
+        public String getCookieToken() {
+            return cookieToken;
+        }
+
+        public void setCookieToken(String cookieToken) {
+            this.cookieToken = cookieToken;
+        }
+    }
+
+    private static final TokenManager INSTANCE = new TokenManager();
+    private final HashMap<String, SessionItem> registry = new HashMap<>();
+
+    private TokenManager() {
+    }
+
+    public static TokenManager getInstance() {
+        return INSTANCE;
+    }
+
+    public void registerNewSession(JwtToken jwtToken) {
+
+        String guid = jwtToken.getAccessToken();
+        SessionItem sitem = new SessionItem(System.currentTimeMillis());
+        sitem.setJwtToken(jwtToken);
+        sitem.setSessionId(guid);
+
+        LOGGER.debug("Registered Session with JWT: " + JsonGeneratorBase.getGson().toJson(jwtToken));
+        registry.put(guid, sitem);
+    }
+
+
+    private boolean sessionHasExpired(long now, SessionItem sitem) {
+        return (now - sitem.getSessionLastAccessTime()) >
+                BackendConfig.getInstance().getInternalSessionLengthMillis() * (1 + (internalSessionLengthOffsetPerc / 100L));
+    }
+
+    public void refreshSessionIsAlive(String token, boolean refresh) throws PortalUnauthorized {
+        String accesstoken = JwtHelper.formatToken(token);
+        SessionItem sitem = registry.get(accesstoken);
+        long now = System.currentTimeMillis();
+
+        if (sitem == null || sessionHasExpired(now, sitem)) {
+            if (sitem != null) {
+                JwtPayload payLoad = JwtHelper.getPayLoad(sitem.getJwtToken());
+                String user = (payLoad != null ? payLoad.getPreferredUsername() : null);
+                LOGGER.info("Session expired for User " + user);
+            }
+            registry.remove(token); // we're done
+            LOGGER.info("Invalid Token: " + token);
+            throw new PortalUnauthorized("Invalid Token");
+        }
+
+        if (refresh) {
+            sitem.setSessionLastAccessTime(now);
+        }
+    }
+
+    public void logout(String token) {
+        String accesstoken = JwtHelper.formatToken(token);
+        if (registry.containsKey(accesstoken)) {
+            registry.remove(accesstoken);
+        }
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java
new file mode 100644
index 0000000..8a59acf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java
@@ -0,0 +1,18 @@
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalBadRequest extends PortalException {
+    public PortalBadRequest() {
+        super();
+    }
+
+    public PortalBadRequest(String message) {
+        super(message);
+    }
+
+    @Override
+    public int getHttpStatus() {
+        return Globals.HTTPSTATUS_BAD_REQUEST;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java
new file mode 100644
index 0000000..4c88114
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java
@@ -0,0 +1,17 @@
+package org.eclipse.openk.portal.exceptions;
+
+public abstract class PortalException extends Exception { // NOSONAR
+    public PortalException() {
+        super();
+    }
+
+    public PortalException(String message) {
+        super(message);
+    }
+
+    public PortalException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+
+    public abstract int getHttpStatus();
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java
new file mode 100644
index 0000000..c78883a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java
@@ -0,0 +1,32 @@
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.viewmodel.ErrorReturn;
+import org.eclipse.openk.portal.viewmodel.GeneralReturnItem;
+
+public final class PortalExceptionMapper {
+    private PortalExceptionMapper() {}
+
+    public static String unknownErrorToJson() {
+        ErrorReturn er = new ErrorReturn();
+        er.setErrorText("Unknown Error");
+        er.setErrorCode(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR);
+        return JsonGeneratorBase.getGson().toJson(er);
+    }
+
+    public static String toJson(PortalException e) {
+            ErrorReturn er = new ErrorReturn();
+            er.setErrorText(e.getMessage());
+        er.setErrorCode(e.getHttpStatus());
+            return JsonGeneratorBase.getGson().toJson(er);
+    }
+
+    public static String getGeneralErrorJson() {
+        return JsonGeneratorBase.getGson().toJson(new GeneralReturnItem("NOK"));
+    }
+
+    public static String getGeneralOKJson() {
+        return JsonGeneratorBase.getGson().toJson(new GeneralReturnItem("OK"));
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java
new file mode 100644
index 0000000..d43a5df
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java
@@ -0,0 +1,18 @@
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalForbidden extends PortalException {
+    public PortalForbidden() {
+        super();
+    }
+
+    public PortalForbidden(String message) {
+        super(message);
+    }
+
+    @Override
+    public int getHttpStatus() {
+        return Globals.HTTPSTATUS_FORBIDDEN;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java
new file mode 100644
index 0000000..74a1220
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java
@@ -0,0 +1,18 @@
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalInternalServerError extends PortalException {
+    public PortalInternalServerError(String message) {
+        super(message);
+    }
+
+    public PortalInternalServerError(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+
+    @Override
+    public int getHttpStatus() {
+        return Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java
new file mode 100644
index 0000000..4e82e2b
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java
@@ -0,0 +1,18 @@
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalNotFound extends PortalException {
+    public PortalNotFound() {
+        super();
+    }
+
+    public PortalNotFound(String message) {
+        super(message);
+    }
+
+    @Override
+    public int getHttpStatus() {
+        return Globals.HTTPSTATUS_NOT_FOUND;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java
new file mode 100644
index 0000000..d172995
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java
@@ -0,0 +1,18 @@
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalUnauthorized extends PortalException {
+    public PortalUnauthorized() {
+        super();
+    }
+
+    public PortalUnauthorized(String message) {
+        super(message);
+    }
+
+    @Override
+    public int getHttpStatus() {
+        return Globals.HTTPSTATUS_UNAUTHORIZED;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java b/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java
new file mode 100644
index 0000000..f349071
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java
@@ -0,0 +1,158 @@
+package org.eclipse.openk.portal.rest;
+
+import javax.ws.rs.PathParam;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.controller.BackendController;
+import org.eclipse.openk.portal.controller.BaseWebService;
+import org.eclipse.openk.portal.controller.ControllerImplementations;
+import org.eclipse.openk.portal.controller.ResponseBuilderWrapper;
+import org.eclipse.openk.portal.controller.TokenManager;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalExceptionMapper;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+@Path("/beservice")
+public class BackendRestService extends BaseWebService {
+    private static final Logger logger = Logger.getLogger(BackendRestService.class.getName());
+    private static final boolean DEVELOP_MODE;
+    private static final String LET_ME_IN = "LET_ME_IN";
+
+    static {
+        // determine static VersionInfo
+        String versionString = BackendRestService.class.getPackage().getImplementationVersion().toUpperCase();
+        DEVELOP_MODE = versionString.contains("DEVELOP") || versionString.contains("SNAPSHOT");
+    }
+    @Context
+    private UriInfo uriInfo;
+
+    public BackendRestService() {
+        super(logger);
+    }
+
+    @POST
+    @Path("/login")
+    @Produces("application/json")
+    @Consumes("application/json")
+    public Response login(String loginCredentials) {
+
+        try (AutoCloseable ignored = perform("login()")) { // NOSONAR
+            JwtToken jwtToken;
+
+            if (loginCredentials == null || loginCredentials.isEmpty()) {
+                logger.info("Login Error. Empty Credentials");
+                throw new PortalUnauthorized();
+            } else {
+                // will throw exception if it fails
+                jwtToken = new BackendController().authenticate(loginCredentials);
+                TokenManager tokenManager = TokenManager.getInstance();
+                tokenManager.registerNewSession(jwtToken);
+                logger.info("Login Success");
+            }
+
+            return createJsonResponse(jwtToken);
+        } catch (Exception e) {
+            logger.info("Login Error. Invalid KeyCloak Credentials/Settings");
+            return responseFromException(e);
+        }
+    }
+
+    private Response createJsonResponse(Object obj) throws PortalException {
+        Response.ResponseBuilder rb = ResponseBuilderWrapper.INSTANCE
+            .getResponseBuilder(obj != null ? JsonGeneratorBase.getGson().toJson(obj) : PortalExceptionMapper.getGeneralOKJson());
+
+        return rb.build();
+    }
+
+    @GET
+    @Path("/checkAuth")
+    @Produces("application/json")
+    public Response checkAuth(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+        logger.debug("checkAuth portal called");
+        return invoke(accessToken, true, new ControllerImplementations.CheckAuth());
+    }
+
+    @GET
+    @Path("/logout")
+    @Produces("application/json")
+    public Response logout(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+        return invoke(accessToken, false, new ControllerImplementations.Logout(accessToken));
+    }
+
+    @GET
+    @Path("/versionInfo/")
+    @Produces("application/json")
+    public Response getVersionInfo() {
+        try (AutoCloseable ignored = perform("getVersionInfo()")) { // NOSONAR
+            VersionInfo versionInfo = new BackendController().getVersionInfo();
+            return createJsonResponse(versionInfo);
+        } catch (Exception e) {
+            return responseFromException(e);
+        }
+    }
+
+    @GET
+    @Path("/userModulesForUser/")
+    @Produces("application/json")
+    public Response getUserModulesForUser(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+        return invoke(accessToken, false, new ControllerImplementations.GetUserModulesForUser(new BackendController()));
+    }
+
+    @GET
+    @Path("/usersForRole/{userRole}")
+    @Produces("application/json")
+    public Response getUsersForRole(@PathParam("userRole") String userRole,
+        @HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+        return invoke(accessToken, false, new ControllerImplementations.GetUsersForRole(new BackendController(),userRole));
+    }
+
+    @GET
+    @Path("/users")
+    @Produces("application/json")
+    public Response getUsers(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+        return invoke(accessToken, false, new ControllerImplementations.GetUsers());
+    }
+
+    private boolean isBackdoor( String sessionId ) {
+        // backdoor is only available when the version(POM) contains "DEVELOP" or "SNAPSHOT"
+        return DEVELOP_MODE && LET_ME_IN.equals(sessionId);
+    }
+
+    @Override
+    protected void assertAndRefreshToken(String token, boolean refresh) throws PortalUnauthorized {
+        if (isBackdoor(token)) {
+            return;
+        }
+        TokenManager.getInstance().refreshSessionIsAlive(token, refresh);
+
+    }
+
+    private Response responseFromException(Exception e) {
+        int errcode;
+        String retJson;
+
+        if (e instanceof PortalException) {
+            logger.error("Caught BackendException", e);
+            errcode = ((PortalException) e).getHttpStatus();
+            retJson = PortalExceptionMapper.toJson((PortalException) e);
+            return Response.status(errcode).entity(retJson).build();
+        } else {
+            logger.error("Unexpected exception", e);
+            return Response.status(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR).entity(PortalExceptionMapper.getGeneralErrorJson()).build();
+        }
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java b/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java
new file mode 100644
index 0000000..7914f9c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java
@@ -0,0 +1,18 @@
+package org.eclipse.openk.portal.rest;
+
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class RestServiceConfiguration extends javax.ws.rs.core.Application {
+    public RestServiceConfiguration() {
+        // Standard Contstructor needed
+    }
+
+    @Override
+    public Set<Class<?>> getClasses() {
+        Set<Class<?>> restServicesClasses = new HashSet<>();
+        restServicesClasses.add(BackendRestService.class);
+        return restServicesClasses;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java b/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java
new file mode 100644
index 0000000..0cb403c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java
@@ -0,0 +1,23 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import java.io.Serializable;
+
+public class ErrorReturn implements Serializable {
+
+    private static final long serialVersionUID = -4653198875478337413L;
+    private String errorText;
+    private int errorCode;
+
+    public String getErrorText() {
+        return errorText;
+    }
+    public void setErrorText(String errorText) {
+        this.errorText = errorText;
+    }
+    public int getErrorCode() {
+        return errorCode;
+    }
+    public void setErrorCode(int errorCode) {
+        this.errorCode = errorCode;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java b/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java
new file mode 100644
index 0000000..5a23a95
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java
@@ -0,0 +1,17 @@
+package org.eclipse.openk.portal.viewmodel;
+
+
+public class GeneralReturnItem {
+    private String ret;
+
+    public GeneralReturnItem( String ret ) {
+        this.ret = ret;
+}
+    public String getRet() {
+        return ret;
+    }
+
+    public void setRet(String ret) {
+        this.ret = ret;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java b/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java
new file mode 100644
index 0000000..c93a87f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java
@@ -0,0 +1,22 @@
+package org.eclipse.openk.portal.viewmodel;
+
+public class LoginCredentials {
+    private String userName;
+    private String password;
+
+    public String getUserName() {
+        return userName;
+    }
+
+    public void setUserName(String userName) {
+        this.userName = userName;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java b/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java
new file mode 100644
index 0000000..028b4d1
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java
@@ -0,0 +1,58 @@
+package org.eclipse.openk.portal.viewmodel;
+
+public class UserAuthentication {
+
+    private int id;
+    private boolean selected;
+    private String username;
+    private String password;
+    private String name;
+    private boolean specialUser;
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public boolean isSelected() {
+        return selected;
+    }
+
+    public void setSelected(boolean selected) {
+        this.selected = selected;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public boolean isSpecialUser() {
+        return specialUser;
+    }
+
+    public void setSpecialUser(boolean specialUser) {
+        this.specialUser = specialUser;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+    public void setUsername(String username) {
+        this.username = username;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java b/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java
new file mode 100644
index 0000000..42a4f13
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java
@@ -0,0 +1,31 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+
+public class UserCache {
+
+  private static final UserCache USERCACHE_INSTANCE = new UserCache();
+  private final List<KeyCloakUser> keyCloakUsers = new ArrayList<>();
+
+  private UserCache(){
+  }
+
+  public static UserCache getInstance() {
+      return USERCACHE_INSTANCE;
+  }
+
+  public List<KeyCloakUser> getKeyCloakUsers() {
+    synchronized (keyCloakUsers){
+      return keyCloakUsers;
+    }
+  }
+
+  public void setKeyCloakUsers(List<KeyCloakUser> keyCloakUsers) {
+    synchronized (this.keyCloakUsers){
+      this.keyCloakUsers.clear();
+      this.keyCloakUsers.addAll(keyCloakUsers);
+    }
+  }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java b/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java
new file mode 100644
index 0000000..1270fab
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java
@@ -0,0 +1,69 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+
+public class UserModule {
+
+    private static String configFileName = "moduleConfigDevLocal.json";
+    private String name;
+    private Integer cols;
+    private Integer rows;
+    private String color;
+    private String link;
+    private String pictureLink;
+    private String requiredRole;
+
+    private static UserModule[] instance;
+
+    public static synchronized UserModule[] getInstance() {
+        if (instance == null) {
+            String jsonConfig = loadJsonConfig();
+            instance = JsonGeneratorBase.getGson().fromJson(jsonConfig, UserModule[].class);
+        }
+
+        return instance;
+    }
+
+    private static String loadJsonConfig() {
+        ResourceLoaderBase resourceLoaderBase = new ResourceLoaderBase();
+        return resourceLoaderBase.loadStringFromResource(configFileName);
+    }
+
+    public String getModuleName() { return name; }
+
+    public void setModuleName(String name) { this.name = name; }
+
+    public Integer getCols() { return cols; }
+
+    public void setCols(Integer cols) { this.cols = cols; }
+
+    public Integer getRows() { return rows; }
+
+    public void setRows(Integer rows) { this.rows = rows; }
+
+    public String getColor() { return color; }
+
+    public void setColor(String color) { this.color = color; }
+
+    public String getLink() { return link; }
+
+    public void setLink(String link) { this.link = link; }
+
+    public String getPictureLink() { return pictureLink; }
+
+    public void setPictureLink(String pictureLink) { this.pictureLink = pictureLink; }
+
+    public String getRequiredRole() { return requiredRole; }
+
+    public void setRequiredRole(String role) { this.requiredRole = role; }
+
+    public static String getConfigFileName() {
+        return configFileName;
+    }
+
+    public static void setConfigFileName(String configFileName) {
+        UserModule.configFileName = configFileName;
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java b/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java
new file mode 100644
index 0000000..a96ac02
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java
@@ -0,0 +1,15 @@
+package org.eclipse.openk.portal.viewmodel;
+
+public class VersionInfo {
+    private String backendVersion;
+
+    public String getBackendVersion() {
+        return backendVersion;
+    }
+
+    public void setBackendVersion(String backendVersion) {
+        this.backendVersion = backendVersion;
+    }
+
+
+}
diff --git a/src/main/resources/backendConfigCustom.json b/src/main/resources/backendConfigCustom.json
new file mode 100644
index 0000000..6197068
--- /dev/null
+++ b/src/main/resources/backendConfigCustom.json
@@ -0,0 +1,9 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://entjava002:8080/",
+  "keycloakRealm": "elogbook",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "nimda"
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigDevLocal.json b/src/main/resources/backendConfigDevLocal.json
new file mode 100644
index 0000000..6197068
--- /dev/null
+++ b/src/main/resources/backendConfigDevLocal.json
@@ -0,0 +1,9 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://entjava002:8080/",
+  "keycloakRealm": "elogbook",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "nimda"
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigDevServer.json b/src/main/resources/backendConfigDevServer.json
new file mode 100644
index 0000000..17b73db
--- /dev/null
+++ b/src/main/resources/backendConfigDevServer.json
@@ -0,0 +1,9 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://localhost:8080/",
+  "keycloakRealm": "Elogbook",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "admin"
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigProduction.json b/src/main/resources/backendConfigProduction.json
new file mode 100644
index 0000000..7fed7db
--- /dev/null
+++ b/src/main/resources/backendConfigProduction.json
@@ -0,0 +1,9 @@
+{
+  "internalSessionLengthMillis": 46800000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://localhost:8090/",
+  "keycloakRealm": "MainDonauNetz",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "Gfxt!T123"
+}
\ No newline at end of file
diff --git a/src/main/resources/moduleConfigCustom.json b/src/main/resources/moduleConfigCustom.json
new file mode 100644
index 0000000..61e59f1
--- /dev/null
+++ b/src/main/resources/moduleConfigCustom.json
@@ -0,0 +1,39 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:8088/elogbookFE",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+    "requiredRole": "elogbook-access"
+
+  },
+  {
+    "name": "Bereitschaftsplanung",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+    "requiredRole": "planning-access"
+  },
+  {
+    "name": "Einspeisemanagement",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+    "requiredRole": "feedin-management-access"
+  },
+  {
+    "name": "Geplante Maßnahmen",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/64-geplante-netzmassnahme",
+    "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+    "requiredRole": "planned-policies-access"
+  }
+]
diff --git a/src/main/resources/moduleConfigDevLocal.json b/src/main/resources/moduleConfigDevLocal.json
new file mode 100644
index 0000000..3e4e543
--- /dev/null
+++ b/src/main/resources/moduleConfigDevLocal.json
@@ -0,0 +1,39 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:4200/",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+    "requiredRole": "elogbook-access"
+
+  },
+  {
+    "name": "Bereitschaftsplanung",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+    "requiredRole": "planning-access"
+  },
+  {
+    "name": "Einspeisemanagement",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+    "requiredRole": "feedin-management-access"
+  },
+  {
+    "name": "Geplante Maßnahmen",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/64-geplante-netzmassnahme",
+    "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+    "requiredRole": "planned-policies-access"
+  }
+]
diff --git a/src/main/resources/moduleConfigDevServer.json b/src/main/resources/moduleConfigDevServer.json
new file mode 100644
index 0000000..c9f70ad
--- /dev/null
+++ b/src/main/resources/moduleConfigDevServer.json
@@ -0,0 +1,39 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://172.18.22.160:8880/elogbookFE",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+    "requiredRole": "elogbook-access"
+
+  },
+  {
+    "name": "Bereitschaftsplanung",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+    "requiredRole": "planning-access"
+  },
+  {
+    "name": "Einspeisemanagement",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+    "requiredRole": "feedin-management-access"
+  },
+  {
+    "name": "Geplante Maßnahmen",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/64-geplante-netzmassnahme",
+    "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+    "requiredRole": "planned-policies-access"
+  }
+]
diff --git a/src/main/resources/moduleConfigProduction.json b/src/main/resources/moduleConfigProduction.json
new file mode 100644
index 0000000..2251e9a
--- /dev/null
+++ b/src/main/resources/moduleConfigProduction.json
@@ -0,0 +1,39 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://159.122.103.182/elogbookFE",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+    "requiredRole": "elogbook-access"
+
+  },
+  {
+    "name": "Bereitschaftsplanung",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+    "requiredRole": "planning-access"
+  },
+  {
+    "name": "Einspeisemanagement",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+    "requiredRole": "feedin-management-access"
+  },
+  {
+    "name": "Geplante Maßnahmen",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/64-geplante-netzmassnahme",
+    "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+    "requiredRole": "planned-policies-access"
+  }
+]
diff --git a/src/main/webapp/WEB-INF/keycloak.json b/src/main/webapp/WEB-INF/keycloak.json
new file mode 100644
index 0000000..40ff32c
--- /dev/null
+++ b/src/main/webapp/WEB-INF/keycloak.json
@@ -0,0 +1,9 @@
+{
+  "realm": "elogbook",
+  "auth-server-url": "http://entjava002:8080/auth",
+  "ssl-required": "external",
+  "resource": "elogbook-backend",
+  "public-client": true,
+  "enable-cors": true,
+  "use-resource-role-mappings": true
+}
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/logger.xml b/src/main/webapp/WEB-INF/logger.xml
new file mode 100644
index 0000000..a0b8f3b
--- /dev/null
+++ b/src/main/webapp/WEB-INF/logger.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration PUBLIC
+        "-//APACHE//DTD LOG4J 1.2//EN"
+        "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+        <param name="Threshold" value="DEBUG"/>
+        <param name="Target" value="System.out"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n"/>
+        </layout>
+    </appender>
+
+    <appender name="Socket" class="org.apache.log4j.net.SocketAppender">
+        <param name="remoteHost" value="127.0.0.1"/>
+        <param name="port" value="4560"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n"/>
+        </layout>
+    </appender>
+
+    <!-- Issue: das Verzeichnis muss existieren ... -->
+    <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
+        <param name="Threshold" value="TRACE"/>
+        <param name="File" value="${catalina.base}/logs/portal-openk.backend.log"/>
+        <param name="Append" value="true"/>
+        <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n"/>
+        </layout>
+    </appender>
+
+    <!-- Default Logging configuration beginnend mit org.eclipse (= alle Packages) -->
+    <category name="org.eclipse">
+        <priority value="INFO"/>
+        <!--<priority value="DEBUG"/> -->
+        <!--<priority value="ERROR"/> -->
+        <appender-ref ref="CONSOLE"/>
+        <!--<appender-ref ref="Socket"/> -->
+        <!--<appender-ref ref="FILE"/> -->
+        <!--<appender-ref ref="SYSLOG"/> -->
+        <appender-ref ref="FILE"/>
+    </category>
+    <category name="org.jboss.resteasy">
+        <priority value="WARN"/>
+        <!--<priority value="DEBUG"/> -->
+        <!--<priority value="ERROR"/> -->
+        <appender-ref ref="CONSOLE"/>
+        <!--<appender-ref ref="Socket"/> -->
+        <!--<appender-ref ref="FILE"/> -->
+        <!--<appender-ref ref="SYSLOG"/> -->
+        <appender-ref ref="FILE"/>
+    </category>
+    <category name="javax.persistence.Persistence">
+        <priority value="INFO"/>
+        <!--<priority value="DEBUG"/> -->
+        <!--<priority value="ERROR"/> -->
+        <appender-ref ref="CONSOLE"/>
+        <!--<appender-ref ref="Socket"/> -->
+        <!--<appender-ref ref="FILE"/> -->
+        <!--<appender-ref ref="SYSLOG"/> -->
+        <appender-ref ref="FILE"/>
+    </category>
+
+</log4j:configuration>
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2b6bcdb
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,60 @@
+<web-app id="WebApp_ID" version="2.4"
+  xmlns="http://java.sun.com/xml/ns/j2ee"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+  <display-name>Restful Web Application</display-name>
+
+  <context-param>
+    <param-name>resteasy.servlet.mapping.prefix</param-name>
+    <param-value>/rest</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>resteasy.scan</param-name>
+    <param-value>false</param-value>
+  </context-param>
+
+  <listener>
+    <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap</listener-class>
+  </listener>
+
+  <servlet>
+    <servlet-name>Resteasy</servlet-name>
+    <servlet-class>
+      org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
+    </servlet-class>
+    <init-param>
+      <param-name>javax.ws.rs.Application</param-name>
+      <param-value>org.eclipse.openk.portal.rest.RestServiceConfiguration</param-value>
+    </init-param>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>Resteasy</servlet-name>
+    <url-pattern>/rest/*</url-pattern>
+  </servlet-mapping>
+
+  <servlet>
+    <servlet-name>log4j-init</servlet-name>
+    <servlet-class>org.eclipse.openk.portal.common.util.LoggerUtil</servlet-class>
+    <init-param>
+      <param-name>log4j-init-file</param-name>
+      <param-value>WEB-INF/logger.xml</param-value>
+    </init-param>
+    <load-on-startup>0</load-on-startup>
+  </servlet>
+
+  <servlet>
+    <servlet-name>InitBackendConfig</servlet-name>
+    <servlet-class>org.eclipse.openk.portal.common.InitBackendConfig</servlet-class>
+    <load-on-startup>2</load-on-startup>
+  </servlet>
+
+  <servlet>
+    <servlet-name>InitUserCacheJob</servlet-name>
+    <servlet-class>org.eclipse.openk.portal.common.InitUserCacheJob</servlet-class>
+    <load-on-startup>3</load-on-startup>
+  </servlet>
+
+</web-app>
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
new file mode 100644
index 0000000..97b5341
--- /dev/null
+++ b/src/main/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+it works!
+</body>
+</html>
\ No newline at end of file
diff --git a/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java b/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java
new file mode 100644
index 0000000..64c9ace
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java
@@ -0,0 +1,23 @@
+package org.eclipse.openk.portal.common;
+
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class BackendConfigTest {
+    @Test
+    public void testConfig() {
+        BackendConfig bc = BackendConfig.getInstance();
+        assertEquals( (int)bc.getInternalSessionLengthMillis(), 3600000 );
+        assertEquals( (int)bc.getReloadUsersInSec(), 300 );
+        assertEquals( bc.getAuthServerUrl(), "http://entjava002:8080/");
+        assertEquals( bc.getKeycloakRealm(), "elogbook");
+        assertEquals( bc.getKeycloakClient(),"elogbook-backend");
+        assertEquals( bc.getKeycloakAdmin(), "admin");
+        assertEquals( bc.getKeycloakPW(), "nimda");
+        assertEquals( BackendConfig.getConfigFileName(), "backendConfigDevLocal.json");
+        BackendConfig.setConfigFileName("backendConfigProduction.json");
+        assertEquals( BackendConfig.getConfigFileName(), "backendConfigProduction.json");
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java b/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java
new file mode 100644
index 0000000..9d14aec
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java
@@ -0,0 +1,38 @@
+package org.eclipse.openk.portal.common;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonSerializationContext;
+import org.junit.Test;
+
+import java.lang.reflect.Type;
+import java.util.Calendar;
+
+public class GsonUTCDateAdapterTest {
+
+    @Test
+    public void serializeTest() {
+        GsonUTCDateAdapter gsonUTCDateAdapter = new GsonUTCDateAdapter();
+        Calendar calendar = Calendar.getInstance();
+        java.util.Date date = calendar.getTime();
+        Type type = new Type() {
+            @Override
+            public String getTypeName() {
+                return null;
+            }
+        };
+        JsonSerializationContext jsonSerializationContext = new JsonSerializationContext() {
+            @Override
+            public JsonElement serialize(Object o) {
+                return null;
+            }
+
+            @Override
+            public JsonElement serialize(Object o, Type type) {
+                return null;
+            }
+        };
+
+        gsonUTCDateAdapter.serialize(date, type, jsonSerializationContext);
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java b/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java
new file mode 100644
index 0000000..d80fbda
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java
@@ -0,0 +1,38 @@
+package org.eclipse.openk.portal.common;
+
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+public class InitBackendConfigTest {
+
+    private InitBackendConfig initBackendConfig = new InitBackendConfig();
+
+    @Test
+    public void testSetConfigFiles() throws Exception {
+        Whitebox.invokeMethod(initBackendConfig, "setConfigFiles", "DevLocal");
+    }
+
+    private void testGeneric(String environment ) throws Exception {
+        Whitebox.invokeMethod(initBackendConfig, "setConfigFiles", environment);
+    }
+
+    @Test
+    public void testCombinations() throws Exception {
+
+        testGeneric("DevLocal");
+        testGeneric("DevLocal");
+
+        testGeneric("DevServer");
+        testGeneric("DevServer");
+
+        testGeneric("Custom");
+        testGeneric("Custom");
+
+        testGeneric(null);
+        testGeneric(null);
+
+        testGeneric("");
+        testGeneric("");
+
+}
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java b/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java
new file mode 100644
index 0000000..49a010d
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java
@@ -0,0 +1,16 @@
+package org.eclipse.openk.portal.common;
+
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+import javax.servlet.ServletException;
+
+public class InitUserCacheJobTest extends ResourceLoaderBase {
+
+    @Test
+    public void testInit() throws ServletException {
+        InitUserCacheJob job = new InitUserCacheJob();
+        job.init();
+        // Test only covers Code!
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java b/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java
new file mode 100644
index 0000000..4a9290e
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java
@@ -0,0 +1,65 @@
+package org.eclipse.openk.portal.common;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.easymock.EasyMock.expect;
+import static org.eclipse.openk.portal.common.JsonGeneratorBase.getGson;
+
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
+import java.util.List;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(JwtHelper.class)
+public class UserCacheTimerTaskTest  extends ResourceLoaderBase {
+
+    private UserCacheTimerTask task;
+
+    @Before
+    public void prepareTests() {
+        task = new UserCacheTimerTask();
+        PowerMock.mockStatic(JwtHelper.class);
+    }
+
+    @Test
+    public void testGetKeyCloakUsersFromToken() throws Exception {
+        String json = super.loadStringFromResource("JWTAdmin.json");
+        JwtToken jwt = getGson().fromJson(json, JwtToken.class);
+
+        String jsonKeyCloakUser = super.loadStringFromResource("testKeyCloakUsers.json");
+        Type listTypeKeyCloakUser = new TypeToken<List<KeyCloakUser>>(){}.getType();
+        List<KeyCloakUser> keyCloakUsersList = JsonGeneratorBase.getGson().fromJson(jsonKeyCloakUser, listTypeKeyCloakUser);
+        keyCloakUsersList.remove(1);
+        keyCloakUsersList.remove(1);
+
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles.json");
+        Type listTypeKeyCloakRole = new TypeToken<List<KeyCloakRole>>(){}.getType();
+        List<KeyCloakRole> keyCloakRolesList = JsonGeneratorBase.getGson().fromJson(jsonKeyCloakRoles, listTypeKeyCloakRole);
+
+        expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(jwt);
+        expect(JwtHelper.getUsers(jwt)).andReturn(keyCloakUsersList);
+        expect(JwtHelper.getRolesForUser(jwt, keyCloakUsersList.get(0).getId())).andReturn(keyCloakRolesList);
+
+        PowerMock.replayAll();
+        task.run();
+        PowerMock.verifyAll();
+
+        List<KeyCloakUser> keyCloakUsersResult = UserCache.getInstance().getKeyCloakUsers();
+
+        assertTrue(keyCloakUsersResult.size() == 1);
+        assertTrue(keyCloakUsersResult.get(0).getRealmRoles().size() == 8);
+        assertTrue(keyCloakUsersResult.get(0).getRealmRoles().get(0).equals("elogbook-superuser"));
+        assertTrue(keyCloakUsersResult.get(0).getRealmRoles().get(6).equals("elogbook-access"));
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java b/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java
new file mode 100644
index 0000000..699f644
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java
@@ -0,0 +1,17 @@
+package org.eclipse.openk.portal.common.util;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Objects;
+import org.junit.Test;
+
+public class HashingAlgoTest {
+	@Test
+	public void testHashIt() {
+		String hash = HashingAlgo.hashIt("TestMe");
+		assertTrue("66d565a2eb74e1a20b6c12bb2cbf84ecaade84ec".equals(hash));
+		assertTrue(!Objects.equals(HashingAlgo.hashIt("ThisIsTest"), HashingAlgo.hashIt("thisIsATest")));
+		assertNull(HashingAlgo.hashIt(null));
+	}
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java b/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java
new file mode 100644
index 0000000..ac2bbec
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java
@@ -0,0 +1,15 @@
+package org.eclipse.openk.portal.common.util;
+
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class ResourceLoaderBaseTest {
+    @Test
+    public void testloadStringFromResourceError() {
+        ResourceLoaderBase rlb = new ResourceLoaderBase();
+        String str = rlb.loadStringFromResource("UNKNOWN_FILE");
+        assertEquals(str, "");
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java b/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java
new file mode 100644
index 0000000..ba61abe
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java
@@ -0,0 +1,37 @@
+package org.eclipse.openk.portal.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import java.util.List;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.LoginCredentials;
+import org.eclipse.openk.portal.viewmodel.UserAuthentication;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class BackendControllerTest  extends ResourceLoaderBase {
+
+    @Test
+    public void testGetVersionInfo() {
+        BackendController bec = new BackendController();
+        VersionInfo vi = bec.getVersionInfo();
+
+        String vCurr = getClass().getPackage().getImplementationVersion();
+        assertEquals( vi.getBackendVersion(), vCurr );
+    }
+
+    @Test
+    public void getUserModuleList_TemporaryOnly() {
+        //_fd only temporarily
+        List<UserModule> modList = new BackendController().getUserModuleList();
+        assertTrue( !modList.isEmpty() );
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java b/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java
new file mode 100644
index 0000000..f804fe6
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java
@@ -0,0 +1,249 @@
+package org.eclipse.openk.portal.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalBadRequest;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class BaseWebServiceTest {
+	private static final org.apache.log4j.Logger EMPTYLOGGER = org.apache.log4j.Logger
+			.getLogger(BaseWebServiceTest.class.getName());
+
+	public static class TestWebService extends BaseWebService {
+		public String sessionId;
+		public boolean throwUnauthException = false;
+
+		public TestWebService() {
+			super(EMPTYLOGGER);
+		}
+
+		protected void assertAndRefreshToken(String sessionId, boolean refresh) throws PortalException {
+			if (throwUnauthException) {
+				throw new PortalUnauthorized();
+			} else {
+				this.sessionId = sessionId;
+			}
+		}
+	}
+
+	public static class TestInvokable extends BackendInvokable {
+		public boolean isInvoked = false;
+		public PortalException exceptionToThrow = null;
+		public boolean throwRuntime = false;
+		public Response response = null;
+
+		@Override
+		public Response invoke() throws PortalException {
+			if (exceptionToThrow != null) {
+				throw exceptionToThrow;
+			}
+			if (throwRuntime) {
+				((String) null).equals("error"); //NOSONAR
+			}
+			isInvoked = true;
+			return response;
+		}
+	}
+	
+	@Test
+	public void testInvokeException() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+
+		ti.exceptionToThrow = new PortalBadRequest();
+		Response ret = tws.invoke("ssess", false, ti);
+		Assert.assertEquals(ret.getStatus(), Globals.HTTPSTATUS_BAD_REQUEST);
+	}
+
+	@Test
+	public void testInvokeRuntimeException() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+
+		ti.throwRuntime = true;
+		Response ret = tws.invoke("ssess",  false, ti);
+		assertEquals(ret.getStatus(), Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR);
+	}
+
+	@Test
+	public void testUnauthException() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+		tws.throwUnauthException = true;
+		Response ret = tws.invoke("ssess",  false, ti);
+		assertEquals(ret.getStatus(), Globals.HTTPSTATUS_UNAUTHORIZED);
+	}
+
+	@Test
+	public void testSecureTypeNone() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+		Response responseForTypeNONE = tws.invoke("ssess", false, ti);
+		assertNull(responseForTypeNONE);
+	}
+
+
+	@Test
+	public void testInvokation() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+		ti.response = new Response() {
+			@Override
+			public Object getEntity() {
+				return null;
+			}
+
+			@Override
+			public <T> T readEntity(Class<T> aClass) {
+				return null;
+			}
+
+			@Override
+			public <T> T readEntity(GenericType<T> genericType) {
+				return null;
+			}
+
+			@Override
+			public <T> T readEntity(Class<T> aClass, Annotation[] annotations) {
+				return null;
+			}
+
+			@Override
+			public <T> T readEntity(GenericType<T> genericType, Annotation[] annotations) {
+				return null;
+			}
+
+			@Override
+			public boolean hasEntity() {
+				return false;
+			}
+
+			@Override
+			public boolean bufferEntity() {
+				return false;
+			}
+
+			@Override
+			public void close() {
+
+			}
+
+			@Override
+			public MediaType getMediaType() {
+				return null;
+			}
+
+			@Override
+			public Locale getLanguage() {
+				return null;
+			}
+
+			@Override
+			public int getLength() {
+				return 0;
+			}
+
+			@Override
+			public Set<String> getAllowedMethods() {
+				return null;
+			}
+
+			@Override
+			public Map<String, NewCookie> getCookies() {
+				return null;
+			}
+
+			@Override
+			public EntityTag getEntityTag() {
+				return null;
+			}
+
+			@Override
+			public Date getDate() {
+				return null;
+			}
+
+			@Override
+			public Date getLastModified() {
+				return null;
+			}
+
+			@Override
+			public URI getLocation() {
+				return null;
+			}
+
+			@Override
+			public Set<Link> getLinks() {
+				return null;
+			}
+
+			@Override
+			public boolean hasLink(String s) {
+				return false;
+			}
+
+			@Override
+			public Link getLink(String s) {
+				return null;
+			}
+
+			@Override
+			public Link.Builder getLinkBuilder(String s) {
+				return null;
+			}
+
+			@Override
+			public int getStatus() {
+				return 666;
+			}
+
+			@Override
+			public StatusType getStatusInfo() {
+				return null;
+			}
+
+			@Override
+			public MultivaluedMap<String, Object> getMetadata() {
+				return null;
+			}
+
+			@Override
+			public MultivaluedMap<String, String> getStringHeaders() {
+				return null;
+			}
+
+			@Override
+			public String getHeaderString(String s) {
+				return null;
+			}
+		};
+
+		Response ret = tws.invoke("ssess",  false, ti);
+		assertTrue(ti.isInvoked);
+		assertEquals(tws.sessionId, "ssess");
+		assertEquals(ret.getStatus(), 666);
+
+	}
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java b/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java
new file mode 100644
index 0000000..0445e84
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java
@@ -0,0 +1,91 @@
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.api.easymock.PowerMock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.easymock.EasyMock.expect;
+
+
+public class ControllerImplementationsTest extends ResourceLoaderBase {
+    private BackendController beMock;
+    @Before
+    public void prepareTests() {
+        beMock = PowerMock.createNiceMock(BackendController.class);
+    }
+
+    @Test
+    public void testGetUsers() throws PortalException {
+        List<KeyCloakUser> userList = new ArrayList<>();
+        ControllerImplementations.GetUsers controllerImpl = new ControllerImplementations.GetUsers();
+        controllerImpl.setModUser("EgalUser");
+        controllerImpl.setUserId(14);
+
+        expect(beMock.getUsers()).andReturn(userList);
+        PowerMock.replay(beMock);
+
+        assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+        assertEquals(controllerImpl.getModUser(), "EgalUser");
+        assertEquals(controllerImpl.getUserId(), 14);
+    }
+
+    @Test
+    public void testGetVersionInfo() throws PortalException {
+        VersionInfo vi = new VersionInfo();
+        ControllerImplementations.GetVersionInfo controllerImpl = new ControllerImplementations.GetVersionInfo(beMock);
+
+        expect(beMock.getVersionInfo()).andReturn(vi);
+        PowerMock.replay(beMock);
+
+        assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+    }
+
+    @Test
+    public void testLogOut() throws PortalException {
+        ControllerImplementations.Logout controllerImpl = new ControllerImplementations.Logout("LogMeOut");
+        assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+    }
+
+    @Test
+    public void testCheckAuth() throws PortalException {
+        ControllerImplementations.CheckAuth controllerImpl = new ControllerImplementations.CheckAuth();
+        assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+    }
+
+    @Test
+    public void testGetUserModulesForUser() throws PortalException {
+        List<UserModule> userModules = new ArrayList<>();
+        ControllerImplementations.GetUserModulesForUser controllerImpl = new ControllerImplementations.GetUserModulesForUser(beMock);
+        controllerImpl.setModUser("EgalUser");
+
+        expect(beMock.getUserModuleList()).andReturn(userModules);
+        PowerMock.replay(beMock);
+
+        assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+        assertEquals(controllerImpl.getModUser(), "EgalUser");
+    }
+
+    @Test
+    public void testGetUserForRole() throws PortalException {
+        List<KeyCloakUser> keyCloakUsers = new ArrayList<>();
+        String userRole = "theBestRole";
+        ControllerImplementations.GetUsersForRole controllerImpl = new ControllerImplementations.GetUsersForRole(beMock, userRole);
+        controllerImpl.setModUser("EgalUser");
+
+        expect(beMock.getUsersForRole(userRole)).andReturn(keyCloakUsers);
+        PowerMock.replay(beMock);
+
+        assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+        assertEquals(controllerImpl.getModUser(), "EgalUser");
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java b/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java
new file mode 100644
index 0000000..5a2bfc4
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java
@@ -0,0 +1,72 @@
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalBadRequest;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+public class InputValidatorTest extends ResourceLoaderBase {
+
+    // Check Credentials -------------------------------------------------------
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testCheckCredentials_Null() throws PortalUnauthorized {
+        new InputDataValuator().checkCredentials(null);
+    }
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testCheckCredentials_Empty() throws PortalUnauthorized {
+        new InputDataValuator().checkCredentials("");
+    }
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testCheckCredentials_TooLong() throws PortalUnauthorized {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < Globals.MAX_CREDENTIALS_LENGTH; i++) {
+            sb.append("W");
+        }
+        new InputDataValuator().checkCredentials(sb.toString());
+
+    }
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testCheckCredentials_Invalid() throws PortalUnauthorized {
+        new InputDataValuator().checkCredentials("{\"abc\":\"123\"}");
+    }
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testCheckCredentials_InvalidNoJson() throws PortalUnauthorized {
+        new InputDataValuator().checkCredentials("123");
+    }
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testCheckCredentials_tooLong() throws PortalUnauthorized {
+        StringBuilder sb = new StringBuilder(Globals.MAX_CREDENTIALS_LENGTH + 1);
+        for (int i = 0; i < Globals.MAX_CREDENTIALS_LENGTH + 1; i++) {
+            sb.append("@");
+        }
+        new InputDataValuator().checkCredentials(sb.toString());
+
+    }
+
+    @Test
+    public void checkWhitelistChars_ok() throws Exception {
+        callWhitelistCheck("AaBbCcäÄöÖüÜß ?0123456789(). _+  ,-:;=!§%&/'#<>\"");
+    }
+
+    @Test(expected = PortalBadRequest.class)
+    public void checkWhitelistChars_nok() throws Exception {
+        callWhitelistCheck(null);
+        callWhitelistCheck("");
+        callWhitelistCheck("AaBbCc.,{}");
+    }
+
+    private void callWhitelistCheck(String tst) throws Exception {
+        InputDataValuator idv = new InputDataValuator();
+        Whitebox.invokeMethod(idv, "checkWhitelistChars", tst, false);
+    }
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java b/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java
new file mode 100644
index 0000000..32b26be
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java
@@ -0,0 +1,31 @@
+package org.eclipse.openk.portal.controller;
+
+
+import static org.junit.Assert.assertEquals;
+
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.junit.Test;
+
+
+public class ResponseBuilderWrapperTest {
+    @Test
+    public void testGetResponseBuilder() throws PortalInternalServerError {
+        String json = "{ 'ret' : 'OK' }";
+        Response.ResponseBuilder rb = ResponseBuilderWrapper.INSTANCE.getResponseBuilder( json );
+        Response resp = rb.build();
+        assertEquals(resp.getStatus(), Globals.HTTPSTATUS_OK );
+    }
+
+    @Test
+    public void testBuildOkResponse() throws PortalException {
+        String json = "{ 'test' : 'Value' }";
+        Response resp = ResponseBuilderWrapper.INSTANCE.buildOKResponse( json );
+        assertEquals( resp.getStatus(), Globals.HTTPSTATUS_OK );
+
+        resp = ResponseBuilderWrapper.INSTANCE.buildOKResponse(json, "ssess");
+        assertEquals( resp.getStatus(), Globals.HTTPSTATUS_OK);
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java b/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java
new file mode 100644
index 0000000..559fed1
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java
@@ -0,0 +1,95 @@
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import java.util.HashMap;
+import static org.junit.Assert.*;
+
+public class TokenManagerTest extends ResourceLoaderBase {
+
+    @Before
+    public void cleanUp() {
+        TokenManager sessione = TokenManager.getInstance();
+        HashMap<String, TokenManager.SessionItem> regMap = Whitebox.getInternalState(sessione, "registry");
+        regMap.clear();
+    }
+
+    @Test
+    public void testRegisterNewSession() {
+        final int COUNT = 1000;
+
+        for (int i = 0; i < COUNT; i++) {
+            TokenManager.getInstance().registerNewSession(createJWT( "T"+i ));
+        }
+    }
+
+
+    @Test(expected = PortalUnauthorized.class)
+    public void testRefreshStatusIsAlive() throws InterruptedException, PortalUnauthorized {
+        TokenManager sessione = TokenManager.getInstance();
+        JwtToken specialToken = createJWT(null);
+
+        long timeNow = System.currentTimeMillis();
+        sessione.registerNewSession(createJWT("HUGO1"));
+        sessione.registerNewSession(specialToken);
+        sessione.registerNewSession(createJWT("HUGO3"));
+
+        HashMap<String, TokenManager.SessionItem> regMap = Whitebox.getInternalState(sessione, "registry");
+
+        assertEquals(regMap.size(), 3);
+        assertTrue(regMap.containsKey("HUGO1"));
+        assertTrue(regMap.containsKey(specialToken.getAccessToken()));
+        assertTrue(regMap.containsKey("HUGO3"));
+
+        regMap.remove(specialToken.getAccessToken());
+        regMap.put(specialToken.getAccessToken(), new TokenManager.SessionItem(timeNow - BackendConfig.getInstance().getInternalSessionLengthMillis() - 1));
+        regMap.get(specialToken.getAccessToken()).setJwtToken(specialToken);
+        regMap.remove("HUGO3");
+        regMap.put("HUGO3", null);
+
+        Thread.sleep(50); // NOSONAR // LOCK is held
+
+        TokenManager.getInstance().refreshSessionIsAlive("HUGO1", true);
+
+        // create Time stays the same
+        TokenManager.SessionItem sit1 = regMap.get("HUGO1");
+        assertTrue(sit1.getSessionLastAccessTime() > sit1.getSessionCreationTime());
+
+        sit1.setSessionCreationTime(sit1.getSessionLastAccessTime()-200);
+        assertEquals( sit1.getSessionCreationTime()+200, sit1.getSessionLastAccessTime());
+        sit1.setUser(null);
+        assertNull(sit1.getUser());
+        assertEquals(sit1.getSessionId(), "HUGO1");
+        sit1.setCookieToken("CaptainCookie");
+        assertEquals(sit1.getCookieToken(), "CaptainCookie");
+
+        TokenManager.getInstance().logout("HUGO1");
+        assertEquals(regMap.size(), 2);
+        TokenManager.getInstance().logout( "FAKE");
+        assertEquals(regMap.size(), 2);
+
+
+        // session out of time
+        TokenManager.getInstance().refreshSessionIsAlive(specialToken.getAccessToken(), true);
+        // fails with PortalUnauthorized
+    }
+
+    private JwtToken createJWT(String accessToken ) {
+        String json = super.loadStringFromResource("JWTAdmin.json");
+        JwtToken jwt = JsonGeneratorBase.getGson().fromJson(json, JwtToken.class);
+
+        if( accessToken != null ) {
+            jwt.setAccessToken(accessToken);
+        }
+        return jwt;
+    }
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java
new file mode 100644
index 0000000..65fa726
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java
@@ -0,0 +1,44 @@
+package org.eclipse.openk.portal.exceptions;
+
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.viewmodel.ErrorReturn;
+import org.junit.Test;
+
+public class PortalExceptionMapperTest extends ResourceLoaderBase {
+    @Test
+    public void testToJson() {
+        String json = PortalExceptionMapper.toJson(new PortalNotFound("lalilu"));
+
+        ErrorReturn er = JsonGeneratorBase.getGson().fromJson(json, ErrorReturn.class);
+        assertEquals(er.getErrorCode(), 404);
+        assertTrue(er.getErrorText().equals("lalilu"));
+    }
+
+    @Test
+    public void testUnknownErrorToJson() {
+        String json = PortalExceptionMapper.unknownErrorToJson();
+
+        ErrorReturn er = JsonGeneratorBase.getGson().fromJson(json, ErrorReturn.class);
+        assertEquals(er.getErrorCode(), 500);
+    }
+
+    @Test
+    public void testGeneralOKJson() {
+        String ok = PortalExceptionMapper.getGeneralOKJson();
+        assertTrue("{\"ret\":\"OK\"}".equals(ok));
+    }
+
+    @Test
+    public void testGeneralErrorJson() {
+        String nok = PortalExceptionMapper.getGeneralErrorJson();
+        assertTrue("{\"ret\":\"NOK\"}".equals(nok));
+    }
+
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java
new file mode 100644
index 0000000..7411aec
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java
@@ -0,0 +1,29 @@
+package org.eclipse.openk.portal.exceptions;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.junit.Test;
+
+public class PortalExceptionsTest {
+
+    @Test
+    public void testConstructors() {
+        assertEquals(new PortalBadRequest().getHttpStatus(), Globals.HTTPSTATUS_BAD_REQUEST);
+        assertEquals(new PortalForbidden().getHttpStatus(), Globals.HTTPSTATUS_FORBIDDEN);
+        assertEquals(new PortalInternalServerError(null, null).getHttpStatus(), Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR);
+        assertEquals(new PortalNotFound().getHttpStatus(), Globals.HTTPSTATUS_NOT_FOUND);
+        assertEquals(new PortalUnauthorized().getHttpStatus(), Globals.HTTPSTATUS_UNAUTHORIZED);
+    }
+
+
+    @Test
+    public void testConstructors2() {
+        final String extext = "ExText";
+        assertEquals(new PortalBadRequest(extext).getMessage(), extext);
+        assertEquals(new PortalForbidden(extext).getMessage(), extext);
+        assertEquals(new PortalInternalServerError(extext).getMessage(), extext);
+        assertEquals(new PortalNotFound(extext).getMessage(), extext);
+        assertEquals(new PortalUnauthorized(extext).getMessage(), extext);
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java
new file mode 100644
index 0000000..9fcfdb0
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java
@@ -0,0 +1,30 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import static org.eclipse.openk.portal.common.JsonGeneratorBase.getGson;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class ErrorReturnTest extends ResourceLoaderBase {
+	// IMPORTANT TEST!!!
+	// Make sure, our Interface produces a DEFINED Json!
+	// Changes in the interface will HOPEFULLY crash here!!!
+
+	@Test
+	public void TestStructureAgainstJson() {
+		String json = super.loadStringFromResource("testErrorReturn.json");
+		ErrorReturn errRet = getGson().fromJson(json, ErrorReturn.class);
+		assertFalse(errRet.getErrorText().isEmpty());
+		assertEquals(errRet.getErrorCode(), 999);
+	}
+
+	@Test
+	public void TestSetters() {
+		ErrorReturn errRet = new ErrorReturn();
+		errRet.setErrorCode(1);
+		errRet.setErrorText("bla bla");
+	}
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java
new file mode 100644
index 0000000..570e89b
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java
@@ -0,0 +1,31 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class GeneralReturnItemTest extends ResourceLoaderBase {
+	// IMPORTANT TEST!!!
+	// Make sure, our Interface produces a DEFINED Json!
+	// Changes in the interface will HOPEFULLY crash here!!!
+
+	@Test
+	public void TestStructureAgainstJson() {
+		String json = super.loadStringFromResource("testGeneralReturnItem.json");
+		GeneralReturnItem gRRet = JsonGeneratorBase.getGson().fromJson(json, GeneralReturnItem.class);
+		assertEquals(gRRet.getRet(), "It works!");
+	}
+
+	@Test
+	public void TestSetters() {
+		GeneralReturnItem gri = new GeneralReturnItem("firstStrike");
+		assertTrue("firstStrike".equals(gri.getRet()));
+		gri.setRet("Retour");
+		assertTrue("Retour".equals(gri.getRet()));
+
+	}
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java
new file mode 100644
index 0000000..1d82045
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java
@@ -0,0 +1,29 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class LoginCredentialsTest extends ResourceLoaderBase {
+
+	@Test
+	public void testStructureAgainstJson() {
+		String json = super.loadStringFromResource("testLoginCredentials.json");
+		LoginCredentials lc = JsonGeneratorBase.getGson().fromJson(json, LoginCredentials.class);
+		assertEquals(lc.getUserName(), "Carlo");
+		assertEquals(lc.getPassword(), "Cottura");
+	}
+
+	@Test
+	public void testSetters() {
+		LoginCredentials lc = new LoginCredentials();
+		lc.setPassword("pwd");
+		assertTrue("pwd".equals(lc.getPassword()));
+		lc.setUserName("usr");
+		assertTrue("usr".equals(lc.getUserName()));
+	}
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java
new file mode 100644
index 0000000..c476f36
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java
@@ -0,0 +1,36 @@
+package org.eclipse.openk.portal.viewmodel;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class UserAuthenticationTest extends ResourceLoaderBase {
+
+    @Test
+    public void testStructureAgainstJson() {
+        String json = super.loadStringFromResource("testUserAuthentication.json");
+        UserAuthentication ua = JsonGeneratorBase.getGson().fromJson(json, UserAuthentication.class);
+        assertTrue(ua.getId() == 1 );
+        assertTrue(ua.getUsername().equals("Pedro"));
+        assertTrue(ua.getPassword().equals("pwd"));
+        assertTrue(ua.getName().equals("Pedro Pepito Sanchez"));
+        assertFalse(ua.isSpecialUser());
+        assertTrue(ua.isSelected());
+    }
+
+    @Test
+    public void testSetters() {
+        UserAuthentication ua = new UserAuthentication();
+        ua.setId(1);
+        ua.setName("Vamos-Namos");
+        ua.setPassword("passoporto");
+        ua.setUsername("VNAMOS");
+        ua.setSpecialUser(true);
+        ua.setSelected(true);
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java
new file mode 100644
index 0000000..32fff14
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java
@@ -0,0 +1,33 @@
+package org.eclipse.openk.portal.viewmodel;
+
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class UserCacheTest extends ResourceLoaderBase {
+    // IMPORTANT TEST!!!
+    // Make sure, our Interface produces a DEFINED Json!
+    // Changes in the interface will HOPEFULLY crash here!!!
+
+    @Test
+    public void testStructureAgainstJsonAndSettersAndGetters() {
+        String json = super.loadStringFromResource("testKeyCloakUsers.json");
+        KeyCloakUser[] keyCloakUsers = JsonGeneratorBase.getGson().fromJson(json, KeyCloakUser[].class);
+        List<KeyCloakUser> keyCloakUsersList = new ArrayList<>(Arrays.asList(keyCloakUsers));
+        UserCache uc = UserCache.getInstance();
+        uc.setKeyCloakUsers(keyCloakUsersList);
+
+        assertTrue(keyCloakUsers.length == 3);
+        assertTrue(uc.getKeyCloakUsers().get(0).getFirstName().equals("Administrator"));
+        assertTrue(uc.getKeyCloakUsers().get(2).getUsername().equals("otto"));
+
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java
new file mode 100644
index 0000000..3f27387
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java
@@ -0,0 +1,25 @@
+package org.eclipse.openk.portal.viewmodel;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class UserModuleTest {
+
+    @Test
+    public void testModuleConfigProduction() {
+        UserModule[] um = UserModule.getInstance();
+        assertEquals( um[0].getModuleName(), "Betriebstagebuch");
+        assertEquals( um[0].getColor(), "#ffffff");
+        assertEquals( (long)um[0].getCols(), 1);
+        assertEquals( (long)um[0].getRows(), 1);
+        assertEquals( um[0].getLink(), "http://localhost:4200/");
+        assertEquals( um[0].getPictureLink(), "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg");
+        assertEquals( um[0].getRequiredRole(), "elogbook-access");
+
+        assertEquals( UserModule.getConfigFileName(), "moduleConfigDevLocal.json");
+        UserModule.setConfigFileName("moduleConfigDevLocal.json");
+        assertEquals( UserModule.getConfigFileName(), "moduleConfigDevLocal.json");
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java
new file mode 100644
index 0000000..dba14f8
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java
@@ -0,0 +1,30 @@
+package org.eclipse.openk.portal.viewmodel;
+
+
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class VersionInfoTest extends ResourceLoaderBase {
+    // IMPORTANT TEST!!!
+    // Make sure, our Interface produces a DEFINED Json!
+    // Changes in the interface will HOPEFULLY crash here!!!
+
+    @Test
+    public void testStructureAgainstJson() {
+        String json = super.loadStringFromResource("VersionInfo.json");
+        VersionInfo vi = JsonGeneratorBase.getGson().fromJson(json, VersionInfo.class);
+
+        assertTrue(vi.getBackendVersion().equals("0x.0x.xx"));
+    }
+
+    @Test
+    public void testSetters() {
+        VersionInfo vi = new VersionInfo();
+
+        vi.setBackendVersion("222");
+    }
+
+}
diff --git a/src/test/resources/JWTAdmin.json b/src/test/resources/JWTAdmin.json
new file mode 100644
index 0000000..dda65c5
--- /dev/null
+++ b/src/test/resources/JWTAdmin.json
@@ -0,0 +1,8 @@
+{
+  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJodVl0eVByUEVLQ1phY3FfMW5sOGZscENETnFHdmZEZHctYUxGQXNoWHZVIn0.eyJqdGkiOiI4ZmY5NTlhZC02ODQ1LTRlOGEtYjRiYi02ODQ0YjAwMjU0ZjgiLCJleHAiOjE1MDY2MDA0NTAsIm5iZiI6MCwiaWF0IjoxNTA2NjAwMTUwLCJpc3MiOiJodHRwOi8vZW50amF2YTAwMjo4MDgwL2F1dGgvcmVhbG1zL2Vsb2dib29rIiwiYXVkIjoiZWxvZ2Jvb2stYmFja2VuZCIsInN1YiI6IjM1OWVmOWM5LTc3ZGYtNGEzZC1hOWM5LWY5NmQ4MzdkMmQ1NyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImVsb2dib29rLWJhY2tlbmQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI5NjVmNzM1MS0yZThiLTQ1MjgtOWYzZC1lZTYyODNhOTViMTYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImVsb2dib29rLXN1cGVydXNlciIsImVsb2dib29rLW5vcm1hbHVzZXIiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy11c2VycyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiQWRtaW5pc3RyYXRvciBBZG1pbmlzdHJhdG93aWNoIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW4iLCJnaXZlbl9uYW1lIjoiQWRtaW5pc3RyYXRvciIsImZhbWlseV9uYW1lIjoiQWRtaW5pc3RyYXRvd2ljaCIsImVtYWlsIjoic2VyZ2VqLmtlcm5AcHRhLmRlIiwicm9sZXN0ZXN0IjoiW2Vsb2dib29rLXN1cGVydXNlciwgZWxvZ2Jvb2stbm9ybWFsdXNlciwgdW1hX2F1dGhvcml6YXRpb24sIG9mZmxpbmVfYWNjZXNzLCB1bWFfYXV0aG9yaXphdGlvbiwgZWxvZ2Jvb2stbm9ybWFsdXNlcl0ifQ.o94Bl43oqyLNzZRABvIq9z-XI8JQjqj2FSDdUUEZGZPTN4uwD5fyi0sONbDxmTFvgWPh_8ZhX6tlDGiupVDBY4eRH43Eettm-t4CDauL7FzB3w3dDPFMB5DhP4rrpk_kATwnY2NKLRbequnh8Z6wLXjcmQNLgrgknXB_gogWAqH29dqKexwceMNIbq-kjaeLsmHSXM9TE9q7_Ln9el04OlkpOVspVguedfINcNFg0DmYLJWyD2ORkOHLmYigN6YnyB9P2NFOnKGlLuQ87GjosI00zBniRGi3PhE9NGd51Qggdbcsm0aM8GiMaZ7SO5i8iQWL10TRFRFyTEfy6hSO8g",
+  "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJodVl0eVByUEVLQ1phY3FfMW5sOGZscENETnFHdmZEZHctYUxGQXNoWHZVIn0.eyJqdGkiOiJlZmNmNzExNS04YzRiLTQzZmQtOGM0ZS0xNjVhYTVmM2ZhZDEiLCJleHAiOjE1MDY2MDE5NTAsIm5iZiI6MCwiaWF0IjoxNTA2NjAwMTUwLCJpc3MiOiJodHRwOi8vZW50amF2YTAwMjo4MDgwL2F1dGgvcmVhbG1zL2Vsb2dib29rIiwiYXVkIjoiZWxvZ2Jvb2stYmFja2VuZCIsInN1YiI6IjM1OWVmOWM5LTc3ZGYtNGEzZC1hOWM5LWY5NmQ4MzdkMmQ1NyIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJlbG9nYm9vay1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiOTY1ZjczNTEtMmU4Yi00NTI4LTlmM2QtZWU2MjgzYTk1YjE2IiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImVsb2dib29rLXN1cGVydXNlciIsImVsb2dib29rLW5vcm1hbHVzZXIiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy11c2VycyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19fQ.rN1f4h9t1-sHW2EXpvYs3Spo8Zxe1-qNuLWCgOwD6E3l_zDwdHOlPxJwlPLwweQ2uuHi1-blk80OdgoDueDslE3tCdkyg_5lXOXG_jVwqgIF8qP2KTlz9gjhJBwBJ94YsHYV2wwy8jvTmUk108FVzEYBvAHL7KMzoD-BJ_4QxLhLuUvhO7I2-xP9sNRnUG_4xOrXl22WhQQVNvWBWL076TOSdBsno8-1oh4zWrXsbRa_iA1GyDQ_QM5Cpf11WE6tfvTDJsEHT_6GBQ8qz8FWSh4P_YtVDTOZZhDbbdddFeZPnQdxkLWXBhpD_jw8JuuE1qR_rAUytWdJpSjz2V90mQ",
+  "token_type": "bearer",
+  "session_state": "965f7351-2e8b-4528-9f3d-ee6283a95b16",
+  "expires_in": 300,
+  "refresh_expires_in": 1800
+}
diff --git a/src/test/resources/VersionInfo.json b/src/test/resources/VersionInfo.json
new file mode 100644
index 0000000..35510d9
--- /dev/null
+++ b/src/test/resources/VersionInfo.json
@@ -0,0 +1,3 @@
+{
+  "backendVersion": "0x.0x.xx"
+}
\ No newline at end of file
diff --git a/src/test/resources/testErrorReturn.json b/src/test/resources/testErrorReturn.json
new file mode 100644
index 0000000..f5540af
--- /dev/null
+++ b/src/test/resources/testErrorReturn.json
@@ -0,0 +1,4 @@
+{
+  "errorText": "TESTAT",
+  "errorCode": 999
+}
diff --git a/src/test/resources/testGeneralReturnItem.json b/src/test/resources/testGeneralReturnItem.json
new file mode 100644
index 0000000..34f9d39
--- /dev/null
+++ b/src/test/resources/testGeneralReturnItem.json
@@ -0,0 +1,3 @@
+{
+  "ret" : "It works!"
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles.json b/src/test/resources/testKeyCloakRoles.json
new file mode 100644
index 0000000..04088f1
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles.json
@@ -0,0 +1,70 @@
+[
+  {
+    "id": "e423626e-4616-45b7-9c3d-10a7f0acab8c",
+    "name": "elogbook-superuser",
+    "description": "Darf sehr sehr viel",
+    "scopeParamRequired": false,
+    "composite": true,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "7a145be5-20ba-4992-ad54-17c28d0bc0f9",
+    "name": "feedin-management-access",
+    "scopeParamRequired": false,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "b1cf034b-bce3-4d29-9e9d-692bf420ce83",
+    "name": "planned-policies-access",
+    "scopeParamRequired": false,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "baf44fc2-7888-4888-beaa-79288e9268a0",
+    "name": "planning-access",
+    "scopeParamRequired": false,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "b20abd6d-f202-41d5-91e2-f3e8266bd1fb",
+    "name": "offline_access",
+    "description": "${role_offline-access}",
+    "scopeParamRequired": true,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "173ed3dd-7c83-4202-bec8-c2f2ab9919fc",
+    "name": "uma_authorization",
+    "description": "${role_uma_authorization}",
+    "scopeParamRequired": false,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "384e7a68-8e70-41aa-bbbd-1a0ffb293335",
+    "name": "elogbook-access",
+    "scopeParamRequired": false,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  },
+  {
+    "id": "6b8d2da8-220c-4f83-8e15-889004e66359",
+    "name": "elogbook-normaluser",
+    "description": "Darf vieles, aber nicht alles",
+    "scopeParamRequired": false,
+    "composite": false,
+    "clientRole": false,
+    "containerId": "elogbook"
+  }
+]
diff --git a/src/test/resources/testKeyCloakUsers.json b/src/test/resources/testKeyCloakUsers.json
new file mode 100644
index 0000000..c590535
--- /dev/null
+++ b/src/test/resources/testKeyCloakUsers.json
@@ -0,0 +1,90 @@
+[
+  {
+    "id": "359ef9c9-77df-4a3d-a9c9-f96d837d2d57",
+    "createdTimestamp": 1501594173784,
+    "username": "admin",
+    "enabled": true,
+    "totp": false,
+    "emailVerified": false,
+    "firstName": "Administrator",
+    "lastName": "Administratowich",
+    "realmRoles": [
+      "elogbook-superuser",
+      "elogbook_access",
+      "feedin_management_access",
+      "planned_policies_access",
+      "offline_access",
+      "uma_authorization",
+      "planning_access",
+      "elogbook-normaluser"
+    ],
+    "disableableCredentialTypes": [
+      "password"
+    ],
+    "requiredActions": [],
+    "access": {
+      "manageGroupMembership": false,
+      "view": true,
+      "mapRoles": false,
+      "impersonate": false,
+      "manage": false
+    }
+  },
+  {
+    "id": "c4b78aa7-91d2-45d7-8ca3-163156d9ee40",
+    "createdTimestamp": 1501594239066,
+    "username": "hugo",
+    "enabled": true,
+    "totp": false,
+    "emailVerified": false,
+    "firstName": "Hugo",
+    "lastName": "Boss",
+    "realmRoles": [
+      "elogbook_access",
+      "feedin_management_access",
+      "planned_policies_access",
+      "offline_access",
+      "uma_authorization",
+      "planning_access",
+      "elogbook-normaluser"
+    ],
+    "disableableCredentialTypes": [
+      "password"
+    ],
+    "requiredActions": [],
+    "access": {
+      "manageGroupMembership": false,
+      "view": true,
+      "mapRoles": false,
+      "impersonate": false,
+      "manage": false
+    }
+  },
+  {
+    "id": "c2e9d7ae-2bfa-4578-b09e-f5dc5f09a879",
+    "createdTimestamp": 1501594273661,
+    "username": "otto",
+    "enabled": true,
+    "totp": false,
+    "emailVerified": false,
+    "firstName": "Otto",
+    "lastName": "Normalverbraucher",
+    "realmRoles": [
+      "elogbook_access",
+      "offline_access",
+      "uma_authorization",
+      "elogbook-normaluser"
+    ],
+    "disableableCredentialTypes": [
+      "password"
+    ],
+    "requiredActions": [],
+    "access": {
+      "manageGroupMembership": false,
+      "view": true,
+      "mapRoles": false,
+      "impersonate": false,
+      "manage": false
+    }
+  }
+]
\ No newline at end of file
diff --git a/src/test/resources/testLoginCredentials.json b/src/test/resources/testLoginCredentials.json
new file mode 100644
index 0000000..88974c6
--- /dev/null
+++ b/src/test/resources/testLoginCredentials.json
@@ -0,0 +1,4 @@
+{
+  "userName": "Carlo",
+  "password": "Cottura"
+}
\ No newline at end of file
diff --git a/src/test/resources/testUserAuthentication.json b/src/test/resources/testUserAuthentication.json
new file mode 100644
index 0000000..2cdef21
--- /dev/null
+++ b/src/test/resources/testUserAuthentication.json
@@ -0,0 +1,8 @@
+{
+  "id": 1,
+  "selected": true,
+  "username": "Pedro",
+  "password": "pwd",
+  "name": "Pedro Pepito Sanchez",
+  "specialUser": false
+}