diff --git a/.env.unix.example b/.env.unix.example
index bbc4ce743d04a6d9bcba22baef1ee7199fdfe0c9..2e4923867fc8febcd1db501b16baf212a99781df 100644
--- a/.env.unix.example
+++ b/.env.unix.example
@@ -14,4 +14,7 @@ BROKER_PASSWORD=fda
 KEYCLOAK_ADMIN=fda
 KEYCLOAK_ADMIN_PASSWORD=fda
 BROKER_CONSUMERS=2
-WEBSITE=http://example.com
\ No newline at end of file
+WEBSITE=http://example.com
+KEY_ALIAS=server
+KEY_STORE_PATH=/server.keystore
+KEY_STORE_PASSWORD=password
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
index 07f8df8fa9704a08e043d468bf13efaf917b99c2..4fffbf9e7e8162e93d1dbecc3ab5c01056244e8c 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -235,8 +235,10 @@ services:
     ports:
       - "9099:9099"
     depends_on:
+      fda-authentication-service:
+        condition: service_healthy
       fda-metadata-db:
-        condition: service_started
+        condition: service_healthy
     logging:
       driver: json-file
 
diff --git a/fda-authentication-service/Dockerfile b/fda-authentication-service/Dockerfile
index 38e737360bfc76a6984dcb88bf2f39d70fcba15f..243d9689185ffeca3c9a26047976352686e12e30 100644
--- a/fda-authentication-service/Dockerfile
+++ b/fda-authentication-service/Dockerfile
@@ -13,8 +13,8 @@ ENV KC_DB=mariadb
 
 WORKDIR /opt/keycloak
 
-# for demonstration purposes only, please make sure to use proper certificates in production instead
-RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
+COPY ./server.keystore ./conf/server.keystore
+
 RUN /opt/keycloak/bin/kc.sh build
 
 ###### SECOND STAGE ######
diff --git a/fda-authentication-service/dbrepo-realm.json b/fda-authentication-service/dbrepo-realm.json
index 0e26cf80c915b19958a8a38e106a8fc2afc9fda0..2007120dde24222cf9ed5bb4f52e0a56a497f580 100644
--- a/fda-authentication-service/dbrepo-realm.json
+++ b/fda-authentication-service/dbrepo-realm.json
@@ -26,7 +26,7 @@
   "oauth2DeviceCodeLifespan" : 600,
   "oauth2DevicePollingInterval" : 5,
   "enabled" : true,
-  "sslRequired" : "none",
+  "sslRequired" : "external",
   "registrationAllowed" : false,
   "registrationEmailAsUsername" : false,
   "rememberMe" : false,
@@ -843,7 +843,7 @@
   "otpPolicyLookAheadWindow" : 1,
   "otpPolicyPeriod" : 30,
   "otpPolicyCodeReusable" : false,
-  "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName" ],
+  "otpSupportedApplications" : [ "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName", "totpAppFreeOTPName" ],
   "webAuthnPolicyRpEntityName" : "keycloak",
   "webAuthnPolicySignatureAlgorithms" : [ "ES256" ],
   "webAuthnPolicyRpId" : "",
@@ -1761,7 +1761,7 @@
       "subType" : "anonymous",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-property-mapper" ]
