Merge "Test Eclipse Gitea Connect Gerrit" into DEVELOP_BE
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/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..11ecb79
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,198 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+   distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+    i) changes to the Program, and
+   ii) additions to the Program;
+
+   where such changes and/or additions to the Program originate from and are
+   distributed by that particular Contributor. A Contribution 'originates' from
+   a Contributor if it was added to the Program by such Contributor itself or
+   anyone acting on such Contributor's behalf. Contributions do not include
+   additions to the Program which: (i) are separate modules of software
+   distributed in conjunction with the Program under their own license
+   agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+  a) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free copyright license to
+     reproduce, prepare derivative works of, publicly display, publicly perform,
+     distribute and sublicense the Contribution of such Contributor, if any, and
+     such derivative works, in source code and object code form.
+  b) Subject to the terms of this Agreement, each Contributor hereby grants
+     Recipient a non-exclusive, worldwide, royalty-free patent license under
+     Licensed Patents to make, use, sell, offer to sell, import and otherwise
+     transfer the Contribution of such Contributor, if any, in source code and
+     object code form. This patent license shall apply to the combination of the
+     Contribution and the Program if, at the time the Contribution is added by
+     the Contributor, such addition of the Contribution causes such combination
+     to be covered by the Licensed Patents. The patent license shall not apply
+     to any other combinations which include the Contribution. No hardware per
+     se is licensed hereunder.
+  c) Recipient understands that although each Contributor grants the licenses to
+     its Contributions set forth herein, no assurances are provided by any
+     Contributor that the Program does not infringe the patent or other
+     intellectual property rights of any other entity. Each Contributor
+     disclaims any liability to Recipient for claims brought by any other entity
+     based on infringement of intellectual property rights or otherwise. As a
+     condition to exercising the rights and licenses granted hereunder, each
+     Recipient hereby assumes sole responsibility to secure any other
+     intellectual property rights needed, if any. For example, if a third party
+     patent license is required to allow Recipient to distribute the Program, it
+     is Recipient's responsibility to acquire that license before distributing
+     the Program.
+  d) Each Contributor represents that to its knowledge it has sufficient
+     copyright rights in its Contribution, if any, to grant the copyright
+     license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its
+own license agreement, provided that:
+
+  a) it complies with the terms and conditions of this Agreement; and
+  b) its license agreement:
+      i) effectively disclaims on behalf of all Contributors all warranties and
+         conditions, express and implied, including warranties or conditions of
+         title and non-infringement, and implied warranties or conditions of
+         merchantability and fitness for a particular purpose;
+     ii) effectively excludes on behalf of all Contributors all liability for
+         damages, including direct, indirect, special, incidental and
+         consequential damages, such as lost profits;
+    iii) states that any provisions which differ from this Agreement are offered
+         by that Contributor alone and not by any other party; and
+     iv) states that source code for the Program is available from such
+         Contributor, and informs licensees how to obtain it in a reasonable
+         manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+  a) it must be made available under this Agreement; and
+  b) a copy of this Agreement must be included with each copy of the Program.
+     Contributors may not remove or alter any copyright notices contained within
+     the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor to
+control, and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may participate in
+any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its exercise of
+rights under this Agreement , including but not limited to the risks and costs
+of program errors, compliance with applicable laws, damage to or loss of data,
+programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted under
+Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue and
+survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation
+may assign the responsibility to serve as the Agreement Steward to a suitable
+separate entity. Each new version of the Agreement will be given a
+distinguishing version number. The Program (including Contributions) may always
+be distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to distribute the Program (including its Contributions)
+under the new version. Except as expressly stated in Sections 2(a) and 2(b)
+above, Recipient receives no rights or licenses to the intellectual property of
+any Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted under
+this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
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/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/get_started.txt b/deploy/get_started.txt
new file mode 100644
index 0000000..51ff81f
--- /dev/null
+++ b/deploy/get_started.txt
@@ -0,0 +1,92 @@
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+GET STARTED
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+
+---------------- REQUIREMENTS -------------
+Java 1.8
+Apache Maven 3.5.0
+
+IF you have this versions, check if you have set JAVA_HOME and M2_HOME.
+    - If yes ignore step 1 and 2
+    - If no follow the corresponding steps below
+
+-------------------- 1 ---------------------
+Install java 8
+
+- Open a cmd and check your java version
+    $ java -version
+- If you dont have java version 1.8 then download and install it from:
+        http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
+- Set JAVA_HOME (Windows OS):
+    Right click on This Computer and select Properties.
+    On the Advanced tab, select Environment Variables, and then edit JAVA_HOME to point to where the JDK software is located, for example, C:\Program Files\Java\jdk1.8.xxx.
+    Also, edit The Path variable in System variables and add the bin path (C:\Program Files\Java\jdk1.8.xxx\bin)
+- Restart your PC
+- Confirm by checking the version
+    $ java -version
+
+
+-------------------- 2 ---------------------
+Install Apache Maven to your pc
+
+Maven is a tool that can be used for building and managing any Java-based project.
+
+- Download maven 3.5.0 from
+        https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.0/
+- Extract the folder and place it on your C drive
+- Set M2_HOME (Windows OS):
+    - Right click on This Computer and select Properties.
+    - On the Advanced tab, select Environment Variables, and then create M2_HOME to point to where the Maven software is located, for example, C:\apache-maven-3.5.0.
+    - Also edit The Path variable in System variables and add the bin path (C:\apache-maven-3.5.0\bin)
+- Restart your PC
+- Confirm with
+    $ mvn -v
+
+-------------------- 3 ---------------------
+To get started with the project you have to clone all four(elogbook and portal backend-frontend ) projects.
+
+- Create a folder and do following for each of them
+- Open a cmd and navigate to the folder
+- Use the command to create a clone of each project
+    § git clone <project_url>
+- If you are going to develop, important is a switch to the develop branch
+    - navigate in the folder with the clone and switch to develop branch
+        $ git checkout <branch>
+- At the end just pull the actual version of the code
+    $ git pull origin <branch>
+
+
+--------------------------
+Active Develop Branches: |
+Backend -> DEVELOP_BE    |
+Frontend -> DEVELOP_FE   |
+-------------------------|
+Stable Branches: master  |
+--------------------------
+
+
+-------------------- 4 ---------------------
+Build the maven project
+
+Building the maven project, will produce a <project_name>.war file(Web Application Archive), which is needed to run the project.
+- Open a command line and navigate to the root folder of the backend project
+- Use the following call to cleanly build and install artifacts into the local repository:
+    $ mvn clean install
+
+-------------------- 5 ---------------------
+Open and familiarize yourself with the project
+
+- If you successfully build the maven project you can find in /target/generated-docs all the documentations of this projects
+    - auth_n_auth_howtoBuild -> here you can read how to build the whole (backend and frontend) project
+    - auth_n_auth_howtoRun -> here you can read how to run the Application
+    - auth_n_auth_architectureDocumentation -> here you can read about the architecture documetation this module
+    - auth_n_auth_interfaceDocumentation -> here you can read about the backend REST Services which are used
+
+- Other useful files:
+    - /target/site/jacoco/index.html -> jacoco code coverage review
+    - /target/surefire-reports -> test reports
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+NEXT STEP -> READ THE auth_n_auth_howtoBuild FILE !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
\ No newline at end of file
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..9c27fd5
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,298 @@
+<?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.1.2</version>
+    <packaging>war</packaging>
+
+    <properties>
+        <skip.asciidoc>false</skip.asciidoc>
+        <httpclient.version>4.5.13</httpclient.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>2.0.9</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.8.6</jacoco-maven-plugin.version>
+        <sonar-maven-plugin.version>3.0.2</sonar-maven-plugin.version>
+        <dependency-check-maven.version>6.1.5</dependency-check-maven.version>
+        <keycloak.version>12.0.4</keycloak.version>
+    </properties>
+
+    <profiles>
+        <profile>
+            <id>local-fast-build</id>
+            <properties>
+                <skip.asciidoc>true</skip.asciidoc>
+                <maven.test.skip>false</maven.test.skip>
+            </properties>
+        </profile>
+        <profile>
+            <id>securitycheck</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.owasp</groupId>
+                        <artifactId>dependency-check-maven</artifactId>
+                        <version>${dependency-check-maven.version}</version>
+                        <configuration>
+                            <skipProvidedScope>true</skipProvidedScope>
+                            <skipRuntimeScope>true</skipRuntimeScope>
+                            <failBuildOnCVSS>7</failBuildOnCVSS>
+                            <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
+                            <suppressionFiles>${basedir}/securitycheck/suppressed.xml</suppressionFiles>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.owasp</groupId>
+            <artifactId>dependency-check-maven</artifactId>
+            <version>${dependency-check-maven.version}</version>
+            <type>maven-plugin</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.glassfish.jersey.bundles</groupId>
+            <artifactId>jaxrs-ri</artifactId>
+            <version>2.22.1</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.15.0</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>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>
+            <scope>test</scope>
+        </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>3.3.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/securitycheck/suppressed.xml b/securitycheck/suppressed.xml
new file mode 100644
index 0000000..7ddc0b5
--- /dev/null
+++ b/securitycheck/suppressed.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
+
+    <!-- log4j wird bei uns nur lokal genutzt ohne Netzwerkkommunikation. -->
+    <suppress>
+        <notes><![CDATA[
+      file name: log4j-1.2.16.jar
+      ]]></notes>
+        <packageUrl regex="true">^pkg:maven/log4j/log4j@.*$</packageUrl>
+        <vulnerabilityName>CVE-2019-17571</vulnerabilityName>
+    </suppress>
+
+    <!-- log4j wird bei uns nur lokal genutzt ohne Netzwerkkommunikation. -->
+    <suppress>
+        <notes><![CDATA[
+   file name: log4j-1.2.16.jar
+   ]]></notes>
+        <packageUrl regex="true">^pkg:maven/log4j/log4j@.*$</packageUrl>
+        <vulnerabilityName>CVE-2020-9488</vulnerabilityName>
+    </suppress>
+</suppressions>
\ No newline at end of file
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..3281812
--- /dev/null
+++ b/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc
@@ -0,0 +1,958 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+*     http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+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",
+  "maxLoadUsers": 1000
+}
+----
+* *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
+* *maxLoadUsers* - Sets the maximum of users that are loaded from keycloak. KC itself is limited here. The value
+should be set to the amount of *all* users in the target "keycloakRealm".
+
+
+.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]
+
+Go to tab `Mappers`. Press `Create`...
+
+.Mappers of elogbook-backend
+[option="header,footer"]
+image::CreateMapper.png[Mapper settings]
+
+and add the `role` mapping accordingly:
+
+.Role mapper
+[option="header,footer"]
+image::CreateRoleMapper.png[Role mapper 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
+- planned-policies-normaluser
+- planned-policies-superuser
+
+. Configuring a superuser role. Under Roles, hit on a superuser(elogbook-superuser or planned-policies-superuser) or press `Edit`
+.. Switch `Composite Roles` to on.
+.. Add the Realm Role 'elogbook-normaluser' or 'planned-policies-normaluser' correspondingly 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
+
+... User right in the distinct modul Planned Grid Measures (`planned-policies-access` required of course):
+- planned-policies-normaluser = standard user in the plannedGridMeasures-app
+- planned-policies-superuser = admin user in the plannedGridMeasures-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' or 'planned-policies-superuser' instead of
+'elogbook-normaluser' or 'planned-policies-normaluser' correspondingly.
+
+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/howto/auth_n_auth_howtoBuild.adoc b/src/main/asciidoc/howto/auth_n_auth_howtoBuild.adoc
new file mode 100644
index 0000000..f71a473
--- /dev/null
+++ b/src/main/asciidoc/howto/auth_n_auth_howtoBuild.adoc
@@ -0,0 +1,97 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+*     http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+= openKonsequenz - How to build the module "portal@openK"
+:Date: 2017-11-17
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+<<<
+
+== Requirements
+* Apache Tomcat 8.0.30
+* Node.js 6.10.0
+* Angular-CLI
+* Graphviz
+
+== How to build the Backend
+To build the backend you need to have installed Apache Maven and Java (look at `/deploy/`*get_started.txt*).
+
+=== Install and Configure Apache Tomcat
+Tomcat is an open-source Java Servlet Container and provides a "pure Java" HTTP web server environment in which Java code can run.
+
+* Download Tomcat version 8.0.30 from https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.30/bin/
+and extract it (apache-tomcat-8-0-30.zip).
+* Place the extracted folder on your C drive.
+* Configure Tomcat:
+** Configure the *context.xml* file. Copy the *<Parameter … >* block from the project file `deploy/conf/`*context.xml*
+and paste it in the `<tomcat>/conf/`*context.xml* in the *<Context>* block.
+** Or just paste this line there:
+
+ <Parameter name="OK_PORTAL_ENVIRONMENT" override="false" value="DevLocal"/>
+
+** Dont forget to save it.
+
+TIP: For more informations check *Deployment View* in Chapter *http://87.128.212.254:8880/portalFE_ADoc/auth_n_auth_architectureDocumentation.html[auth_n_auth_architectureDocumentation]*.
+
+
+=== Install Graphviz
+Graphviz is open source graph visualization software. You need this software because of auto-generated graphics in the documentations.
+
+* Download and install Graphviz from http://www.graphviz.org/Download_windows.php
+* If not, set the PATH variable
+
+ Name of variable: GRAPHVIZ_DOT
+ Value of variable: <GRAPHVIZ_DIR>\bin\dot.exe
+
+
+== How to build the Frontend
+
+=== Install Node.js
+
+Node.js is an open-source, cross-platform JavaScript run-time environment for executing JavaScript (also Typescript which is a strongly typed form of JavaScript) code server-side.
+
+* Download Node.js 6.10.0 from https://nodejs.org/download/release/v6.10.0/ by clicking on a xxx.msi image for windows.
+* Run the downloaded Node.js .msi Installer - including accepting the license, selecting the destination, and authenticating for the install.
+This requires Administrator privileges, and you may need to authenticate
+* To ensure Node.js has been installed, run the following in your terminal - you should get something like v6.10.0
+
+[source,command]
+----
+    $ node -v
+----
+{blank}
+
+=== Update the npm Angular-CLI client
+This package manager comes bundled with Node.js and its good to have the latest version.
+
+* Open a command line and navigate to the root folder of the frontend project
+* Run the following commands (the version is defined in the package.json file):
+
+[source,command]
+----
+    $ npm install --save-dev @angular/cli
+----
+{blank}
+
+[source,command]
+----
+    $ npm install
+----
+{blank}
+
+TIP: Next Step -> Read the *auth_n_auth_howtoRun* file!
+
+
+
+
diff --git a/src/main/asciidoc/howto/auth_n_auth_howtoRun.adoc b/src/main/asciidoc/howto/auth_n_auth_howtoRun.adoc
new file mode 100644
index 0000000..bddebfc
--- /dev/null
+++ b/src/main/asciidoc/howto/auth_n_auth_howtoRun.adoc
@@ -0,0 +1,81 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+*     http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+= openKonsequenz - How to run the module "portal@openK"
+:Date: 2017-11-17
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+<<<
+
+== Requirements
+* Browser (Chrome or IE11 suggested)
+
+== Prerequisites
+
+* KeyCloak 3.2.1 Final (look at the *http://87.128.212.254:8880/portalFE_ADoc/auth_n_auth_architectureDocumentation.html[auth_n_auth_architectureDocumentation]* in *Deployment View* Chapter for install instructions)
+
+IMPORTANT: KeyCloak must be installed for a successful login at the application!
+
+== How to run the Backend
+To run the backend you need to have installed and configured Apache Tomcat (look at *auth_n_auth_howtoBuild*).
+
+=== Set up and start Apache Tomcat
+Tomcat needs the Web Application Archive (war) file, which is produced by building the maven project, to run the application.
+
+* Copy the *portal.war* file from the project file `/target` in the `<tomcat>/webapps` file. If there is a folder named *portal*, delete it before.
+* Navigate to `C:\apache-tomcat-8.0.30\bin` and start Tomcat by clicking on *startup.bat*.
+* Tomcat's default port is *8080*.
+
+[source,text]
+----
+If 8080 port is already in use, you have to change tomcat's port as follows:
+- Go to <tomcat>/conf folder
+- Open server.xml file and search for "Connector port"
+- Replace "8080" by your port number (for example 8181)
+- Restart tomcat server (in the same folder which startup.bat is located, you can also find a shutdown.bat file).
+----
+{blank}
+
+IMPORTANT: If you change the port number you have also adapt the port in the
+frontend project: File "<PRJ_portalFE>/proxy.conf.json". There might be other config files
+that need to be adepted as well!
+
+TIP: Look at the *http://87.128.212.254:8880/portalFE_ADoc/auth_n_auth_interfaceDocumentation.html[auth_n_auth_interfaceDocumentation]* for informations about the services.
+
+== How to run the Frontend
+To run the frontend project you need to have installed and updated Node.js and npm Angular-CLI.
+
+=== Compile the Frontend
+
+To compile say Angular-CLI to start.
+
+* Open a command line and navigate to the root folder of the frontend project
+* Run the command
+
+[source,command]
+----
+   $  npm start
+----
+{blank}
+
+* Open a browser and type:
+
+[source,http]
+----
+    http://localhost:4201
+----
+{blank}
+
+IMPORTANT: To open the *Betriebstagebuch* module you have to run the *elogbook* application too.
+
diff --git a/src/main/asciidoc/images/CreateMapper.png b/src/main/asciidoc/images/CreateMapper.png
new file mode 100644
index 0000000..0c835cb
--- /dev/null
+++ b/src/main/asciidoc/images/CreateMapper.png
Binary files differ
diff --git a/src/main/asciidoc/images/CreateRoleMapper.png b/src/main/asciidoc/images/CreateRoleMapper.png
new file mode 100644
index 0000000..19e6ea0
--- /dev/null
+++ b/src/main/asciidoc/images/CreateRoleMapper.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/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/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..d9aed64
--- /dev/null
+++ b/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc
@@ -0,0 +1,402 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+*     http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+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*:
+
+=== Get health state
+This service returns the health state of this module.
+
+*URL:* /healthcheck/pretty=true
+
+*Method:* GET
+
+
+
+*Request-Headers*:
+
+* Authorization – none
+
+
+*Produces*: application/json
+
+*Response*:
+
+If the module is healthy then...
+[source,json]
+----
+{"Keycloak present":{"healthy":true}}
+----
+
+If the module is *not* healthy...
+[source,json]
+----
+{
+    "Keycloak present":
+    {
+        "healthy":false,
+        "message":"<Error message>"
+    }
+}
+----
+
+
+*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..2bef7fd
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java
@@ -0,0 +1,23 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..5518bf6
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java
@@ -0,0 +1,25 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..6f6ffe3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java
@@ -0,0 +1,113 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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;
+
+    //Since Keycloak 4.8.3 "aud" Parameter is an array now
+    //Pre 4.8.3 "aud" was a single String
+    //We keep it for documentation reasons
+    //private String[] aud; //NOSONAR
+    //private String aud; //NOSONAR
+    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 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..05df537
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..6be7f95
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java
@@ -0,0 +1,19 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..e428466
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java
@@ -0,0 +1,43 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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/KeyCloakClientRoles.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakClientRoles.java
new file mode 100644
index 0000000..6536a21
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakClientRoles.java
@@ -0,0 +1,45 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+
+public class KeyCloakClientRoles {
+
+  private String id;
+  private String client;
+  private List<KeyCloakRole> mappings;
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(String id) {
+    this.id = id;
+  }
+
+  public String getClient() {
+    return client;
+  }
+
+  public void setClient(String client) {
+    this.client = client;
+  }
+
+  public List<KeyCloakRole> getMappings() {
+    return mappings;
+  }
+
+  public void setMappings(List<KeyCloakRole> mappings) {
+    this.mappings = mappings;
+  }
+}
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..04ea3e1
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java
@@ -0,0 +1,79 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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/KeyCloakRoles.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRoles.java
new file mode 100644
index 0000000..643b105
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRoles.java
@@ -0,0 +1,38 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+import java.util.Map;
+
+public class KeyCloakRoles {
+
+  List<KeyCloakRole> realmMappings;
+
+  private Map<String, KeyCloakClientRoles> clientMappings;
+
+  public List<KeyCloakRole> getRealmMappings() {
+    return realmMappings;
+  }
+
+  public void setRealmMappings(List<KeyCloakRole> realmMappings) {
+    this.realmMappings = realmMappings;
+  }
+
+  public Map<String, KeyCloakClientRoles> getClientMappings() {
+    return clientMappings;
+  }
+
+  public void setClientMappings(Map<String, KeyCloakClientRoles> clientMappings) {
+    this.clientMappings = clientMappings;
+  }
+}
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..58aeb90
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java
@@ -0,0 +1,110 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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 String name;
+    private List<String> allRoles;
+    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 void setTotp(boolean totp) { this.totp = totp; }
+
+    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> getAllRoles() {
+        return allRoles;
+    }
+
+    public void setAllRoles(List<String> allRoles) {
+        this.allRoles = allRoles;
+    }
+
+    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;
+    }
+
+    public void setName() {
+        if (lastName!= null && !lastName.isEmpty()){
+            this.name = firstName+ " " + lastName;
+        } else {
+            this.name = firstName;
+        }
+    }
+}
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..48b158f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java
@@ -0,0 +1,31 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..3d3ce96
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java
@@ -0,0 +1,228 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.util;
+
+import java.io.*;
+import java.net.URLEncoder;
+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.KeyCloakClientRoles;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRoles;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+
+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;
+
+import static org.eclipse.openk.portal.common.JsonGeneratorBase.getGson;
+
+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 = null;
+    try {
+      token = sendPost(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" +
+                      BackendConfig.getInstance().getKeycloakRealm() + "/protocol/openid-connect/token",
+              "username=" + user + "&password=" + URLEncoder.encode(password, "UTF-8") + "&client_id="
+                      + BackendConfig.getInstance().getKeycloakClient() + "&grant_type=password");
+    } catch (UnsupportedEncodingException e) {
+      logger.error( "Unsupported Encoding Exception: ", e);
+      throw new PortalInternalServerError(e.getMessage());
+    }
+    return getJwtTokenFromJson(token);
+  }
+
+  public static boolean serviceAvailable() throws PortalInternalServerError {
+    String jsonRet = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" +
+                    BackendConfig.getInstance().getKeycloakRealm(), "", null);
+
+    return jsonRet != null ? jsonRet.contains("realm") && jsonRet.contains(BackendConfig.getInstance().getKeycloakRealm())
+                           : false;
+  }
+
+  public static List<KeyCloakUser> getUsers(JwtToken jwtToken, int maxUsers) throws PortalInternalServerError {
+    String users = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users?max="+maxUsers,
+        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/",
+        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 {
+      List<KeyCloakRole> allRoles = new ArrayList<>();
+      KeyCloakRoles keyCloakRoles = getGson().fromJson(json, KeyCloakRoles.class);
+      List<KeyCloakRole> realmRoles = keyCloakRoles.getRealmMappings();
+
+      if (realmRoles != null) {
+        allRoles.addAll(realmRoles);
+      }
+
+      Map<String, KeyCloakClientRoles> clientMappings = keyCloakRoles.getClientMappings();
+      if (clientMappings != null) {
+        KeyCloakClientRoles keyCloakClientRoles = clientMappings.get(BackendConfig.getInstance().getKeycloakClient());
+        if (keyCloakClientRoles != null){
+          List<KeyCloakRole> clientRoles = keyCloakClientRoles.getMappings();
+          allRoles.addAll(clientRoles);
+        }
+      }
+
+      return allRoles;
+    } 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
+    Base64.Decoder decoder = Base64.getDecoder();
+    byte[] decoded = decoder.decode(jwtPayload);
+    jwtPayload = new String(decoded, StandardCharsets.UTF_8);
+    logger.debug(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.trace("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, StandardCharsets.UTF_8))) {
+        String line;
+        while ((line = rd.readLine()) != null) {
+          response.append(line);
+          response.append('\r');
+          logger.trace("Got line -> " + line);
+        }
+      }
+      logger.trace("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.debug("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; charset=utf-8");
+      con.setRequestProperty("Accept", MediaType.APPLICATION_JSON);
+      con.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes(StandardCharsets.UTF_8.name()).length));
+
+      con.setInstanceFollowRedirects(false);
+      con.setDoOutput(true);
+      // Send request
+      try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
+        wr.write(urlParameters.getBytes(StandardCharsets.UTF_8.name()));
+      }
+      // Get Response
+      InputStream is = con.getInputStream();
+
+      try (BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8.name()))) {
+        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..4ac8a11
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java
@@ -0,0 +1,80 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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 Integer maxLoadUsers;
+
+    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 Integer getMaxLoadUsers() {
+        return maxLoadUsers;
+    }
+
+    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..b11101b
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/Globals.java
@@ -0,0 +1,52 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..fd364b8
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java
@@ -0,0 +1,51 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..61d7e63
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java
@@ -0,0 +1,65 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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;
+            case "Docker":
+                backendConfigFile="backendConfigDocker.json";
+                moduleConfigFile="moduleConfigDocker.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..0d9be8f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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.debug("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..43e0ca5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java
@@ -0,0 +1,26 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..3a192f1
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java
@@ -0,0 +1,71 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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());
+      if( token == null ) {
+        LOGGER.error("Login for getKeyCloakUsersFromToken() failed for User:"+ BackendConfig.getInstance().getKeycloakAdmin());
+        return;
+      }
+
+      List<KeyCloakUser> allUsersWithRoles = getKeyCloakUsersFromToken(token);
+
+      if( allUsersWithRoles.isEmpty()) {
+        LOGGER.warn("getKeyCloakUsersFromToken provided empty list!");
+      }
+
+      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, BackendConfig.getInstance().getMaxLoadUsers());
+    List<KeyCloakUser> allUsersWithRoles = new ArrayList<>();
+
+    for (KeyCloakUser user : allUsers) {
+      List<String> rolesList = new ArrayList<>();
+      List<KeyCloakRole> rolesForUser = JwtHelper.getRolesForUser(token, user.getId());
+      user.setName();
+      for (KeyCloakRole keyCloakRole : rolesForUser) {
+        rolesList.add(keyCloakRole.getName());
+      }
+      user.setAllRoles(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..df13cbf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java
@@ -0,0 +1,32 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..7262f5f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java
@@ -0,0 +1,82 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..cb5d9d3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java
@@ -0,0 +1,36 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..0ad7143
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BackendController.java
@@ -0,0 +1,113 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+
+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.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+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> getUsersForRole(String roleToCheck) {
+        List<KeyCloakUser> usersWithRole = new ArrayList<>();
+        List<KeyCloakUser> keyCloakUsers = UserCache.getInstance().getKeyCloakUsers();
+
+        for (KeyCloakUser user : keyCloakUsers) {
+            List<String> allRoles = user.getAllRoles();
+            if (allRoles ==  null) {
+                continue;
+            }
+
+            for (String role : allRoles) {
+                if(role.equals(roleToCheck)){
+                    usersWithRole.add(user);
+                    break;
+                }
+            }
+        }
+
+        return usersWithRole;
+    }
+
+
+    public JwtToken authenticate(String credentials) throws PortalException {
+        LOGGER.debug("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.debug("authenticate() succeeded.");
+        return token;
+    }
+
+    public VersionInfo getVersionInfo() {
+        LOGGER.debug("getVersionInfo() is called");
+
+        String version = getClass().getPackage().getImplementationVersion();
+        VersionInfo vi = new VersionInfo();
+        vi.setBackendVersion(version);
+
+        LOGGER.debug("getVersionInfo() is finished");
+        return vi;
+    }
+
+    public List<UserModule> getUserModuleList() {
+        LOGGER.debug("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.debug("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..cb4b50c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java
@@ -0,0 +1,39 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..fc04dc4
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java
@@ -0,0 +1,78 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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.trace(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.trace(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.debug("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..8d3fb8e
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java
@@ -0,0 +1,111 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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 {
+
+        @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..fc094a5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java
@@ -0,0 +1,67 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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);
+        } 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 { // NOSONAR 24.09.2018: There's a great possibility that we need a whitebox-charecter check for security reasons again. Because of this, we leave this code
+        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..afa57cf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java
@@ -0,0 +1,60 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..f38e01c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java
@@ -0,0 +1,147 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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.debug("Session expired for User " + user);
+            }
+            registry.remove(token); // we're done
+            LOGGER.debug("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..28a63f5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..3e8ba82
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..db1b187
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java
@@ -0,0 +1,43 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..dd5937e
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..5c446b3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..acee53c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..bc264cf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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/health/base/HealthCheck.java b/src/main/java/org/eclipse/openk/portal/health/base/HealthCheck.java
new file mode 100644
index 0000000..f6bc66c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/HealthCheck.java
@@ -0,0 +1,17 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+public abstract class HealthCheck {
+
+    protected abstract Result check() throws Exception; // NOSONAR
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/HealthChecker.java b/src/main/java/org/eclipse/openk/portal/health/base/HealthChecker.java
new file mode 100644
index 0000000..34ebd90
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/HealthChecker.java
@@ -0,0 +1,47 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+*/
+package org.eclipse.openk.portal.health.base;
+
+import org.apache.log4j.Logger;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class HealthChecker {
+    private static final Logger logger = Logger.getLogger(HealthChecker.class);
+
+    private List<HealthCheck> registeredHealthChecks = new LinkedList<>();
+    private Map<HealthCheck, String> namingMap = new HashMap<>();
+
+    public void register( String title, HealthCheck hc ) {
+        namingMap.put(hc, title);
+        registeredHealthChecks.add(hc);
+    }
+
+    public List<NamedHealthCheckResult> performHealthChecks() {
+        List<NamedHealthCheckResult> hcList = new LinkedList<>();
+        for( HealthCheck hc : registeredHealthChecks) {
+            try {
+                hcList.add(new NamedHealthCheckResult(namingMap.get(hc), hc.check()));
+
+            } catch (Throwable t) { // NOSONAR  we definately want to catch everything here!!!
+                logger.error("Error during healthcheck", t);
+                hcList.add(new NamedHealthCheckResult(namingMap.get(hc),
+                        Result.unhealthy("Exception during test: "+t+" -> See Log!")));
+            }
+        }
+        return hcList;
+    }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResult.java b/src/main/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResult.java
new file mode 100644
index 0000000..9726cb9
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResult.java
@@ -0,0 +1,53 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+import com.google.gson.GsonBuilder;
+
+import java.util.List;
+
+public class NamedHealthCheckResult {
+    private String name;
+    private Result result;
+
+    public NamedHealthCheckResult( String name, Result result ) {
+        this.name = name;
+        this.result = result;
+    }
+
+    public String toJson() {
+        StringBuffer buffer = new StringBuffer(); // NOSONAR - _fd we don't a new dependency because of this
+        buffer.append("\""+name+"\":");
+        buffer.append(new GsonBuilder().disableHtmlEscaping().create().toJson(result));
+        return buffer.toString();
+    }
+
+    public static String toJson(List<NamedHealthCheckResult> resultArray ) {
+        StringBuilder builder = new StringBuilder();
+        builder.append('{');
+        for( int i=0; i < resultArray.size(); i++ ) {
+            builder.append(resultArray.get(i).toJson());
+            if( i+1 < resultArray.size() ) {
+                builder.append(',');
+            }
+        }
+        return builder.append('}').toString();
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Result getResult() {
+        return result;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/Result.java b/src/main/java/org/eclipse/openk/portal/health/base/Result.java
new file mode 100644
index 0000000..6ff7de7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/Result.java
@@ -0,0 +1,41 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+
+public class Result {
+    private boolean healthy;
+    private String message;
+
+    private Result() {}
+
+    public static Result healthy() {
+        Result res = new Result();
+        res.healthy = true;
+        return res;
+    }
+
+    public static Result unhealthy(String message) {
+        Result res = new Result();
+        res.healthy = false;
+        res.message = message;
+        return res;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public boolean isHealthy() {
+        return healthy;
+    }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheck.java b/src/main/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheck.java
new file mode 100644
index 0000000..80a7b52
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheck.java
@@ -0,0 +1,37 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.impl;
+
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.eclipse.openk.portal.health.base.HealthCheck;
+import org.eclipse.openk.portal.health.base.Result;
+
+public class KeyCloakPresentHealthCheck extends HealthCheck {
+
+    protected boolean checkit() throws PortalInternalServerError {
+        return JwtHelper.serviceAvailable();
+    }
+
+    @Override
+    protected Result check() throws Exception {
+        if( checkit() ) {
+            return Result.healthy();
+        }
+        else {
+            BackendConfig gc = BackendConfig.getInstance();
+            String msg = gc.getAuthServerUrl() + "/" + gc.getKeycloakRealm();
+            return Result.unhealthy("KeyCloak-Service not available: "+msg);
+        }
+    }
+}
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..4f6fb0a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java
@@ -0,0 +1,184 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.rest;
+
+import javax.ws.rs.*;
+
+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.health.base.HealthChecker;
+import org.eclipse.openk.portal.health.base.NamedHealthCheckResult;
+import org.eclipse.openk.portal.health.impl.KeyCloakPresentHealthCheck;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+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.debug("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.trace("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());
+    }
+
+    @GET
+    @Path("/healthcheck")
+    @Produces("application/json")
+    public Response getHealthCheck() {
+        HealthChecker hc = new HealthChecker();
+        hc.register("Keycloak present", new KeyCloakPresentHealthCheck());
+
+        String returnJson = NamedHealthCheckResult.toJson(hc.performHealthChecks());
+
+        try {
+            return ResponseBuilderWrapper.INSTANCE.buildOKResponse(returnJson);
+        } catch (PortalException e) {
+            logger.error("unexpected error", e);
+            return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+        }
+    }
+
+    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..42c8d50
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..1064078
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..a54f7d0
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..6c80d69
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java
@@ -0,0 +1,33 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..acb75f6
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java
@@ -0,0 +1,69 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..d1a671a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java
@@ -0,0 +1,42 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..70c18d3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java
@@ -0,0 +1,80 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..57bf001
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java
@@ -0,0 +1,26 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..430658e
--- /dev/null
+++ b/src/main/resources/_backendConfigCustom.json
@@ -0,0 +1,10 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://entjava002:8080/",
+  "keycloakRealm": "elogbook",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "admin",
+  "maxLoadUsers": 1000
+}
\ 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/backendConfigDevLocal.json b/src/main/resources/backendConfigDevLocal.json
new file mode 100644
index 0000000..38dd236
--- /dev/null
+++ b/src/main/resources/backendConfigDevLocal.json
@@ -0,0 +1,10 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://entopkon:8080/",
+  "keycloakRealm": "Elogbook",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "admin",
+  "maxLoadUsers": 1000
+}
\ 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..04e1609
--- /dev/null
+++ b/src/main/resources/backendConfigDevServer.json
@@ -0,0 +1,10 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://localhost:8080/",
+  "keycloakRealm": "Elogbook",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "admin",
+  "maxLoadUsers": 1000
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigDocker.json b/src/main/resources/backendConfigDocker.json
new file mode 100644
index 0000000..4820cf5
--- /dev/null
+++ b/src/main/resources/backendConfigDocker.json
@@ -0,0 +1,10 @@
+{
+  "internalSessionLengthMillis": 3600000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://172.25.0.66:8888/",
+  "keycloakRealm": "portaldocker",
+  "keycloakClient": "portal-docker",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "admin",
+  "maxLoadUsers": 1000
+}
\ 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..1ed733e
--- /dev/null
+++ b/src/main/resources/backendConfigProduction.json
@@ -0,0 +1,10 @@
+{
+  "internalSessionLengthMillis": 46800000,
+  "reloadUsersInSec": 300,
+  "authServerUrl": "http://localhost:8380/",
+  "keycloakRealm": "OpenKRealm",
+  "keycloakClient": "elogbook-backend",
+  "keycloakAdmin": "admin",
+  "keycloakPW": "admin",
+  "maxLoadUsers": 1000
+}
diff --git a/src/main/resources/moduleConfigDevLocal.json b/src/main/resources/moduleConfigDevLocal.json
new file mode 100644
index 0000000..5a4df1a
--- /dev/null
+++ b/src/main/resources/moduleConfigDevLocal.json
@@ -0,0 +1,76 @@
+[
+  {
+    "name": "Betriebstagebuch local 4200",
+    "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": "Betriebstagebuch local 8080",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:8080/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": "http://localhost:4220/",
+    "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"
+  },
+  {
+    "name": "Kontaktstammdaten",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4222",
+    "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+    "requiredRole": "kon-access"
+  },
+  {
+    "name": "Kontaktstammdaten local 8080",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:8080/contactdatabase",
+    "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+    "requiredRole": "kon-access"
+  },
+  {
+    "name": "Kontaktstammdaten local 4200",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:4200",
+    "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+    "requiredRole": "kon-access"
+  }
+]
diff --git a/src/main/resources/moduleConfigDevServer.json b/src/main/resources/moduleConfigDevServer.json
new file mode 100644
index 0000000..be2673b
--- /dev/null
+++ b/src/main/resources/moduleConfigDevServer.json
@@ -0,0 +1,121 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:8085/elogbookFE",
+    "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+    "requiredRole": "elogbook-access"
+
+  },
+  {
+    "name": "Betriebstagebuch (Web)",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://87.128.212.254: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": "plannedGridMeasures",
+    "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": "http://172.18.22.160:8880/plannedGridMeasures",
+    "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"
+  },
+  {
+    "name": "Geplante Maßnahmen (Web)",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://87.128.212.254:8880/plannedGridMeasures",
+    "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"
+  },
+  {
+    "name": "Kontaktstammdaten",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4222",
+    "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+    "requiredRole": "kon-access"
+  },
+  {
+    "name": "Kontaktstammdaten Feature Branch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4224",
+    "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+    "requiredRole": "kon-access"
+  },
+  {
+    "name": "SIT DEV",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4223",
+    "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+    "requiredRole": "grid-failure-access"
+  },
+  {
+    "name": "SIT Feature Branch - A",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4225",
+    "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+    "requiredRole": "grid-failure-access"
+  },
+  {
+    "name": "SIT Feature Branch - B",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4229",
+    "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+    "requiredRole": "grid-failure-access"
+  },
+  {
+    "name": "SIT Feature Backend",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://entdockergss:4226",
+    "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+    "requiredRole": "grid-failure-access"
+  },
+  {
+    "name": "SIT Localhost",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:4200",
+    "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+    "requiredRole": "grid-failure-access"
+  }
+]
diff --git a/src/main/resources/moduleConfigDocker.json b/src/main/resources/moduleConfigDocker.json
new file mode 100644
index 0000000..63832d7
--- /dev/null
+++ b/src/main/resources/moduleConfigDocker.json
@@ -0,0 +1,39 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://localhost:8080/ElogbookFrontend",
+    "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": "http://localhost:8080/GridMeasuresFrontend",
+    "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..fd8f7fd
--- /dev/null
+++ b/src/main/resources/moduleConfigProduction.json
@@ -0,0 +1,57 @@
+[
+  {
+    "name": "Betriebstagebuch",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "https://169.50.13.154/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://169.50.13.154/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": "http://169.50.13.154/plannedGridMeasures",
+    "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"
+  },
+  {
+    "name": "Kontaktstammdaten",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://169.50.13.154/contactdatabase",
+    "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+    "requiredRole": "kon-access"
+  },
+  {
+    "name": "Störungsinformationstool",
+    "cols": 1,
+    "rows": 1,
+    "color": "#ffffff",
+    "link": "http://169.50.13.154/gridfailureinformation",
+    "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+    "requiredRole": "grid-failure-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..2ce8042
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,49 @@
+<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>
+
+  <servlet>
+    <servlet-name>jersey-serlvet</servlet-name>
+    <servlet-class>
+      org.glassfish.jersey.servlet.ServletContainer
+    </servlet-class>
+    <init-param>
+      <param-name>jersey.config.server.provider.packages</param-name>
+      <param-value>org.eclipse.openk.portal.rest</param-value>
+    </init-param>
+    <load-on-startup>1</load-on-startup>
+
+  </servlet>
+
+
+  <servlet-mapping>
+    <servlet-name>jersey-serlvet</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..a441a8a
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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( 3600000, (int)bc.getInternalSessionLengthMillis() );
+        assertEquals( 300 , (int)bc.getReloadUsersInSec());
+        assertEquals( "http://entopkon:8080/", bc.getAuthServerUrl() );
+        assertEquals( "Elogbook", bc.getKeycloakRealm());
+        assertEquals( "elogbook-backend", bc.getKeycloakClient());
+        assertEquals( "admin", bc.getKeycloakAdmin() );
+        assertEquals( "admin", bc.getKeycloakPW() );
+        assertEquals( "backendConfigDevLocal.json", BackendConfig.getConfigFileName() );
+        BackendConfig.setConfigFileName("backendConfigProduction.json");
+        assertEquals( "backendConfigProduction.json", BackendConfig.getConfigFileName() );
+    }
+}
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..f805370
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java
@@ -0,0 +1,49 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..983c909
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java
@@ -0,0 +1,49 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..ef2455d
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java
@@ -0,0 +1,27 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..cf4f250
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java
@@ -0,0 +1,142 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNull;
+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.ArrayList;
+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.KeyCloakRoles;
+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.exceptions.PortalInternalServerError;
+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();
+    }
+
+    @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 = getGson().fromJson(jsonKeyCloakUser, listTypeKeyCloakUser);
+        keyCloakUsersList.remove(1);
+        keyCloakUsersList.remove(1);
+
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakClientAndRealmRoles.json");
+        List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+        PowerMock.mockStatic(JwtHelper.class);
+        expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(jwt);
+        expect(JwtHelper.getUsers(jwt, BackendConfig.getInstance().getMaxLoadUsers())).andReturn(keyCloakUsersList);
+        expect(JwtHelper.getRolesForUser(jwt, keyCloakUsersList.get(0).getId())).andReturn(keyCloakRolesList);
+
+        PowerMock.replayAll();
+        task.run();
+        PowerMock.verifyAll();
+
+        List<KeyCloakUser> keyCloakUsersResult = UserCache.getInstance().getKeyCloakUsers();
+
+        assertEquals(1, keyCloakUsersResult.size());
+        assertEquals(18, keyCloakUsersResult.get(0).getAllRoles().size());
+        assertEquals("feedin-management-access", keyCloakUsersResult.get(0).getAllRoles().get(0));
+        assertEquals("testclientrole", keyCloakUsersResult.get(0).getAllRoles().get(17));
+    }
+
+    @Test
+    public void testGetKeyCloakUsers_EmptyToken() throws Exception {
+        PowerMock.mockStatic(JwtHelper.class);
+        List<KeyCloakUser> compList = new ArrayList<>();
+        UserCache.getInstance().setKeyCloakUsers(compList);
+
+        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(null);
+
+        PowerMock.replayAll();
+        task.run();
+        PowerMock.verifyAll();
+
+        assertTrue(UserCache.getInstance().getKeyCloakUsers().isEmpty());
+    }
+
+    @Test
+    public void testGetKeyCloakUsers_null() throws Exception {
+        PowerMock.mockStatic(JwtHelper.class);
+        List<KeyCloakUser> compList = new ArrayList<>();
+        UserCache.getInstance().setKeyCloakUsers(compList);
+
+        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(null);
+
+        PowerMock.replayAll();
+        task.run();
+        PowerMock.verifyAll();
+
+        assertTrue(UserCache.getInstance().getKeyCloakUsers().isEmpty());
+    }
+
+
+    @Test
+    public void testGetKeyCloakUsersFromToken_ListEmpty() throws Exception {
+        PowerMock.mockStatic(JwtHelper.class);
+        String jsonKeyCloakUser = super.loadStringFromResource("testKeyCloakUsers.json");
+        Type listTypeKeyCloakUser = new TypeToken<List<KeyCloakUser>>(){}.getType();
+        List<KeyCloakUser> keyCloakUsersListOrg = JsonGeneratorBase.getGson().fromJson(jsonKeyCloakUser, listTypeKeyCloakUser);
+
+        UserCache.getInstance().setKeyCloakUsers(keyCloakUsersListOrg);
+        String json = super.loadStringFromResource("JWTAdmin.json");
+        JwtToken jwt = getGson().fromJson(json, JwtToken.class);
+
+        List<KeyCloakUser> keyCloakUsersList = new ArrayList<>();
+
+        expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(jwt);
+        expect(JwtHelper.getUsers(jwt, BackendConfig.getInstance().getMaxLoadUsers())).andReturn(keyCloakUsersList);
+
+        PowerMock.replayAll();
+        task.run();
+        PowerMock.verifyAll();
+
+        assertEquals(keyCloakUsersList.size(), UserCache.getInstance().getKeyCloakUsers().size());
+    }
+}
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..fdb8400
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..9d888ef
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java
@@ -0,0 +1,26 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..8135628
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java
@@ -0,0 +1,48 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..10a17dc
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java
@@ -0,0 +1,260 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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(Globals.HTTPSTATUS_BAD_REQUEST, ret.getStatus());
+	}
+
+	@Test
+	public void testInvokeRuntimeException() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+
+		ti.throwRuntime = true;
+		Response ret = tws.invoke("ssess",  false, ti);
+		assertEquals(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR, ret.getStatus());
+	}
+
+	@Test
+	public void testUnauthException() {
+		TestWebService tws = new TestWebService();
+		TestInvokable ti = new TestInvokable();
+		tws.throwUnauthException = true;
+		Response ret = tws.invoke("ssess",  false, ti);
+		assertEquals(Globals.HTTPSTATUS_UNAUTHORIZED, ret.getStatus());
+	}
+
+	@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("ssess", tws.sessionId);
+		assertEquals(666, ret.getStatus() );
+
+	}
+
+}
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..3dce81e
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java
@@ -0,0 +1,99 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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);
+
+        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..16f90db
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java
@@ -0,0 +1,83 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..a64e04e
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java
@@ -0,0 +1,42 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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(Globals.HTTPSTATUS_OK, resp.getStatus());
+    }
+
+    @Test
+    public void testBuildOkResponse() throws PortalException {
+        String json = "{ 'test' : 'Value' }";
+        Response resp = ResponseBuilderWrapper.INSTANCE.buildOKResponse( json );
+        assertEquals( Globals.HTTPSTATUS_OK, resp.getStatus());
+
+        resp = ResponseBuilderWrapper.INSTANCE.buildOKResponse(json, "ssess");
+        assertEquals( Globals.HTTPSTATUS_OK, resp.getStatus());
+    }
+}
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..1c31de2
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java
@@ -0,0 +1,106 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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(3, regMap.size());
+        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("HUGO1", sit1.getSessionId() );
+        sit1.setCookieToken("CaptainCookie");
+        assertEquals("CaptainCookie", sit1.getCookieToken());
+
+        TokenManager.getInstance().logout("HUGO1");
+        assertEquals(2, regMap.size());
+        TokenManager.getInstance().logout( "FAKE");
+        assertEquals(2, regMap.size());
+
+
+        // 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..f9506e9
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java
@@ -0,0 +1,54 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+
+import static junit.framework.Assert.assertEquals;
+
+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);
+        assertEquals("lalilu", er.getErrorText());
+    }
+
+    @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();
+        assertEquals("{\"ret\":\"OK\"}", ok);
+    }
+
+    @Test
+    public void testGeneralErrorJson() {
+        String nok = PortalExceptionMapper.getGeneralErrorJson();
+        assertEquals("{\"ret\":\"NOK\"}", 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..5cdf190
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java
@@ -0,0 +1,40 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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(Globals.HTTPSTATUS_BAD_REQUEST, new PortalBadRequest().getHttpStatus() );
+        assertEquals(Globals.HTTPSTATUS_FORBIDDEN, new PortalForbidden().getHttpStatus());
+        assertEquals(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR, new PortalInternalServerError(null, null).getHttpStatus());
+        assertEquals(Globals.HTTPSTATUS_NOT_FOUND, new PortalNotFound().getHttpStatus());
+        assertEquals(Globals.HTTPSTATUS_UNAUTHORIZED, new PortalUnauthorized().getHttpStatus());
+    }
+
+
+    @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/health/base/HealthCheckerTest.java b/src/test/java/org/eclipse/openk/portal/health/base/HealthCheckerTest.java
new file mode 100644
index 0000000..87aed26
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/base/HealthCheckerTest.java
@@ -0,0 +1,93 @@
+/*
+ ******************************************************************************
+ * Copyright © 2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+*/
+package org.eclipse.openk.portal.health.base;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.*;
+
+public class HealthCheckerTest {
+    public boolean hc1Called;
+    public boolean hc2Called;
+    public boolean hc3Called;
+
+    @Before
+    public void init() {
+        hc1Called = false;
+        hc2Called = false;
+        hc3Called = false;
+    }
+
+    @Test
+    public void test_ok() {
+        HealthCheck hc1 = new HealthCheck() {
+
+            @Override
+            protected Result check() throws Exception {
+                hc1Called = true;
+                return Result.healthy();
+            }
+        };
+
+        HealthCheck hc2 = new HealthCheck() {
+            @Override
+            protected Result check() throws Exception {
+                hc2Called = true;
+                return Result.unhealthy("because of...");
+            }
+        };
+
+        HealthChecker theChecker = new HealthChecker();
+        theChecker.register("firstTest", hc1 );
+        theChecker.register( "secondTest", hc2 );
+
+        List<NamedHealthCheckResult> retList = theChecker.performHealthChecks();
+
+        assertEquals( 2, retList.size() );
+        assertTrue( hc1Called );
+        assertTrue( hc2Called );
+        assertNull( retList.get(0).getResult().getMessage());
+        assertNotNull( retList.get(1).getResult().getMessage());
+        assertEquals( "firstTest", retList.get(0).getName());
+        assertEquals( "secondTest", retList.get(1).getName());
+        assertTrue( retList.get(0).getResult().isHealthy());
+        assertFalse( retList.get(1).getResult().isHealthy());
+    }
+
+    @Test
+    public void test_nok() {
+        HealthCheck hc1 = new HealthCheck() {
+
+            @Override
+            protected Result check() throws Exception {
+                hc3Called = true;
+                throw new Exception("Error in healthCheck");
+            }
+        };
+
+
+        HealthChecker theChecker = new HealthChecker();
+        theChecker.register("errorTest", hc1 );
+
+        List<NamedHealthCheckResult> retList = theChecker.performHealthChecks();
+
+        assertEquals( 1, retList.size() );
+        assertTrue( hc3Called );
+        assertNotNull( retList.get(0).getResult().getMessage());
+        assertFalse( retList.get(0).getResult().isHealthy());
+
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResultTest.java b/src/test/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResultTest.java
new file mode 100644
index 0000000..9cb9770
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResultTest.java
@@ -0,0 +1,36 @@
+/**
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class NamedHealthCheckResultTest {
+    @Test
+    public void testAll() {
+        NamedHealthCheckResult h1 = new NamedHealthCheckResult("Uno", Result.healthy());
+        NamedHealthCheckResult h2 = new NamedHealthCheckResult("Due", Result.unhealthy("Darum"));
+
+        assertEquals("\"Uno\":{\"healthy\":true}", h1.toJson());
+        assertEquals("\"Due\":{\"healthy\":false,\"message\":\"Darum\"}", h2.toJson());
+
+        List<NamedHealthCheckResult> lista = new LinkedList<>();
+        lista.add(h1);
+        lista.add(h2);
+        assertEquals( "{\"Uno\":{\"healthy\":true},\"Due\":{\"healthy\":false,\"message\":\"Darum\"}}",
+                NamedHealthCheckResult.toJson(lista));
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/base/ResultTest.java b/src/test/java/org/eclipse/openk/portal/health/base/ResultTest.java
new file mode 100644
index 0000000..a2056b0
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/base/ResultTest.java
@@ -0,0 +1,31 @@
+/**
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ResultTest {
+
+    @Test
+    public void testAll() {
+        Result res1 = Result.healthy();
+        Result res2 = Result.unhealthy("Msg");
+
+        assertTrue(res1.isHealthy());
+        assertFalse(res2.isHealthy());
+        assertNull(res1.getMessage());
+        assertNotNull(res2.getMessage());
+
+    }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheckTest.java b/src/test/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheckTest.java
new file mode 100644
index 0000000..25ef190
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheckTest.java
@@ -0,0 +1,48 @@
+/**
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ *     http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class KeyCloakPresentHealthCheckTest {
+    private KeyCloakPresentHealthCheck hc;
+
+    @Before
+    public void init() {
+        hc = new KeyCloakPresentHealthCheck() {
+            public boolean checkit;
+
+            @Override
+            protected boolean checkit() {
+                return checkit;
+            }
+        };
+    }
+
+    @Test
+    public void testOk() throws Exception {
+        Whitebox.setInternalState(hc, "checkit", true);
+        assertTrue(hc.check().isHealthy());
+    }
+
+    @Test
+    public void testNok() throws Exception {
+        Whitebox.setInternalState(hc, "checkit", false);
+        assertFalse(hc.check().isHealthy());
+    }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/util/JwtHelperTest.java b/src/test/java/org/eclipse/openk/portal/util/JwtHelperTest.java
new file mode 100644
index 0000000..4404351
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/util/JwtHelperTest.java
@@ -0,0 +1,118 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+package org.eclipse.openk.portal.util;
+
+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.util.JwtHelper;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertNotNull;
+
+public class JwtHelperTest extends ResourceLoaderBase {
+
+    @Test
+    public void testGetJwtPayload_Base64URL() {
+        //Token Pre 4.8.3 Keycloak
+        String base64urlToken = "AA.eyJqdGkiOiI3NDVmOTc4Zi00OTYwLTRlO"+
+                                "WYtYmFiMS1jNjdkZjMzODEwYjQiLCJleH"+
+                                "AiOjE1MTYwMTAxNDksIm5iZiI6MCwiaWF"+
+                                "0IjoxNTE2MDA5ODQ5LCJpc3MiOiJodHRw"+
+                                "Oi8vbG9jYWxob3N0OjgwOTAvYXV0aC9yZ"+
+                                "WFsbXMvTVZWTmV0emUiLCJhdWQiOiJlbG"+
+                                "9nYm9vay1iYWNrZW5kIiwic3ViIjoiNTk"+
+                                "5ZWY3NzMtNjRmYS00MzM2LWIwNDktMmEz"+
+                                "Njc4NTEzZTU4IiwidHlwIjoiQmVhcmVyI"+
+                                "iwiYXpwIjoiZWxvZ2Jvb2stYmFja2VuZC"+
+                                "IsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9"+
+                                "zdGF0ZSI6ImE2OGE4MzNkLTRiNTItNDgw"+
+                                "My05MDU4LTRkNjJhNmI3NzI3MCIsImFjc"+
+                                "iI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOl"+
+                                "siKiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9"+
+                                "sZXMiOlsiZWxvZ2Jvb2stYWNjZXNzIiwi"+
+                                "ZWxvZ2Jvb2stbm9ybWFsdXNlciIsInVtY"+
+                                "V9hdXRob3JpemF0aW9uIl19LCJyZXNvdX"+
+                                "JjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJ"+
+                                "yb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIs"+
+                                "Im1hbmFnZS1hY2NvdW50LWxpbmtzIiwid"+
+                                "mlldy1wcm9maWxlIl19fSwicm9sZXMiOi"+
+                                "JbdW1hX2F1dGhvcml6YXRpb24sIGVsb2d"+
+                                "ib29rLWFjY2VzcywgZWxvZ2Jvb2stbm9y"+
+                                "bWFsdXNlciwgb2ZmbGluZV9hY2Nlc3NdI"+
+                                "iwibmFtZSI6IlV3ZSByb8OfIiwicHJlZm"+
+                                "VycmVkX3VzZXJuYW1lIjoib3Blbmt0ZXN"+
+                                "0IiwiZ2l2ZW5fbmFtZSI6IlV3ZSIsImZh"+
+                                "bWlseV9uYW1lIjoicm_DnyJ9.CC";
+        //Since Keycloak 4.8.3 Aud Parameter is an array now
+        base64urlToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJIRWQ4NGl4V2xaVWk2bWFSa005Tk1wSEd0amRXRU1pZGtNV0Nvbk90U1ZVIn0.eyJleHAiOjE2MTA3MzYxNDEsImlhdCI6MTYxMDczNTg0MSwianRpIjoiNGIwMTM1NGMtN2NmZC00ZmEyLThmMjQtYWM0ZmJlZWZhNTZkIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgwL2F1dGgvcmVhbG1zL0Vsb2dib29rIiwiYXVkIjpbInJlYWxtLW1hbmFnZW1lbnQiLCJhY2NvdW50Il0sInN1YiI6IjAzNDU0MjJmLTk0MzctNDVmYy1iMmY0LTNlYTcwZDUzY2Q3NCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImVsb2dib29rLWJhY2tlbmQiLCJzZXNzaW9uX3N0YXRlIjoiNDRlMWQxMTctYTU0My00NWZjLWJjNTAtZjE5MDYzZGVmOTk0IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJlbG9nYm9vay1ub3JtYWx1c2VyIiwicGxhbm5lZC1wb2xpY2llcy1ub3JtYWx1c2VyIiwiZWxvZ2Jvb2stYWNjZXNzIiwiZWxvZ2Jvb2stc3VwZXJ1c2VyIiwia29uLWFkbWluIiwiZ3JpZC1mYWlsdXJlLWFjY2VzcyIsIm9mZmxpbmVfYWNjZXNzIiwia29uLWFjY2VzcyIsImdyaWQtZmFpbHVyZS1hZG1pbiIsInBsYW5uZWQtcG9saWNpZXMtYWNjZXNzIiwicGxhbm5pbmctYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJwbGFubmVkLXBvbGljaWVzLXN1cGVydXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy11c2VycyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJBZG1pbiBTdHJhdG9yIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW4iLCJnaXZlbl9uYW1lIjoiQWRtaW4iLCJmYW1pbHlfbmFtZSI6IlN0cmF0b3IifQ.sz5nOZZDwDHUS-WLzx1KX_KGTiWGuWTisR_bbHyReeXJyMefL6pngYwF_Qt0EPk1g0rqmqdhTN8-5IaSrwO1n0RmZrWLg19n1QnjkAs6ebF84UL07n5EEFJKh0luyWOKb_EW8JZpwRpLhaiWTG6KdXnOU6VkxJ-xX0ncmrHS8MYDh_u1LhIUPnu43trn0jJWoNAuHHVMY0rhpXNaZqc3Rq8iI3Vye87Yvs83jKTj5d1rHsFTrkaRt51bgi-2ML6IZa9GxIbCYroHZ7Idue00jisWPzmYU7F-wOpASBClBDsweTwRY9Dgr_yjrMns-1KXfYwtt4BTEc0IMKfX5gneSg";
+        // this payload contains a char with is valid in Base64URL but NOT in Base64.
+        JwtToken jt = new JwtToken();
+        jt.setAccessToken(base64urlToken);
+        JwtPayload pl = JwtHelper.getPayLoad(jt);
+        assertNotNull( pl );
+
+    }
+
+    @Test
+    public void testGetRolesListFromJson_testKeyCloakRoles_noClientRoleAtAll() throws PortalInternalServerError {
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_noClientRoleAtAll.json");
+        List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+        assertEquals("elogbook-access", keyCloakRolesList.get(0).getName());
+        assertEquals(2, keyCloakRolesList.size());
+    }
+
+    @Test
+    public void testGetRolesListFromJson_testKeyCloakRoles_noClientRoleForClient() throws PortalInternalServerError {
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_noClientRoleForClient.json");
+        List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+        assertEquals("elogbook-access", keyCloakRolesList.get(0).getName());
+        assertEquals(2, keyCloakRolesList.size());
+    }
+
+    @Test
+    public void testGetRolesListFromJson_testKeyCloakRoles_noRealmRole() throws PortalInternalServerError {
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_noRealmRole.json");
+        List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+        assertTrue(keyCloakRolesList.isEmpty());
+    }
+
+    @Test
+    public void testGetRolesListFromJson_testKeyCloakRoles_onlyClientRole() throws PortalInternalServerError {
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_onlyClientRole.json");
+        List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+        assertEquals("view-profile", keyCloakRolesList.get(0).getName());
+        assertTrue(keyCloakRolesList.get(0).getClientRole());
+        assertEquals(2, keyCloakRolesList.size());
+    }
+
+    @Test
+    public void testGetRolesListFromJson_testKeyCloakRoles_sameClientRealmRole() throws PortalInternalServerError {
+        String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_sameClientRealmRole.json");
+        List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+        assertEquals("elogbook-access", keyCloakRolesList.get(0).getName());
+        assertEquals(4, keyCloakRolesList.size());
+    }
+
+
+}
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..b4ba312
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java
@@ -0,0 +1,41 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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(999, errRet.getErrorCode());
+	}
+
+	@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..217cd7d
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java
@@ -0,0 +1,42 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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("It works!", gRRet.getRet());
+	}
+
+	@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..d6ad438
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java
@@ -0,0 +1,40 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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("Carlo", lc.getUserName() );
+		assertEquals("Cottura", lc.getPassword());
+	}
+
+	@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..92ec165
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java
@@ -0,0 +1,47 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..3a54c14
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java
@@ -0,0 +1,44 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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..f5f13ef
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java
@@ -0,0 +1,36 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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( "Betriebstagebuch local 4200", um[0].getModuleName() );
+        assertEquals( "#ffffff", um[0].getColor() );
+        assertEquals( 1, (long)um[0].getCols() );
+        assertEquals( 1, (long)um[0].getRows() );
+        assertEquals( "http://localhost:4200/", um[0].getLink() );
+        assertEquals( "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg", um[0].getPictureLink() );
+        assertEquals( "elogbook-access", um[0].getRequiredRole() );
+
+        assertEquals( "moduleConfigDevLocal.json", UserModule.getConfigFileName());
+        UserModule.setConfigFileName("moduleConfigDevLocal.json");
+        assertEquals( "moduleConfigDevLocal.json", UserModule.getConfigFileName() );
+    }
+
+}
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..4c64753
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java
@@ -0,0 +1,41 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* 
+*     http://www.eclipse.org/legal/epl-v10.html
+* 
+******************************************************************************
+*/
+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/testKeyCloakClientAndRealmRoles.json b/src/test/resources/testKeyCloakClientAndRealmRoles.json
new file mode 100644
index 0000000..a39cb11
--- /dev/null
+++ b/src/test/resources/testKeyCloakClientAndRealmRoles.json
@@ -0,0 +1,159 @@
+{
+  "realmMappings": [
+    {
+      "id": "7a145be5-20ba-4992-ad54-17c28d0bc0f9",
+      "name": "feedin-management-access",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "37d42cc3-0157-4ab6-b9fe-8be50de37da8",
+      "name": "planned-policies-executor",
+      "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": "a1760267-b72d-4cef-bb2a-91c0d4a24cd7",
+      "name": "planned-policies-measureplanner",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "f41f6144-f788-434d-be7a-ee3190099f5d",
+      "name": "planned-policies-superuser",
+      "scopeParamRequired": false,
+      "composite": true,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "f8fa3a84-b7d8-4ad7-98c5-3c77ca6c1a33",
+      "name": "kon_admin",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "1e41d089-72ea-4b22-a88c-56037b9680d8",
+      "name": "planned-policies-measureapplicant",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "e423626e-4616-45b7-9c3d-10a7f0acab8c",
+      "name": "elogbook-superuser",
+      "description": "",
+      "scopeParamRequired": false,
+      "composite": true,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "69cd9f7d-bd7b-473d-9ae2-8ca8665fa9bf",
+      "name": "planned-policies-requester",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "7533b166-79da-44f6-bb84-fe6a3916c9cd",
+      "name": "planned-policies-measureapprover",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "dc84c3f4-2509-4894-9b91-772b67d1d470",
+      "name": "planned-policies-completion",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "061827bc-771d-4ce1-9123-3d211686c078",
+      "name": "planned-policies-normaluser",
+      "description": "Darf vieles, aber nicht alles",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "27b9578f-416b-4f67-8259-60464636f457",
+      "name": "planned-policies-clearance",
+      "scopeParamRequired": false,
+      "composite": false,
+      "clientRole": false,
+      "containerId": "elogbook"
+    },
+    {
+      "id": "7b977153-1107-4a7d-b2b3-dc6daa461c15",
+      "name": "kon-access",
+      "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"
+    }
+  ],
+  "clientMappings": {
+    "elogbook-backend": {
+      "id": "e9904530-1ced-4d6b-96dc-fd1f3ce6420c",
+      "client": "elogbook-backend",
+      "mappings": [
+        {
+          "id": "f9971606-b587-41d0-a903-4e97b103e3b2",
+          "name": "testclientrole",
+          "scopeParamRequired": false,
+          "composite": false,
+          "clientRole": true,
+          "containerId": "e9904530-1ced-4d6b-96dc-fd1f3ce6420c"
+        }
+      ]
+    }
+  }
+}
\ 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/testKeyCloakRoles_noClientRoleAtAll.json b/src/test/resources/testKeyCloakRoles_noClientRoleAtAll.json
new file mode 100644
index 0000000..760a6a1
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_noClientRoleAtAll.json
@@ -0,0 +1,21 @@
+{
+  "realmMappings": [
+    {
+      "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"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_noClientRoleForClient.json b/src/test/resources/testKeyCloakRoles_noClientRoleForClient.json
new file mode 100644
index 0000000..d11bef0
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_noClientRoleForClient.json
@@ -0,0 +1,47 @@
+{
+  "realmMappings": [
+    {
+      "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"
+    }
+  ],
+  "clientMappings": {
+    "account": {
+      "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+      "client": "account",
+      "mappings": [
+        {
+          "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+          "name": "view-profile",
+          "description": "${role_view-profile}",
+          "scopeParamRequired": false,
+          "composite": false,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        },
+        {
+          "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+          "name": "manage-account",
+          "description": "${role_manage-account}",
+          "scopeParamRequired": false,
+          "composite": true,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_noRealmRole.json b/src/test/resources/testKeyCloakRoles_noRealmRole.json
new file mode 100644
index 0000000..66470b2
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_noRealmRole.json
@@ -0,0 +1,28 @@
+{
+  "clientMappings": {
+    "account": {
+      "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+      "client": "account",
+      "mappings": [
+        {
+          "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+          "name": "view-profile",
+          "description": "${role_view-profile}",
+          "scopeParamRequired": false,
+          "composite": false,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        },
+        {
+          "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+          "name": "manage-account",
+          "description": "${role_manage-account}",
+          "scopeParamRequired": false,
+          "composite": true,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_onlyClientRole.json b/src/test/resources/testKeyCloakRoles_onlyClientRole.json
new file mode 100644
index 0000000..24aff34
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_onlyClientRole.json
@@ -0,0 +1,28 @@
+{
+  "clientMappings": {
+    "elogbook-backend": {
+      "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+      "client": "elogbook-backend",
+      "mappings": [
+        {
+          "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+          "name": "view-profile",
+          "description": "${role_view-profile}",
+          "scopeParamRequired": false,
+          "composite": false,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        },
+        {
+          "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+          "name": "manage-account",
+          "description": "${role_manage-account}",
+          "scopeParamRequired": false,
+          "composite": true,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_sameClientRealmRole.json b/src/test/resources/testKeyCloakRoles_sameClientRealmRole.json
new file mode 100644
index 0000000..2141a33
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_sameClientRealmRole.json
@@ -0,0 +1,47 @@
+{
+  "realmMappings": [
+    {
+      "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"
+    }
+  ],
+  "clientMappings": {
+    "elogbook-backend": {
+      "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+      "client": "elogbook-backend",
+      "mappings": [
+        {
+          "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+          "name": "elogbook-access",
+          "description": "${role_view-profile}",
+          "scopeParamRequired": false,
+          "composite": false,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        },
+        {
+          "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+          "name": "manage-account",
+          "description": "${role_manage-account}",
+          "scopeParamRequired": false,
+          "composite": true,
+          "clientRole": true,
+          "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+        }
+      ]
+    }
+  }
+}
\ No newline at end of file
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
+}