diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index e5e605dc8fda374fd5756aa7d7b43dbce8055657..f5b4aa651380693a7327c40c5c6e8e2efb38b0a3 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -236,7 +236,7 @@ cat source_env.local
 
 export HYDRA_ADMIN_URL=http://localhost:4445
 export KRATOS_PUBLIC_URL=http://localhost/api
-export KRATOS_ADMIN_URL=http://localhost:8000/admin
+export KRATOS_ADMIN_URL=http://localhost:8000
 export LOGIN_PANEL_URL=http://localhost/web
 export DATABASE_URL="mysql+pymysql://stackspin:stackspin@localhost/stackspin"
 ```
diff --git a/areas/users/user_service.py b/areas/users/user_service.py
index 8e1dd5ae5c933ca50e6a8f7ce575f6ae5a498c67..74f0bc4aff4a26f48ef61668205aaa1b7608fa2e 100644
--- a/areas/users/user_service.py
+++ b/areas/users/user_service.py
@@ -8,7 +8,7 @@ from helpers import KratosApi
 class UserService:
     @staticmethod
     def get_users():
-        res = KratosApi.get("/identities").json()
+        res = KratosApi.get("/admin/identities").json()
         userList = []
         for r in res:
             userList.append(UserService.__insertAppRoleToUser(r["id"], r))
@@ -17,7 +17,7 @@ class UserService:
 
     @staticmethod
     def get_user(id):
-        res = KratosApi.get("/identities/{}".format(id)).json()
+        res = KratosApi.get("/admin/identities/{}".format(id)).json()
         return UserService.__insertAppRoleToUser(id, res)
 
     @staticmethod
@@ -26,7 +26,7 @@ class UserService:
             "schema_id": "default",
             "traits": {"email": data["email"], "name": data["name"]},
         }
-        res = KratosApi.post("/identities", kratos_data).json()
+        res = KratosApi.post("/admin/identities", kratos_data).json()
 
         appRole = AppRole(
             user_id=res["id"],
@@ -45,7 +45,7 @@ class UserService:
             "schema_id": "default",
             "traits": {"email": data["email"], "name": data["name"]},
         }
-        KratosApi.put("/identities/{}".format(id), kratos_data)
+        KratosApi.put("/admin/identities/{}".format(id), kratos_data)
 
         app_role = AppRole.query.filter_by(user_id=id).first()
         if app_role:
diff --git a/run_app.sh b/run_app.sh
index 7710af382790ac66939d342021035c3ee1cd3f9b..4d6074a24e199e0027a39521eb3a0061f6121e09 100755
--- a/run_app.sh
+++ b/run_app.sh
@@ -28,7 +28,7 @@ export TOKEN_URL="https://sso.init.stackspin.net/oauth2/token"
 
 # Login facilitator paths
 export KRATOS_PUBLIC_URL=http://localhost/kratos
-export KRATOS_ADMIN_URL=http://localhost:8000/admin
+export KRATOS_ADMIN_URL=http://localhost:8000
 export HYDRA_PUBLIC_URL="https://sso.init.stackspin.net"
 export HYDRA_ADMIN_URL=http://localhost:4445
 export LOGIN_PANEL_URL=http://localhost/web/
diff --git a/web/login/login.py b/web/login/login.py
index 8f8f7e087de778e07f500200138bd76704704898..7874f8ee8bdca91fb9dac0ddeee52e0e3c7bea7d 100644
--- a/web/login/login.py
+++ b/web/login/login.py
@@ -71,6 +71,25 @@ def settings():
 
     return render_template("settings.html", api_url=KRATOS_PUBLIC_URL)
 
+@web.route("/error", methods=["GET"])
+def error():
+    """Show error messages from Kratos
+
+    Implements user-facing errors as described in https://www.ory.sh/docs/kratos/self-service/flows/user-facing-errors
+
+    :param id: error ID as given by Kratos
+    :return: redirect or settings page
+    """
+
+    error_id = request.args.get("id")
+    api_response=""
+    try:
+        # Get Self-Service Errors
+        api_response = KRATOS_ADMIN.get_self_service_error(error_id)
+    except ory_kratos_client.ApiException as ex:
+        print("Exception when calling V0alpha2Api->get_self_service_error: %s\n" % ex)
+
+    return render_template("error.html", error_message=api_response)
 
 @web.route("/login", methods=["GET", "POST"])
 def login():
diff --git a/web/static/base.js b/web/static/base.js
index a98e4a0fe3bc128c008e3f08ee5c1a5d4dba2387..6d94cea0094dd8894a5cedfb416d876527e6aace 100644
--- a/web/static/base.js
+++ b/web/static/base.js
@@ -56,8 +56,8 @@ function flow_login() {
         url: uri,
         success: function(data) {
 
-            // Render login form (group: profile)
-            var html = render_form(data, 'profile');
+            // Render login form (group: password)
+            var html = render_form(data, 'password');
             $("#contentLogin").html(html);
 
         },
@@ -94,11 +94,15 @@ function flow_settings_validate() {
                 window.location.href = 'settings';
             }
             else {
-
-                 // There was an error, Kratos does not specify what is
-                 // wrong. So we just show the general error message and
-                 // let the user figure it out. We can re-use the flow-id
-                 $("#contentProfileSaveFailed").show();
+                // There was an error, Kratos does not specify what is
+                // wrong. So we just show the general error message and
+                // let the user figure it out. We can re-use the flow-id
+                $("#contentProfileSaveFailed").show();
+
+                // For now, this code assumes that only the password can fail
+                // validation. Other forms might need to be added in the future.
+                html = render_form(data, 'password')
+                $("#contentPassword").html(html)
             }
         }
     });
@@ -134,12 +138,10 @@ function flow_settings() {
             }
 
 
-            // FIXME: This seems to be not necessary anymore in kratos 0.9.0
-            // because they moved the password field to the profile group
             // Render the password & profile form based on the fields we got
             // from the API
-            // var html = render_form(data, 'profile');
-            // $("#contentPassword").html(html);
+            var html = render_form(data, 'password');
+            $("#contentPassword").html(html);
 
             html = render_form(data, 'profile');
             $("#contentProfile").html(html);
@@ -251,9 +253,10 @@ function render_form(data, group) {
         var name = node.attributes.name;
         var type = node.attributes.type;
         var value = node.attributes.value;
+        var messages = node.messages
 
         if (node.group == 'default' || node.group == group) {
-            var elm = getFormElement(type, name, value);
+            var elm = getFormElement(type, name, value, messages);
             form += elm;
         }
     }
@@ -271,11 +274,18 @@ function render_form(data, group) {
 //                   like "email" are also supported
 // name: name of the field. Used when posting data
 // value: If there is already a value known, show it
-function getFormElement(type, name, value) {
+// messages: error messages related to the field
+function getFormElement(type, name, value, messages) {
+    console.log("Getting form element", type, name, value, messages)
 
     if (value == undefined) {
             value = '';
     }
+
+    if (typeof(messages) == "undefined") {
+        messages = []
+    }
+
     if (name == 'email' || name == 'traits.email') {
         return getFormInput(
                 'email',
@@ -285,6 +295,7 @@ function getFormElement(type, name, value) {
                 'Please enter your e-mail address here',
                 'Please provide your e-mail address. We will send a recovery ' +
                 'link to that e-mail address.',
+                messages,
                 );
     }
 
@@ -295,7 +306,8 @@ function getFormElement(type, name, value) {
                 value,
                 'Username',
                 'Please provide an username',
-                null
+                null,
+                messages,
                 );
     }
 
@@ -306,7 +318,8 @@ function getFormElement(type, name, value) {
                 value,
                 'Full name',
                 'Please provide your full name',
-                null
+                null,
+                messages,
                 );
     }
 
@@ -317,8 +330,9 @@ function getFormElement(type, name, value) {
                 name,
                 value,
                 'E-mail address',
-                'Please provide your e-mail address to login',
-                null
+                'Please provide your e-mail address to log in',
+                null,
+                messages,
                 );
     }
 
@@ -329,7 +343,8 @@ function getFormElement(type, name, value) {
                 value,
                 'Password',
                 'Please provide your password',
-                null
+                null,
+                messages,
                 );
     }
 
@@ -350,7 +365,7 @@ function getFormElement(type, name, value) {
     }
 
 
-    return getFormInput('input', name, value, name, null,null);
+    return getFormInput('input', name, value, name, null,null, messages);
 
 
 }
@@ -363,7 +378,12 @@ function getFormElement(type, name, value) {
 // param label: Label to display above field
 // param placeHolder: Label to display in field if empty
 // param help: Additional help text, displayed below the field in small font
-function getFormInput(type, name, value, label, placeHolder, help) {
+// param messages: Message about failed input
+function getFormInput(type, name, value, label, placeHolder, help, messages) {
+    if (typeof(help) == "undefined" || help == null) {
+        help = ""
+    }
+    console.log("Messages: ", messages);
 
     // Id field for help element
     var nameHelp = name + "Help";
@@ -372,6 +392,14 @@ function getFormInput(type, name, value, label, placeHolder, help) {
     element += '<label for="'+name+'">'+label+'</label>';
     element += '<input type="'+type+'" class="form-control" id="'+name+'" name="'+name+'" ';
 
+    // messages get appended to help info
+    if (messages.length) {
+        for (message in messages) {
+            console.log("adding message", messages[message])
+            help += messages[message]['text']
+        }
+    }
+
     // If we are a password field, add a eye icon to reveal password
     if (value) {
         element += 'value="'+value+'" ';
diff --git a/web/templates/error.html b/web/templates/error.html
new file mode 100644
index 0000000000000000000000000000000000000000..b943b98d18f4f62eb24aae52174d36aee5cf8eda
--- /dev/null
+++ b/web/templates/error.html
@@ -0,0 +1,23 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+<script>
+    var api_url = '{{ api_url }}';
+
+    // Actions
+    $(document).ready(function() {
+        flow_settings();
+    });
+
+</script>
+
+<h2>Error: {{ error_message['error']['status'] }}</h2>
+
+
+<div class=error-div>
+    {{ error_message['error']['message'] }}
+    {{ error_message['error']['reason'] }}
+</div>
+{% endblock %}
+