+        "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "saml-user-property-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper" ]
       }
     }, {
       "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1",
@@ -1787,7 +1787,7 @@
       "subType" : "authenticated",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper" ]
+        "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper", "oidc-full-name-mapper" ]
       }
     } ],
     "org.keycloak.userprofile.UserProfileProvider" : [ {
@@ -1845,7 +1845,7 @@
   "internationalizationEnabled" : false,
   "supportedLocales" : [ ],
   "authenticationFlows" : [ {
-    "id" : "5eb1d49c-38cd-41a8-9557-13bcffb1a642",
+    "id" : "6fa20b3b-44fc-40ba-b310-bb2e729d53b9",
     "alias" : "Account verification options",
     "description" : "Method with which to verity the existing account",
     "providerId" : "basic-flow",
@@ -1867,7 +1867,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "29e68803-3d8d-4fe5-af03-0814e35a6ed3",
+    "id" : "c4f55400-b209-4eea-b996-70a19bea428e",
     "alias" : "Authentication Options",
     "description" : "Authentication options.",
     "providerId" : "basic-flow",
@@ -1896,7 +1896,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "aeadaa3b-f3d2-47ef-9e0a-ea4b737fe684",
+    "id" : "e43378cd-51b1-4978-8083-c01b8ab9e4c7",
     "alias" : "Browser - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -1918,7 +1918,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "4c958b93-579e-45da-8471-a6aebc439641",
+    "id" : "db5f2382-dabd-4a38-901b-95eff1d60c14",
     "alias" : "Direct Grant - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -1940,7 +1940,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "6878c43f-0aa7-40c6-bf28-f984029e893b",
+    "id" : "29a20ae2-7a1a-44fd-888a-fac7954cfe01",
     "alias" : "First broker login - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -1962,7 +1962,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "aae75803-fb3c-4c74-9ee7-73fc897aad05",
+    "id" : "3aa766d9-06ec-4073-9143-d810e12a2233",
     "alias" : "Handle Existing Account",
     "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider",
     "providerId" : "basic-flow",
@@ -1984,7 +1984,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "0987a7fe-5e31-40b1-be1f-6cd4a5a76e43",
+    "id" : "6a72a53f-bf1e-4c06-a366-71a4d963d5d0",
     "alias" : "Reset - Conditional OTP",
     "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
     "providerId" : "basic-flow",
@@ -2006,7 +2006,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "68078236-033e-4f17-b02f-fb5f401be3fe",
+    "id" : "5cb272da-a960-4429-b090-e676b358bb80",
     "alias" : "User creation or linking",
     "description" : "Flow for the existing/non-existing user alternatives",
     "providerId" : "basic-flow",
@@ -2029,7 +2029,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "28c746e7-fc22-4c61-872a-26670fffb8ed",
+    "id" : "58c9a9c9-3a95-45bf-9c40-d2926246158a",
     "alias" : "Verify Existing Account by Re-authentication",
     "description" : "Reauthentication of existing account",
     "providerId" : "basic-flow",
@@ -2051,7 +2051,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "502957db-db9d-4138-a5e3-90fce22bff15",
+    "id" : "976a2b1b-0a72-4c7b-9ebb-356595ad08b4",
     "alias" : "browser",
     "description" : "browser based authentication",
     "providerId" : "basic-flow",
@@ -2087,7 +2087,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "9312b6c7-f999-4285-ae9f-e365666066e7",
+    "id" : "63b290b2-4828-457b-9ed4-c68aa477cd2b",
     "alias" : "clients",
     "description" : "Base authentication for clients",
     "providerId" : "client-flow",
@@ -2123,7 +2123,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "31c2af88-b37c-4fdb-8dec-23a5ba145114",
+    "id" : "9c557280-9319-45c7-8656-198765ab5f23",
     "alias" : "direct grant",
     "description" : "OpenID Connect Resource Owner Grant",
     "providerId" : "basic-flow",
@@ -2152,7 +2152,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "c11ae35d-772a-4a1f-9934-a1945b45d617",
+    "id" : "6b0351e2-9b6b-475a-b59b-045096c2bbfa",
     "alias" : "docker auth",
     "description" : "Used by Docker clients to authenticate against the IDP",
     "providerId" : "basic-flow",
@@ -2167,7 +2167,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "0485179d-460c-4ad0-b0b2-02bbf57eb012",
+    "id" : "39d51855-eabd-4b38-b2da-04046c3d156c",
     "alias" : "first broker login",
     "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
     "providerId" : "basic-flow",
@@ -2190,7 +2190,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "aa1b06b4-1c12-4f7c-9d5a-6422ab5bb89a",
+    "id" : "ee67da7f-0738-4ef6-a07f-cb814a171dc6",
     "alias" : "forms",
     "description" : "Username, password, otp and other auth forms.",
     "providerId" : "basic-flow",
@@ -2212,7 +2212,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "fc52dc5f-16ee-499e-ad0a-ba04093efc33",
+    "id" : "011fb692-45ac-487f-8124-56836be0fbfe",
     "alias" : "http challenge",
     "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes",
     "providerId" : "basic-flow",
@@ -2234,7 +2234,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "576fb8d9-96b4-464a-a2b5-655c61755ec0",
+    "id" : "7fe214c5-6462-4965-8a37-6c5753f27a97",
     "alias" : "registration",
     "description" : "registration flow",
     "providerId" : "basic-flow",
@@ -2250,7 +2250,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "a026a910-1a04-4eb0-9fe2-6eb72139a39b",
+    "id" : "e140eca6-cb4e-4db9-811a-f2c8a012d873",
     "alias" : "registration form",
     "description" : "registration form",
     "providerId" : "form-flow",
@@ -2286,7 +2286,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "0d0e32f3-7030-42fa-be83-528281d9eca0",
+    "id" : "715bab3d-905a-4f91-8c62-b141cfd89002",
     "alias" : "reset credentials",
     "description" : "Reset credentials for a user if they forgot their password or something",
     "providerId" : "basic-flow",
@@ -2322,7 +2322,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "ec850fcc-5b8c-4109-9cf4-a16f84cd7804",
+    "id" : "83dd0a05-4fc5-47d3-84d8-f6f2641e4de3",
     "alias" : "saml ecp",
     "description" : "SAML ECP Profile Authentication Flow",
     "providerId" : "basic-flow",
@@ -2338,13 +2338,13 @@
     } ]
   } ],
   "authenticatorConfig" : [ {
-    "id" : "d42b19d3-2efe-4879-9ce0-7c055a3d949e",
+    "id" : "c07fe13c-bb0d-451b-955e-078376f851db",
     "alias" : "create unique user config",
     "config" : {
       "require.password.update.after.registration" : "false"
     }
   }, {
-    "id" : "f1c71d63-f83f-432d-b9b4-e1a97095b5e1",
+    "id" : "5b25a33e-a4dc-4827-a4e8-62fc1f383cef",
     "alias" : "review profile config",
     "config" : {
       "update.profile.on.first.login" : "missing"
diff --git a/fda-authentication-service/docker-entrypoint.sh b/fda-authentication-service/docker-entrypoint.sh
index ca82a7badaf62a1fe8aef07e992df833d17755b6..d8e0fdcd850f1e8f867b99c22926aef8c341589e 100644
--- a/fda-authentication-service/docker-entrypoint.sh
+++ b/fda-authentication-service/docker-entrypoint.sh
@@ -1,6 +1,6 @@
 #!/bin/bash
 
-/app/service-register.sh authentication-service 8080
-(while sleep 60; do bash /app/service-register.sh authentication-service 8080; done) &
+/app/service-register.sh authentication-service 8443 8080
+(while sleep 60; do bash /app/service-register.sh authentication-service 8443 8080; done) &
 
 /opt/keycloak/bin/kc.sh start-dev --import-realm
diff --git a/fda-authentication-service/server.keystore b/fda-authentication-service/server.keystore
new file mode 100644
index 0000000000000000000000000000000000000000..93e5c28b23293910dac23a3e974cb485524a3a17
Binary files /dev/null and b/fda-authentication-service/server.keystore differ
diff --git a/fda-authentication-service/service-register.sh b/fda-authentication-service/service-register.sh
index 72734426bbe787ca64d394dd514b79f4561cf2c6..2d7f64be971f7e14fad690f3e6a9b708f092ab26 100755
--- a/fda-authentication-service/service-register.sh
+++ b/fda-authentication-service/service-register.sh
@@ -9,7 +9,8 @@ EUREKA_URI="http://$EUREKA_HOST:$EUREKA_PORT"
 SERVICE_NAME="$1"
 SERVICE_PROTOCOL="http"
 SERVICE_HOST="$1"
-SERVICE_PORT="${2:-9000}"
+SECURE_PORT="${2:-9000}"
+SERVICE_PORT="${3:-9000}"
 
 SERVICE_URI="$SERVICE_PROTOCOL://$SERVICE_HOST:$SERVICE_PORT"
 HOME_URI="$SERVICE_URI/realms/dbrepo"
@@ -72,8 +73,8 @@ cat <<EOF > /tmp/json.json
       "@enabled": "true"
     },
     "securePort": {
-      "\$": "$SERVICE_PORT",
-      "@enabled": "false"
+      "\$": "$SECURE_PORT",
+      "@enabled": "true"
     },
     "vipAddress": "$SERVICE_HOST",
     "secureVipAddress": "$SERVICE_HOST",
diff --git a/fda-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java b/fda-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
index 00c5a1f3dcd48020120630ab3568a58b71c9479e..37617f6ccf2abcfe03e994bfa44e3c445532951a 100644
--- a/fda-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
+++ b/fda-container-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
@@ -37,7 +37,7 @@ public class ReadyConfig {
             imageService.pull(imageRepository, imageTag);
         } else {
             log.debug("image {}:{} is present on the host", imageRepository, imageTag);
-            log.debug("skip pulling image {}:{}", imageRepository, imageTag);
+            log.trace("skip pulling image {}:{}", imageRepository, imageTag);
         }
         Files.touch(new File(readyPath));
         log.info("Service is ready");
diff --git a/fda-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java b/fda-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java
index 682ced6609f9ffee066ef95322d4975c532d17d0..ccb3dbae797cfd70d52009355c2f07405a78082b 100644
--- a/fda-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java
+++ b/fda-container-service/services/src/main/java/at/tuwien/service/impl/ImageServiceImpl.java
@@ -162,7 +162,6 @@ public class ImageServiceImpl implements ImageService {
     public boolean exists(String repository, String tag) {
         final List<Image> images = dockerClient.listImagesCmd()
                 .exec();
-        log.trace("found images {}", images);
         return images.stream()
                 .filter(i -> Objects.nonNull(i.getRepoTags()))
                 .filter(i -> i.getRepoTags().length > 0)
diff --git a/fda-gateway-service/Dockerfile b/fda-gateway-service/Dockerfile
index f8aea4c73b96ce8de9d78476a7685fd5540fe30f..a270239d58b0b4b44aefba904aa8d007fca8d720 100644
--- a/fda-gateway-service/Dockerfile
+++ b/fda-gateway-service/Dockerfile
@@ -21,6 +21,12 @@ ENV METADATA_USERNAME=postgres
 ENV METADATA_PASSWORD=postgres
 ENV GATEWAY_ENDPOINT=http://gateway-service:9095
 ENV LOG_LEVEL=debug
+ENV KEY_ALIAS=server
+ENV KEY_PASS=password
+ENV KEY_STORE=/server.keystore
+ENV KEY_STORE_PASS=password
+
+COPY ./server.keystore /server.keystore
 
 COPY ./service_ready /usr/bin
 RUN chmod +x /usr/bin/service_ready
diff --git a/fda-gateway-service/pom.xml b/fda-gateway-service/pom.xml
index 210f10156c6a28fcbd4cc216c2a153ef49a20659..5110b896d822418f6133b6fc918fcf1f4dcbaebc 100644
--- a/fda-gateway-service/pom.xml
+++ b/fda-gateway-service/pom.xml
@@ -12,6 +12,14 @@
     <version>1.1.0-alpha</version>
     <name>fda-gateway-service</name>
     <description>Demo project for Spring Boot</description>
+    <url>https://dbrepo-docs.ossdip.at</url>
+    <developers>
+        <developer>
+            <name>Martin Weise</name>
+            <email>martin.weise@tuwien.ac.at</email>
+            <organization>TU Wien</organization>
+        </developer>
+    </developers>
 
     <packaging>pom</packaging>
     <modules>
diff --git a/fda-gateway-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java b/fda-gateway-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java
index f4eae349a40b40c119e4c2d6545390c035b66c1a..2250fa50884df3f47b0b063975aea74f06203f80 100644
--- a/fda-gateway-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java
+++ b/fda-gateway-service/rest-service/src/main/java/at/tuwien/config/ReadyConfig.java
@@ -18,9 +18,7 @@ public class ReadyConfig {
     private String readyPath;
 
     @EventListener(ApplicationReadyEvent.class)
-    public void init() throws IOException, InterruptedException {
-        log.info("Wait more for gateway start");
-        Thread.sleep(20 * 1000L);
+    public void init() throws IOException {
         Files.touch(new File(readyPath));
     }
 
diff --git a/fda-gateway-service/rest-service/src/main/resources/application-docker.yml b/fda-gateway-service/rest-service/src/main/resources/application-docker.yml
index 7c42301ea62bed1ffde75db2e3e4b462b83c39c5..b1eda86566fd3e7bfc350f2f730f3dd72965d776 100644
--- a/fda-gateway-service/rest-service/src/main/resources/application-docker.yml
+++ b/fda-gateway-service/rest-service/src/main/resources/application-docker.yml
@@ -22,8 +22,20 @@ spring:
     name: gateway-service
   cloud:
     loadbalancer.ribbon.enabled: false
+    gateway:
+      httpclient:
+        ssl:
+          useInsecureTrustManager: true
 management.endpoints.web.exposure.include: health,info,prometheus
-server.port: 9095
+server:
+  port: 9095
+  ssl:
+    enabled: true
+    key-alias: "${KEY_ALIAS}"
+    key-store: "${KEY_STORE}"
+    key-store-type: jks
+    key-store-password: "${KEY_STORE_PASS}"
+    key-password: "${KEY_PASS}"
 logging:
   pattern.console: "%d %highlight(%-5level) %msg%n"
   level:
diff --git a/fda-gateway-service/rest-service/src/main/resources/application-local.yml b/fda-gateway-service/rest-service/src/main/resources/application-local.yml
index 6c2aeb22df2b9c71a815e3017ea755a7e0698402..ab294c2a578b643cb24002204804c6d3953b0b93 100644
--- a/fda-gateway-service/rest-service/src/main/resources/application-local.yml
+++ b/fda-gateway-service/rest-service/src/main/resources/application-local.yml
@@ -22,8 +22,20 @@ spring:
     name: gateway-service
   cloud:
     loadbalancer.ribbon.enabled: false
+    gateway:
+      httpclient:
+        ssl:
+          useInsecureTrustManager: true
 management.endpoints.web.exposure.include: health,info,prometheus
-server.port: 9095
+server:
+  port: 9095
+  ssl:
+    enabled: true
+    key-alias: server
+    key-store: "./server.keystore"
+    key-store-type: jks
+    key-store-password: password
+    key-password: password
 logging:
   pattern.console: "%d %highlight(%-5level) %msg%n"
   level:
diff --git a/fda-gateway-service/rest-service/src/main/resources/application.yml b/fda-gateway-service/rest-service/src/main/resources/application.yml
index 21e4e554b3f5be85eec0dd124c6a76d83b9c7667..94983082cbc97883df236924c7bb61226f877aee 100644
--- a/fda-gateway-service/rest-service/src/main/resources/application.yml
+++ b/fda-gateway-service/rest-service/src/main/resources/application.yml
@@ -17,9 +17,23 @@ spring:
           time_zone: UTC
   application:
     name: gateway-service
+  cloud:
+    loadbalancer.ribbon.enabled: false
+    gateway:
+      httpclient:
+        ssl:
+          useInsecureTrustManager: true
 springdoc.swagger-ui.enabled: false
 management.endpoints.web.exposure.include: health,info,prometheus
-server.port: 9095
+server:
+  port: 9095
+  ssl:
+    enabled: true
+    key-alias: "${KEY_ALIAS}"
+    key-store: "${KEY_STORE}"
+    key-store-type: jks
+    key-store-password: "${KEY_STORE_PASS}"
+    key-password: "${KEY_PASS}"
 logging:
   pattern.console: "%d %highlight(%-5level) %msg%n"
   level:
diff --git a/fda-gateway-service/server.keystore b/fda-gateway-service/server.keystore
new file mode 100644
index 0000000000000000000000000000000000000000..93e5c28b23293910dac23a3e974cb485524a3a17
Binary files /dev/null and b/fda-gateway-service/server.keystore differ
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java
similarity index 53%
rename from fda-metadata-db/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java
rename to fda-metadata-db/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java
index c92b4913c8d02e5f44677bd7d18cfdb0362081be..d300e6696719e5206c61e57269c26e40a71e1f3d 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/JwtResponseDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/CreateUserDto.java
@@ -3,6 +3,8 @@ package at.tuwien.api.auth;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.util.List;
 
@@ -12,22 +14,26 @@ import java.util.List;
 @Builder
 @AllArgsConstructor
 @NoArgsConstructor
-public class JwtResponseDto {
+public class CreateUserDto {
 
     @NotNull
-    @ToString.Exclude
-    private String token;
-
-    private String type;
-
-    private Long id;
+    @Schema(example = "true")
+    private Boolean enabled;
 
+    @NotBlank
     @Schema(example = "user")
     private String username;
 
+    @NotBlank
+    @Email
     @Schema(example = "user@example.com")
     private String email;
 
-    private List<String> roles;
+    private String firstName;
+
+    private String lastName;
+
+    @NotNull
+    private List<CredentialDto> credentials;
 
 }
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/CredentialDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/CredentialDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe1400d3ab94ffd7a0ce46c571ae99b5f463b7a9
--- /dev/null
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/CredentialDto.java
@@ -0,0 +1,29 @@
+package at.tuwien.api.auth;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+@ToString
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class CredentialDto {
+
+    @NotBlank
+    @Schema(example = "password")
+    private String type;
+
+    @NotBlank
+    @Schema(example = "abc123")
+    private String value;
+
+    @NotNull
+    @Schema(example = "false")
+    private Boolean temporary;
+
+}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java
index 7f6f3937bcb251604d9ec979ae8649bceb685d42..3f6784bdd0eef1322ac391408e1e6e88e0b6cb5f 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/SignupRequestDto.java
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 
 import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import javax.validation.constraints.Pattern;
 
@@ -15,12 +16,12 @@ import javax.validation.constraints.Pattern;
 @NoArgsConstructor
 public class SignupRequestDto {
 
-    @NotNull
+    @NotBlank
     @Pattern(regexp = "^[a-z0-9]{3,}$")
     @Schema(example = "user")
     private String username;
 
-    @NotNull
+    @NotBlank
     @Email
     @Schema(example = "user@example.com")
     private String email;
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenBriefDto.java
deleted file mode 100644
index cbb50605403f1009acba86ac22b56d2e335f27e0..0000000000000000000000000000000000000000
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenBriefDto.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package at.tuwien.api.auth;
-
-import com.fasterxml.jackson.annotation.JsonFormat;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import java.time.Instant;
-
-@Getter
-@Setter
-@ToString
-@Builder
-@AllArgsConstructor
-@NoArgsConstructor
-public class TokenBriefDto {
-
-    @NotNull
-    private Long id;
-
-    @NotBlank
-    @JsonProperty("token_hash")
-    @Schema(example = "5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03")
-    private String tokenHash;
-
-    @NotNull
-    @Schema(example = "2020-08-04 11:12:00")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
-    private Instant created;
-
-    @JsonProperty("last_used")
-    @Schema(example = "2020-08-04 11:12:00")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
-    private Instant lastUsed;
-
-    @NotNull
-    @Schema(example = "2020-08-04 11:12:00")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
-    private Instant expires;
-
-}
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenDto.java
index 1cf442509c4207dd697b5afa37431a087da65ed0..cf3399dbe9a865c5b741426c40bb854fe2b84acf 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/auth/TokenDto.java
@@ -1,13 +1,11 @@
 package at.tuwien.api.auth;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
-import java.time.Instant;
 
 @Getter
 @Setter
@@ -17,31 +15,44 @@ import java.time.Instant;
 @NoArgsConstructor
 public class TokenDto {
 
-    @NotNull
-    private Long id;
+    @NotBlank
+    @JsonProperty("access_token")
+    @Schema(example = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJBbFdvalRsa1dBSVVoYTJLWjFvOEluWEtNbVAzUTg0STZiMFFHYkR6aEpvIn0.eyJleHAiOjE2ODAyNjgyNjgsImlhdCI6MTY4MDI2ODIwOCwianRpIjoiNjkwNjRlNTQtODNhNS00NGYxLWE3OTItNWFjOWU4OTA5YTlkIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJzdWIiOiI4MjQ2OWMyMS0yYjNjLTRmMDctODg1Yi1hMzViMGQ5YTJhNjYiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIiwiYWNyIjoiMSIsInNjb3BlIjoicHJvZmlsZSBlbWFpbCIsInNpZCI6IjQ0NTgwN2VlLTI4NzYtNDYxZC1hOGYzLTRkMjdiMzBjMjFmYSIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicHJlZmVycmVkX3VzZXJuYW1lIjoiZmRhIn0.IOQxqWvlPDV9WuFOeLVG-ayexbK8OqylPABghEMSbMpmNlQhSAjbjaMY31uU-uADZRHB-mC8bmRS5PoWNtanuhz0lORDCeissFsbv0UL9Q42CaxG75vFAAD5WsdIHIr-dtEjEiXYtu-qwdg83griAUeO119TTdgldyPxo4jWzNw0ui6W7r4LqP4fSk31iJfxR5urgs5k6Ctzg-fXCORT31-nKz_YJQwLoPO9j4afX_1mnCXY5qFGMSrmPKzB0CArZfUpa_4nqt4Y768yOC3gigAyCjXtvXKkgCmARPSRjERGDdTb6SGbAwRDiVHVy9wy7XZwOcCFMEra9H7mV0Mx2A")
+    private String accessToken;
 
     @NotBlank
-    @JsonProperty("token_hash")
-    @Schema(example = "5891b5b522d5df086d0ff0b110fbd9d21bb4fc7163af34d08286a2e846f6be03")
-    private String tokenHash;
+    @JsonProperty("refresh_token")
+    @Schema(example = "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICI4YTczZGYwZS03NzMwLTRiZDEtOGVhOC1mZTdjZWViNmMxYWMifQ.eyJleHAiOjE2ODAyNzAwMDgsImlhdCI6MTY4MDI2ODIwOCwianRpIjoiNWYyNDIwNDItNmJmZi00ZTQ2LTg2NTAtNDBhY2E3YjVkZjMyIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy9tYXN0ZXIiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL21hc3RlciIsInN1YiI6IjgyNDY5YzIxLTJiM2MtNGYwNy04ODViLWEzNWIwZDlhMmE2NiIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJhZG1pbi1jbGkiLCJzZXNzaW9uX3N0YXRlIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIiwic2NvcGUiOiJwcm9maWxlIGVtYWlsIiwic2lkIjoiNDQ1ODA3ZWUtMjg3Ni00NjFkLWE4ZjMtNGQyN2IzMGMyMWZhIn0.-GltWGkIaKUJ4AqRYnGHblTr0ygZm2CsRQB6zz5ePm4")
+    private String refreshToken;
+
+    @NotBlank
+    @JsonProperty("token_type")
+    @Schema(example = "Bearer")
+    private String tokenType;
 
     @NotNull
-    @Schema(example = "2020-08-04 11:12:00")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
-    private Instant created;
+    @JsonProperty("expires_in")
+    @Schema(example = "60")
+    private Long expiresIn;
 
-    @JsonProperty("last_used")
-    @Schema(example = "2020-08-04 11:12:00")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
-    private Instant lastUsed;
+    @NotNull
+    @JsonProperty("session_state")
+    @Schema(example = "445807ee-2876-461d-a8f3-4d27b30c21fa")
+    private String sessionState;
 
     @NotNull
-    @Schema(example = "2020-08-04 11:12:00")
-    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
-    private Instant expires;
+    @JsonProperty("scope")
+    @Schema(example = "profile email")
+    private String scope;
 
-    @NotBlank
-    @Schema(example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c")
-    private String token;
+    @NotNull
+    @JsonProperty("refresh_expires_in")
+    @Schema(example = "1800")
+    private Long refreshExpiresIn;
+
+    @NotNull
+    @JsonProperty("not-before-policy")
+    @Schema(example = "0")
+    private Long notBeforePolicy;
 
 }
diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/auth/Realm.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/auth/Realm.java
new file mode 100644
index 0000000000000000000000000000000000000000..fb7010325f5165428e8a09c3ddb4b9e19fc8bcf8
--- /dev/null
+++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/auth/Realm.java
@@ -0,0 +1,31 @@
+package at.tuwien.entities.auth;
+
+import lombok.*;
+
+import javax.persistence.*;
+
+@Data
+@Entity
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@ToString
+@EqualsAndHashCode(onlyExplicitlyIncluded = true)
+@Table(name = "realm")
+public class Realm {
+
+    @Id
+    @EqualsAndHashCode.Include
+    @Column(nullable = false)
+    private String id;
+
+    @Column(nullable = false)
+    private Boolean enabled;
+
+    @Column(nullable = false)
+    private String name;
+
+    @Column(nullable = false)
+    private String sslRequired;
+
+}
diff --git a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java
index abd946bdb9231d74479b880e4eb822b6ae14dad3..29f7222a7159524f446b764964ba361d3fea32d7 100644
--- a/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java
+++ b/fda-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java
@@ -36,7 +36,7 @@ public class User {
     @Column(name = "last_name")
     private String lastname;
 
-    @Column(name = "realm id")
+    @Column(name = "realm_id")
     private String realmId;
 
     @Column(unique = true, nullable = false)
diff --git a/fda-query-service/pom.xml b/fda-query-service/pom.xml
index 67fb838c96353c66bd00f0725042783a442a0630..35ec3a29280f9b41b5d1a3170670329ef5185957 100644
--- a/fda-query-service/pom.xml
+++ b/fda-query-service/pom.xml
@@ -297,9 +297,6 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-project-info-reports-plugin</artifactId>
                 <version>3.0.0</version>
-<!--                <configuration>-->
-<!--                    <outputDirectory>docs</outputDirectory>-->
-<!--                </configuration>-->
             </plugin>
             <plugin>
                 <groupId>com.soebes.maven.plugins</groupId>
diff --git a/fda-user-service/Dockerfile b/fda-user-service/Dockerfile
index dd9fe0250e12a17d5bfd81ce0070530badd5385a..a772cacf6ff3420cd7568106ee27c38a346285bb 100644
--- a/fda-user-service/Dockerfile
+++ b/fda-user-service/Dockerfile
@@ -24,6 +24,9 @@ FROM openjdk:11-jre-slim as runtime
 ENV METADATA_DB=fda
 ENV METADATA_USERNAME=root
 ENV METADATA_PASSWORD=dbrepo
+ENV GATEWAY_ENDPOINT=http://gateway-service:9095
+ENV KEYCLOAK_ADMIN=fda
+ENV KEYCLOAK_ADMIN_PASSWORD=fda
 ENV LOG_LEVEL=debug
 ENV DBREPO_CLIENT_SECRET=client-secret
 ENV CLIENT_ID=dbrepo-client
diff --git a/fda-user-service/pom.xml b/fda-user-service/pom.xml
index f06580d159c91afa43a80c0dcb785fcb21b7f434..989dafab4ceaf1fb5bc6dbcdf3027cb8821e8b3d 100644
--- a/fda-user-service/pom.xml
+++ b/fda-user-service/pom.xml
@@ -118,29 +118,6 @@
             <groupId>org.springframework.data</groupId>
             <artifactId>spring-data-elasticsearch</artifactId>
         </dependency>
-        <!-- AMPQ -->
-        <dependency>
-            <groupId>com.rabbitmq</groupId>
-            <artifactId>amqp-client</artifactId>
-            <version>${rabbit-amqp-client.version}</version>
-        </dependency>
-        <!-- Docker -->
-        <dependency>
-            <groupId>com.github.docker-java</groupId>
-            <artifactId>docker-java</artifactId>
-            <version>${docker.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>javax.ws.rs</groupId>
-                    <artifactId>jsr311-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>com.github.docker-java</groupId>
-            <artifactId>docker-java-transport-httpclient5</artifactId>
-            <version>${docker.version}</version>
-        </dependency>
         <!-- IDE -->
         <dependency>
             <groupId>org.projectlombok</groupId>
@@ -237,9 +214,7 @@
                         <exclude>at/tuwien/handlers/**/*</exclude>
                         <exclude>at/tuwien/exception/**/*</exclude>
                         <exclude>at/tuwien/config/**/*</exclude>
-                        <exclude>**/RabbitMqServiceImpl.class</exclude>
-                        <exclude>**/ServiceSeeder.class</exclude>
-                        <exclude>**/FdaQueryServiceApplication.class</exclude>
+                        <exclude>**/FdaUserServiceApplication.class</exclude>
                     </excludes>
                 </configuration>
                 <executions>
@@ -267,9 +242,6 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-project-info-reports-plugin</artifactId>
                 <version>3.0.0</version>
-<!--                <configuration>-->
-<!--                    <outputDirectory>docs</outputDirectory>-->
-<!--                </configuration>-->
             </plugin>
             <plugin>
                 <groupId>com.soebes.maven.plugins</groupId>
diff --git a/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java b/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java
index 7bb8dc31490b8468f1a772fda01ffcb4b242ea9d..20c41199280f2df5ac0bee8385707cc46bf0634a 100644
--- a/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java
+++ b/fda-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java
@@ -2,6 +2,9 @@ package at.tuwien.endpoint;
 
 import at.tuwien.api.auth.SignupRequestDto;
 import at.tuwien.api.user.UserBriefDto;
+import at.tuwien.exception.RealmNotFoundException;
+import at.tuwien.exception.RemoteUnavailableException;
+import at.tuwien.exception.UserNotFoundException;
 import at.tuwien.mapper.UserMapper;
 import at.tuwien.service.UserService;
 import io.micrometer.core.annotation.Timed;
@@ -48,7 +51,8 @@ public class UserEndpoint {
     @Transactional
     @Timed(value = "user.create", description = "Time needed to create a user in the metadata database")
     @Operation(summary = "Create a user")
-    public ResponseEntity<UserBriefDto> create(SignupRequestDto data) {
+    public ResponseEntity<?> create(SignupRequestDto data) throws RealmNotFoundException, UserNotFoundException,
+            RemoteUnavailableException {
         log.debug("endpoint create a user, data={}", data);
         final UserBriefDto dto = userMapper.userToUserBriefDto(userService.create(data));
         log.trace("create user resulted in dto {}", dto);
diff --git a/fda-user-service/rest-service/src/main/resources/application-docker.yml b/fda-user-service/rest-service/src/main/resources/application-docker.yml
index 084cc82986478d9fd376495e9f52bf2c93e2f42c..486101dd8e32882c69e4066d1911a030e07be3ce 100644
--- a/fda-user-service/rest-service/src/main/resources/application-docker.yml
+++ b/fda-user-service/rest-service/src/main/resources/application-docker.yml
@@ -35,6 +35,11 @@ eureka:
   client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/
 fda:
   ready.path: /ready
+  gateway.endpoint: "${GATEWAY_ENDPOINT}"
+  keycloak:
+    endpoint: https://authentication-service:8443/
+    username: "${KEYCLOAK_ADMIN}"
+    password: "${KEYCLOAK_ADMIN_PASSWORD}"
   jwt:
     issuer: "${JWT_ISSUER}"
     public_key: "${JWT_PUBKEY}"
\ No newline at end of file
diff --git a/fda-user-service/rest-service/src/main/resources/application-local.yml b/fda-user-service/rest-service/src/main/resources/application-local.yml
index 4b86aa03a823e192a3525861c367164eee7a000c..c6ac95610eda5541b3765e8e5ca10939c1b53294 100644
--- a/fda-user-service/rest-service/src/main/resources/application-local.yml
+++ b/fda-user-service/rest-service/src/main/resources/application-local.yml
@@ -32,9 +32,14 @@ logging:
     org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver: debug
 eureka:
   instance.hostname: user-service
-  client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/
+  client.serviceUrl.defaultZone: http://localhost:9090/eureka/
 fda:
-  ready.path: /ready
+  ready.path: ./ready
+  gateway.endpoint: http://localhost:9095
+  keycloak:
+    endpoint: https://localhost:8443/
+    username: fda
+    password: fda
   jwt:
     issuer: http://localhost:8080/realms/dbrepo
     public_key: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqqnHQ2BWWW9vDNLRCcxD++xZg/16oqMo/c1l+lcFEjjAIJjJp/HqrPYU/U9GvquGE6PbVFtTzW1KcKawOW+FJNOA3CGo8Q1TFEfz43B8rZpKsFbJKvQGVv1Z4HaKPvLUm7iMm8Hv91cLduuoWx6Q3DPe2vg13GKKEZe7UFghF+0T9u8EKzA/XqQ0OiICmsmYPbwvf9N3bCKsB/Y10EYmZRb8IhCoV9mmO5TxgWgiuNeCTtNCv2ePYqL/U0WvyGFW0reasIK8eg3KrAUj8DpyOgPOVBn3lBGf+3KFSYi+0bwZbJZWqbC/Xlk20Go1YfeJPRIt7ImxD27R/lNjgDO/MwIDAQAB
\ No newline at end of file
diff --git a/fda-user-service/rest-service/src/main/resources/application.yml b/fda-user-service/rest-service/src/main/resources/application.yml
index 9ba4e1547a5795546ef952e72819193e32d670c3..5f93e7a6182e1972a150ad884e9385752b4c8c0d 100644
--- a/fda-user-service/rest-service/src/main/resources/application.yml
+++ b/fda-user-service/rest-service/src/main/resources/application.yml
@@ -35,6 +35,11 @@ eureka:
   client.serviceUrl.defaultZone: http://discovery-service:9090/eureka/
 fda:
   ready.path: /ready
+  gateway.endpoint: "${GATEWAY_ENDPOINT}"
+  keycloak:
+    endpoint: https://authentication-service:8443/
+    username: "${KEYCLOAK_ADMIN}"
+    password: "${KEYCLOAK_ADMIN_PASSWORD}"
   jwt:
     issuer: "${JWT_ISSUER}"
     public_key: "${JWT_PUBKEY}"
diff --git a/fda-user-service/rest-service/src/test/resources/application.properties b/fda-user-service/rest-service/src/test/resources/application.properties
index 4eea490a9199d7e0155b1f33cf3500a5e1f2863f..ddba279a3bfcf1940585c1d6cb4c4608cd3f54c9 100644
--- a/fda-user-service/rest-service/src/test/resources/application.properties
+++ b/fda-user-service/rest-service/src/test/resources/application.properties
@@ -21,11 +21,6 @@ spring.jpa.show-sql=false
 logging.level.root=error
 logging.level.at.tuwien.=trace
 
-# broker service
-spring.rabbitmq.host=dbrepo-broker-service
-spring.rabbitmq.username=guest
-spring.rabbitmq.password=guest
-
 # search service
 fda.consumers=2
 fda.gateway.endpoint: http://localhost:15672
diff --git a/fda-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/fda-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..540b5d96f4e750a5fdea93f0d2da7a46e7c5c44c
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java
@@ -0,0 +1,40 @@
+package at.tuwien.config;
+
+import lombok.Getter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+import org.springframework.web.util.DefaultUriBuilderFactory;
+
+@Getter
+@Configuration
+public class GatewayConfig {
+
+    @Value("${fda.gateway.endpoint}")
+    private String gatewayEndpoint;
+
+    @Value("${fda.keycloak.endpoint}")
+    private String keycloakEndpoint;
+
+    @Value("${fda.keycloak.username}")
+    private String keycloakUsername;
+
+    @Value("${fda.keycloak.password}")
+    private String keycloakPassword;
+
+    @Bean
+    public RestTemplate gatewayRestTemplate() {
+        final RestTemplate restTemplate =  new RestTemplate();
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
+        return restTemplate;
+    }
+
+    @Bean
+    public RestTemplate keycloakRestTemplate() {
+        final RestTemplate restTemplate =  new RestTemplate();
+        restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(keycloakEndpoint));
+        return restTemplate;
+    }
+
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/config/ReadyConfig.java b/fda-user-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
index 2250fa50884df3f47b0b063975aea74f06203f80..388480c9be24fb50e83699c7fd2f1a92bd39f8d5 100644
--- a/fda-user-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
+++ b/fda-user-service/services/src/main/java/at/tuwien/config/ReadyConfig.java
@@ -1,7 +1,10 @@
 package at.tuwien.config;
 
+import at.tuwien.exception.RealmNotFoundException;
+import at.tuwien.service.RealmService;
 import com.google.common.io.Files;
 import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.context.event.ApplicationReadyEvent;
 import org.springframework.context.annotation.Configuration;
@@ -17,8 +20,16 @@ public class ReadyConfig {
     @Value("${fda.ready.path}")
     private String readyPath;
 
+    private final RealmService realmService;
+
+    @Autowired
+    public ReadyConfig(RealmService realmService) {
+        this.realmService = realmService;
+    }
+
     @EventListener(ApplicationReadyEvent.class)
-    public void init() throws IOException {
+    public void init() throws IOException, RealmNotFoundException {
+        realmService.update("master");
         Files.touch(new File(readyPath));
     }
 
diff --git a/fda-user-service/services/src/main/java/at/tuwien/exception/RealmNotFoundException.java b/fda-user-service/services/src/main/java/at/tuwien/exception/RealmNotFoundException.java
new file mode 100644
index 0000000000000000000000000000000000000000..1750cfb525c2947f8f13837b5e89ed7ddc46f8fd
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/exception/RealmNotFoundException.java
@@ -0,0 +1,21 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.NOT_FOUND)
+public class RealmNotFoundException extends Exception {
+
+    public RealmNotFoundException(String msg) {
+        super(msg);
+    }
+
+    public RealmNotFoundException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public RealmNotFoundException(Throwable thr) {
+        super(thr);
+    }
+
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/exception/RemoteUnavailableException.java b/fda-user-service/services/src/main/java/at/tuwien/exception/RemoteUnavailableException.java
new file mode 100644
index 0000000000000000000000000000000000000000..3f6700d06b277d59ccbf812136faec277261357d
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/exception/RemoteUnavailableException.java
@@ -0,0 +1,21 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.NO_CONTENT)
+public class RemoteUnavailableException extends Exception {
+
+    public RemoteUnavailableException(String msg) {
+        super(msg);
+    }
+
+    public RemoteUnavailableException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public RemoteUnavailableException(Throwable thr) {
+        super(thr);
+    }
+
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java b/fda-user-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
new file mode 100644
index 0000000000000000000000000000000000000000..3d41955d06f05e0897e2bc27db4c784ed6ad3b86
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/gateway/AuthenticationServiceGateway.java
@@ -0,0 +1,11 @@
+package at.tuwien.gateway;
+
+import at.tuwien.api.auth.CreateUserDto;
+import at.tuwien.api.auth.TokenDto;
+import at.tuwien.exception.RemoteUnavailableException;
+
+public interface AuthenticationServiceGateway {
+    TokenDto getToken() throws RemoteUnavailableException;
+
+    void createUser(String token, CreateUserDto data) throws RemoteUnavailableException;
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java b/fda-user-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..19e2544e29a596e34296cb6179c29e3f0443783c
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/gateway/impl/AuthenticationServiceGatewayImpl.java
@@ -0,0 +1,77 @@
+package at.tuwien.gateway.impl;
+
+import at.tuwien.api.auth.CreateUserDto;
+import at.tuwien.api.auth.TokenDto;
+import at.tuwien.config.GatewayConfig;
+import at.tuwien.exception.RemoteUnavailableException;
+import at.tuwien.gateway.AuthenticationServiceGateway;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.HttpServerErrorException;
+import org.springframework.web.client.ResourceAccessException;
+import org.springframework.web.client.RestTemplate;
+
+@Log4j2
+@Service
+public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
+
+    private final RestTemplate restTemplate;
+    private final GatewayConfig gatewayConfig;
+
+    @Autowired
+    public AuthenticationServiceGatewayImpl(@Qualifier("keycloakRestTemplate") RestTemplate restTemplate,
+                                            GatewayConfig gatewayConfig) {
+        this.restTemplate = restTemplate;
+        this.gatewayConfig = gatewayConfig;
+    }
+
+    @Override
+    public TokenDto getToken() throws RemoteUnavailableException {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.add("Content-Type", MediaType.APPLICATION_FORM_URLENCODED.toString());
+        final MultiValueMap<String, String> payload = new LinkedMultiValueMap<>();
+        payload.add("username", gatewayConfig.getKeycloakUsername());
+        payload.add("password", gatewayConfig.getKeycloakPassword());
+        payload.add("grant_type", "password");
+        payload.add("client_id", "admin-cli");
+        final String url = "/realms/master/protocol/openid-connect/token";
+        log.debug("call authentication service {}", url);
+        final ResponseEntity<TokenDto> response;
+        try {
+            response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class);
+        } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
+            log.error("Failed to obtain admin token: {}", e.getMessage());
+            throw new RemoteUnavailableException("Failed to obtain admin token", e);
+        }
+        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
+            log.error("Failed to obtain admin token: credentials are invalid");
+            throw new RemoteUnavailableException("Failed to obtain admin token: credentials are invalid");
+        }
+        return response.getBody();
+    }
+
+    @Override
+    public void createUser(String token, CreateUserDto data) throws RemoteUnavailableException {
+        final HttpHeaders headers = new HttpHeaders();
+        headers.add("Content-Type", MediaType.APPLICATION_JSON.toString());
+        headers.add("Accept", MediaType.APPLICATION_JSON.toString());
+        headers.add("Authorization", "Bearer: " + token);
+        final ResponseEntity<Void> response;
+        try {
+            response = restTemplate.exchange("/admin/realms/dbrepo/users", HttpMethod.POST, new HttpEntity<>(data, headers), Void.class);
+        } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
+            log.error("Failed to create user: {}", e.getMessage());
+            throw new RemoteUnavailableException("Failed to create user", e);
+        }
+        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
+            log.error("Failed to create user: credentials are invalid");
+            throw new RemoteUnavailableException("Failed to create user: credentials are invalid");
+        }
+    }
+
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/fda-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
index cba134ae89d4f6aeae126b925437bb92bff55d21..3a60fc1c3df990bb9cdf524fe62db5d4eee73c65 100644
--- a/fda-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
+++ b/fda-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java
@@ -1,5 +1,6 @@
 package at.tuwien.mapper;
 
+import at.tuwien.api.auth.CreateUserDto;
 import at.tuwien.api.auth.SignupRequestDto;
 import at.tuwien.api.user.GrantedAuthorityDto;
 import at.tuwien.api.user.UserBriefDto;
@@ -21,7 +22,7 @@ public interface UserMapper {
 
     UserBriefDto userToUserBriefDto(User data);
 
-    User signupRequestDtoToUser(SignupRequestDto data);
+    CreateUserDto signupRequestDtoToCreateUserDto(SignupRequestDto data);
 
     default GrantedAuthority grantedAuthorityDtoToGrantedAuthority(GrantedAuthorityDto data) {
         final GrantedAuthority authority = new SimpleGrantedAuthority(data.getAuthority());
diff --git a/fda-user-service/services/src/main/java/at/tuwien/repository/elastic/UserIdxRepository.java b/fda-user-service/services/src/main/java/at/tuwien/repository/elastic/UserIdxRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..812cb439f61d9b708aac09589d28b9c39d100d8d
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/repository/elastic/UserIdxRepository.java
@@ -0,0 +1,10 @@
+package at.tuwien.repository.elastic;
+
+import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.user.UserDto;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface UserIdxRepository extends ElasticsearchRepository<UserDto, Long> {
+}
\ No newline at end of file
diff --git a/fda-user-service/services/src/main/java/at/tuwien/repository/jpa/RealmRepository.java b/fda-user-service/services/src/main/java/at/tuwien/repository/jpa/RealmRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..db0443c0a78c3c8c2d653edf15901c9a3f2e4686
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/repository/jpa/RealmRepository.java
@@ -0,0 +1,14 @@
+package at.tuwien.repository.jpa;
+
+import at.tuwien.entities.auth.Realm;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+@Repository
+public interface RealmRepository extends JpaRepository<Realm, String> {
+
+    Optional<Realm> findByName(String name);
+
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/service/RealmService.java b/fda-user-service/services/src/main/java/at/tuwien/service/RealmService.java
new file mode 100644
index 0000000000000000000000000000000000000000..fc3f15f2880c009c9cbbbe034f36e7ac5fbbd6ae
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/service/RealmService.java
@@ -0,0 +1,10 @@
+package at.tuwien.service;
+
+import at.tuwien.entities.auth.Realm;
+import at.tuwien.exception.RealmNotFoundException;
+
+public interface RealmService {
+    Realm find(String name) throws RealmNotFoundException;
+
+    Realm update(String name) throws RealmNotFoundException;
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java b/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java
index d9371a4695a522f4a079dc8cb53ee95309eb7a3b..abf06036cb4eac51fe001e25e938dc90f8b5bf99 100644
--- a/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java
+++ b/fda-user-service/services/src/main/java/at/tuwien/service/UserService.java
@@ -3,6 +3,8 @@ package at.tuwien.service;
 import at.tuwien.api.auth.SignupRequestDto;
 import at.tuwien.entities.container.Container;
 import at.tuwien.entities.user.User;
+import at.tuwien.exception.RealmNotFoundException;
+import at.tuwien.exception.RemoteUnavailableException;
 import at.tuwien.exception.UserNotFoundException;
 
 import java.security.Principal;
@@ -26,7 +28,7 @@ public interface UserService {
      */
     User findByUsername(String username) throws UserNotFoundException;
 
-    User create(SignupRequestDto data);
+    User create(SignupRequestDto data) throws RealmNotFoundException, RemoteUnavailableException, UserNotFoundException;
 
     /**
      * Finds a user by id.
diff --git a/fda-user-service/services/src/main/java/at/tuwien/service/impl/RealmServiceImpl.java b/fda-user-service/services/src/main/java/at/tuwien/service/impl/RealmServiceImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..249876f68dd6d70830025e69f3c93b4e57d5e09a
--- /dev/null
+++ b/fda-user-service/services/src/main/java/at/tuwien/service/impl/RealmServiceImpl.java
@@ -0,0 +1,43 @@
+package at.tuwien.service.impl;
+
+import at.tuwien.entities.auth.Realm;
+import at.tuwien.exception.RealmNotFoundException;
+import at.tuwien.repository.jpa.RealmRepository;
+import at.tuwien.service.RealmService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+@Log4j2
+@Service
+public class RealmServiceImpl implements RealmService {
+
+    final RealmRepository realmRepository;
+
+    @Autowired
+    public RealmServiceImpl(RealmRepository realmRepository) {
+        this.realmRepository = realmRepository;
+    }
+
+    @Override
+    public Realm find(String name) throws RealmNotFoundException {
+        final Optional<Realm> optional = realmRepository.findByName(name);
+        if (optional.isEmpty()) {
+            log.error("Failed to find realm with name '{}'", name);
+            throw new RealmNotFoundException("Failed to find realm");
+        }
+        return optional.get();
+    }
+
+    @Override
+    public Realm update(String name) throws RealmNotFoundException {
+        final Realm realm = find("master");
+        realm.setSslRequired("NONE");
+        final Realm entity = realmRepository.save(realm);
+        log.info("Disabled SSL for realm with name '{}'", name);
+        return entity;
+    }
+
+}
diff --git a/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
index 5578d9186b04dce27aa8f54d826a4bc3334d2a9b..50bbea2634ad74620f38e0edd15fa130f63033be 100644
--- a/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
+++ b/fda-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
@@ -1,8 +1,13 @@
 package at.tuwien.service.impl;
 
+import at.tuwien.api.auth.CreateUserDto;
 import at.tuwien.api.auth.SignupRequestDto;
+import at.tuwien.api.auth.TokenDto;
 import at.tuwien.entities.user.User;
+import at.tuwien.exception.RealmNotFoundException;
+import at.tuwien.exception.RemoteUnavailableException;
 import at.tuwien.exception.UserNotFoundException;
+import at.tuwien.gateway.AuthenticationServiceGateway;
 import at.tuwien.mapper.UserMapper;
 import at.tuwien.repository.jpa.UserRepository;
 import at.tuwien.service.UserService;
@@ -12,7 +17,6 @@ import org.springframework.stereotype.Service;
 
 import java.util.List;
 import java.util.Optional;
-import java.util.UUID;
 
 @Log4j2
 @Service
@@ -20,11 +24,14 @@ public class UserServiceImpl implements UserService {
 
     private final UserMapper userMapper;
     private final UserRepository userRepository;
+    private final AuthenticationServiceGateway authenticationServiceGateway;
 
     @Autowired
-    public UserServiceImpl(UserMapper userMapper, UserRepository userRepository) {
+    public UserServiceImpl(UserMapper userMapper, UserRepository userRepository,
+                           AuthenticationServiceGateway authenticationServiceGateway) {
         this.userMapper = userMapper;
         this.userRepository = userRepository;
+        this.authenticationServiceGateway = authenticationServiceGateway;
     }
 
     @Override
@@ -43,14 +50,20 @@ public class UserServiceImpl implements UserService {
     }
 
     @Override
-    public User create(SignupRequestDto data) {
-        final User user = userMapper.signupRequestDtoToUser(data);
-        user.setRealmId("82c39861-d877-4667-a0f3-4daa2ee230e0");
-        user.setEmailVerified(false);
-        user.setId(UUID.randomUUID().toString());
-        final User entity = userRepository.save(user);
-        log.info("Created user with id {}", entity.getId());
-        return entity;
+    public User create(SignupRequestDto data) throws RealmNotFoundException, RemoteUnavailableException,
+            UserNotFoundException {
+        final TokenDto dto = authenticationServiceGateway.getToken();
+        log.debug("obtained authentication token");
+        final CreateUserDto userDto = userMapper.signupRequestDtoToCreateUserDto(data);
+        authenticationServiceGateway.createUser(dto.getAccessToken(), userDto);
+        final Optional<User> optional = userRepository.findByUsername(data.getUsername());
+        if (optional.isEmpty()) {
+            /* should never occur */
+            throw new UserNotFoundException("User not found with username '" + data.getUsername() + "'");
+        }
+        final User user = optional.get();
+        log.info("Created user with id {}", user.getId());
+        return user;
     }
 
     @Override
diff --git a/server.keystore b/server.keystore
new file mode 100644
index 0000000000000000000000000000000000000000..93e5c28b23293910dac23a3e974cb485524a3a17
Binary files /dev/null and b/server.keystore differ