keycloak-memoizeit

Changes

Details

diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index ff6d9cc..93a1593 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -103,9 +103,9 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $ht
                                 Current.realm = Current.realms[i];
                             }
                         }
+                        $location.url("/realms/" + id);
+                        Notifications.success("Created realm");
                     });
-                    $location.url("/realms/" + id);
-                    Notifications.success("Created realm");
                 });
             } else {
                 console.log('updating realm...');
@@ -155,7 +155,7 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm,
     console.log('RealmRequiredCredentialsCtrl');
 
     $scope.realm = {
-        id : realm.id, realm : realm.realm,
+        id : realm.id, realm : realm.realm, social : realm.social,
         requiredCredentials : realm.requiredCredentials,
         requiredApplicationCredentials : realm.requiredApplicationCredentials,
         requiredOAuthClientCredentials : realm.requiredOAuthClientCredentials
@@ -200,7 +200,7 @@ module.controller('RealmRequiredCredentialsCtrl', function($scope, Realm, realm,
 module.controller('RealmTokenDetailCtrl', function($scope, Realm, realm, $http, $location, Dialog, Notifications) {
     console.log('RealmTokenDetailCtrl');
 
-    $scope.realm = { id : realm.id, realm : realm.realm, tokenLifespan : realm.tokenLifespan,  accessCodeLifespan : realm.accessCodeLifespan };
+    $scope.realm = { id : realm.id, realm : realm.realm, social : realm.social, tokenLifespan : realm.tokenLifespan,  accessCodeLifespan : realm.accessCodeLifespan };
     $scope.realm.tokenLifespanUnit = 'Seconds';
     $scope.realm.accessCodeLifespanUnit = 'Seconds';
 
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
index 6786466..2d0c9bd 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/menu.html
@@ -19,16 +19,25 @@
         </div>
     </div>
     <div class="navbar primary">
-        <div class="navbar-inner" data-ng-controller="RealmDropdownCtrl">
-            <ul class="nav pull-right" data-ng-show="auth.loggedIn">
-                <li class="divider-vertical-left" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
-                    data-ng-show="auth.loggedIn"><a href="#/create/realm">New Realm</a></li>
-            </ul>
-            <ul class="nav" >
-                <li data-ng-show="showNav()"><a href="#/realms/{{current.realm.id}}">Realm</a></li>
-                <li class="select-rcue" data-ng-show="showNav()"><select ng-change="changeRealm()" ng-model="current.realm" ng-options="r.realm for r in current.realms">
-                </select></li>
+        <div class="navbar-inner clearfix" data-ng-controller="RealmDropdownCtrl">
+            <ul class="nav pull-left">
+                <li>
+                    <span class="dropdown-label" data-ng-show="showNav()">Realm:</span>
+                    <div class="dropdown" data-ng-show="showNav()">
+                        <a data-toggle="dropdown" class="dropdown-toggle" href="#">My First Realm</a>
+                        <ul class="dropdown-menu">
+                            <li class="selected"><a href="#">My First Realm</a></li>
+                            <li><a href="#">Another Realm</a></li>
+                            <li><a href="#">Some realm with a freaking gigantic name</a></li>
+                        </ul>
+                    </div>
+                    <!-- This component should be replaced by the dropdown-menu above --> <li class="select-rcue" data-ng-show="showNav()"><select ng-change="changeRealm()" ng-model="current.realm" ng-options="r.realm for r in current.realms"></select></li>
+                </li>
             </ul>
+            <div class="pull-right" data-ng-show="auth.loggedIn">
+                <a class="button primary" href="#/create/realm" data-ng-class="path[0] == 'create' && path[1] == 'realm' && 'active'"
+                    data-ng-show="auth.loggedIn">Add Realm</a>
+            </div>
         </div>
     </div>
 </div>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
index 84aa0c6..fcb89f1 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-detail.html
@@ -4,22 +4,27 @@
         <div id="content-area" class="col-md-9" role="main">
             <div class="top-nav" data-ng-hide="createRealm">
                 <ul class="rcue-tabs">
-                    <li class="active"><a href="#/realms/{{realm.id}}">Settings</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}">General</a></li>
                     <li data-ng-show="realm.social"><a href="#">Social</a></li>
                     <li><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
-                    <li><a href="#/realms/{{realm.id}}/required-credentials">Required Credentials</a></li>
-                    <li><a href="#/realms/{{realm.id}}/token-settings">Token Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
+                    <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
                 </ul>
             </div>
             <div id="content">
-                <h2 class="pull-left" data-ng-show="createRealm">New Realm</h2>
-                <h2 class="pull-left" data-ng-hide="createRealm">Realm: <span>{{realm.realm}}</span></h2>
+                <ol class="breadcrumb" data-ng-hide="createRealm">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}">Settings</a></li>
+                    <li class="active">General</li>
+                </ol>
+                <h2 class="pull-left" data-ng-show="createRealm">Add Realm</h2>
+                <h2 class="pull-left" data-ng-hide="createRealm"><span>{{realm.realm}}</span> General Settings</h2>
                 <p class="subtitle" data-ng-show="createRealm"><span class="required">*</span> Required fields</p>
                 <form name="realmForm" novalidate>
                     <fieldset>
-                        <legend uncollapsed><span class="text">Required Settings</span> </legend>
+                        <legend uncollapsed><span class="text">Required Settings</span></legend>
                         <div class="form-group">
-                            <label for="name">Name </label><span class="required" data-ng-show="createRealm">*</span>
+                            <label for="name">Name <span class="required" data-ng-show="createRealm">*</span></label>
 
                             <div class="controls">
                                 <input type="text" id="name" name="name" data-ng-model="realm.realm" autofocus
@@ -107,7 +112,6 @@
 
                     <div class="form-actions" data-ng-show="!createRealm">
                         <button type="submit" data-ng-click="save()" class="primary" data-ng-show="changed">Save
-                            changes
                         </button>
                         <button type="submit" data-ng-click="reset()" data-ng-show="changed">Clear changes
                         </button>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html
index 5d0c1c4..1c2ccba 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-menu.html
@@ -1,5 +1,5 @@
 <ul data-ng-hide="createRealm">
-    <li data-ng-class="(!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' || path[2] == 'required-credentials') && 'active'"><a href="#/realms/{{realm.id}}">Realm Settings</a></li>
+    <li data-ng-class="(!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' || path[2] == 'required-credentials') && 'active'"><a href="#/realms/{{realm.id}}">Settings</a></li>
     <li data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.id}}/users">Users</a>
     </li>
     <li data-ng-class="(path[2] == 'applications' || path[1] == 'application') && 'active'"><a href="#/realms/{{realm.id}}/applications">Applications</a></li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html
index a819452..f2d0a3e 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-list.html
@@ -4,32 +4,47 @@
         <div id="content-area" class="col-md-9" role="main">
             <div class="top-nav">
                 <ul class="rcue-tabs">
-                    <li><a href="#/create/role/{{realm.id}}">New Realm Role</a></li>
-                    <li class="active"><a href="#/realms/{{realm.id}}/roles">Realm Roles</a></li>
-                    <li><a href="#/realms/{{realm.id}}">Realm Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}">General</a></li>
+                    <li data-ng-show="realm.social"><a href="#">Social</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/roles">Roles</a></li>
+                    <li><a href="#/realms/{{realm.id}}/required-credentials">Credentials</a></li>
+                    <li><a href="#/realms/{{realm.id}}/token-settings">Token</a></li>
                 </ul>
             </div>
             <div id="content">
-                <h2 class="pull-left">Realm Roles</h2>
+                <ol class="breadcrumb" data-ng-hide="createRealm">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}">Settings</a></li>
+                    <li class="active">Roles</li>
+                </ol>
+                <h2 class="pull-left"><span>{{realm.realm}}</span> Roles</h2>
                 <table>
-                    <caption data-ng-show="roles && roles.length > 0">Table of realm roles</caption>
+                    <caption class="hidden" data-ng-show="roles && roles.length > 0">Table of realm roles</caption>
                     <caption data-ng-show="!roles || roles.length == 0">No configured realm roles...</caption>
                     <thead>
-                    <tr data-ng-show="roles && roles.length > 5">
-                        <th class="rcue-table-actions" colspan="2">
-                            <div class="search-comp clearfix">
-                                <input type="text" placeholder="Search..." class="search">
-                                <button class="icon-search tooltipRightTrigger"
-                                        data-original-title="Search by role name.">
-                                    Icon: search
-                                </button>
-                            </div>
-                        </th>
-                    </tr>
-                    <tr>
-                        <th>Role Name</th>
-                        <th>Description</th>
-                    </tr>
+                        <tr>
+                            <th class="rcue-table-actions" colspan="2">
+                                <div class="actions">
+                                    <a class="button" href="#/create/role/{{realm.id}}">Add</a>
+                                    <!-- <button class="remove disabled">Remove</button> -->
+                                </div>
+                            </th>
+                        </tr>
+                        <tr data-ng-show="roles && roles.length > 5">
+                            <th class="rcue-table-actions" colspan="2">
+                                <div class="search-comp clearfix">
+                                    <input type="text" placeholder="Search..." class="search">
+                                    <button class="icon-search tooltipRightTrigger"
+                                            data-original-title="Search by role name.">
+                                        Icon: search
+                                    </button>
+                                </div>
+                            </th>
+                        </tr>
+                        <tr>
+                            <th>Role Name</th>
+                            <th>Description</th>
+                        </tr>
                     </thead>
                     <tfoot data-ng-show="roles && roles.length > 5"> <!-- todo -->
                     <tr>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-mappings.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-mappings.html
index d4ffcce..902394d 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-mappings.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/role-mappings.html
@@ -4,36 +4,48 @@
         <div id="content-area" class="col-md-9" role="main">
             <div class="top-nav">
                 <ul class="rcue-tabs" >
-                    <li><a href="#/create/user/{{realm.id}}">New User</a></li>
-                    <li><a href="#/realms/{{realm.id}}/users">Query Users</a></li>
-                    <li><a href="#/realms/{{realm.id}}/users/{{user.username}}">{{user.username}} Attributes</a></li>
-                    <li><a href="#">{{user.username}} Credentials</a></li>
-                    <li class="active"><a href="#">{{user.username}} Role Mappings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/users/{{user.username}}">Attributes</a></li>
+                    <li><a href="#">Credentials</a></li>
+                    <li class="active"><a href="#">Role Mappings</a></li>
                 </ul>
             </div>
             <div id="content">
-                <h2 class="pull-left">User Role Mappings for <span>{{user.username}}</span></h2>
-                <p class="subtitle"></p>
+                <ol class="breadcrumb">
+                    <li><a href="#/realms/{{realm.id}}">{{realm.realm}}</a></li>
+                    <li><a href="#/realms/{{realm.id}}/users">Users</a></li>
+                    <li><a href="#/realms/{{realm.id}}/users/{{user.username}}">{{user.username}}</a></li>
+                    <li class="active">Role Mappings</li>
+                </ol>
+                <h2 class="pull-left"><span>{{user.username}}'s</span> Role Mappings</h2>
+                <p class="subtitle">All fields required</p>
                 <form name="realmForm" novalidate>
-                    <fieldset>
-                        <legend uncollapsed><span class="text">Realm Roles</span> </legend>
+                    <fieldset class="border-top">
                         <div class="form-group">
-                            <div class="controls">
-                                <select multiple size="5"
-                                        ng-multiple="true"
-                                        ng-model="selectedRealmRoles"
-                                        ng-options="r.name for r in realmRoles">
-                                </select>
-                                <button type="submit" ng-click="addRealmRole()">---&gt;</button>
-                                <button type="submit" ng-click="deleteRealmRole()">&lt;---</button>
-                                <select multiple size=5
+                            <div class="controls changing-selectors">
+                                <div class="select-title">
+                                    <label for="available">Available Roles</label>
+                                    <select id="available" class="form-control" multiple size="5"
+                                            ng-multiple="true"
+                                            ng-model="selectedRealmRoles"
+                                            ng-options="r.name for r in realmRoles">
+                                    </select>
+                                </div>
+                                <div class="middle-buttons">
+                                    <button type="submit" ng-click="addRealmRole()" data-original-title="Move right" class="tooltipRightTrigger"><span class="icon-arrow-right">Move right</span></button>
+                                    <button type="submit" ng-click="deleteRealmRole()" data-original-title="Move left" class="tooltipRightTrigger"><span class="icon-arrow-left">Move left</span></button>
+                                </div>
+                                <div class="select-title">
+                                    <label for="assigned">Assigned Roles</label>
+                                    <select id="assigned" class="form-control" multiple size=5
                                         ng-multiple="true"
                                         ng-model="selectedRealmMappings"
                                         ng-options="r.name for r in realmMappings">
-                                </select>
+                                    </select>
+                                </div>
                             </div>
                         </div>
                     </fieldset>
+                    
                     <fieldset ng-show="applications.length > 0">
                         <legend collapsed><span class="text">Application Roles</span> </legend>
                         <div class="form-group input-select">
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.css b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.css
index 596fdfc..acc7fb4 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.css
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.css
@@ -5,6 +5,92 @@ body {
   color: #4d5258;
   font-family: "Open Sans", sans-serif;
 }
+.feedback-aligner {
+  top: 0.9em;
+}
+/* Header */
+.header.rcue .navbar.primary .navbar-inner {
+  min-height: 42px;
+}
+.header.rcue .navbar.primary .nav > li .dropdown-label {
+  font-size: 0.84615384615385em;
+  color: #dbdada;
+  margin-left: 1.36363636363636em;
+  display: inline-block;
+}
+.header.rcue .navbar.primary .nav > li .dropdown {
+  display: inline-block;
+  margin-left: 0.53846153846154em;
+  margin-top: 0.46153846153846em;
+  min-width: 15.3846153846154em;
+  width: auto;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-toggle {
+  font-size: 0.84615384615385em;
+  color: #fff;
+  display: inline-block;
+  line-height: 2.36363636363636em;
+  border: 1px solid #676c6e;
+  border-radius: 2px;
+  padding: 0 0.54545454545455em;
+  background: #555a5e url(img/sprite-arrow-down.svg) no-repeat right -26px;
+  display: block;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-toggle:hover,
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-toggle:focus {
+  text-decoration: none;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-toggle:hover {
+  border-color: #7e8385;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu {
+  left: 0;
+  min-width: 0;
+  width: 100%;
+  overflow: hidden;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li,
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li.selected {
+  width: auto;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li a,
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li.selected a {
+  width: auto;
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid transparent;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li a:hover,
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li.selected a:hover {
+  background-color: #D5ECF9;
+  background-image: none;
+  border-bottom: 1px solid #A7D7F1;
+  border-top: 1px solid #A7D7F1;
+  color: #4D5258;
+}
+.header.rcue .navbar.primary .nav > li .dropdown .dropdown-menu li.selected a {
+  background-color: #2B99C0;
+  background-image: linear-gradient(top, #2ea1ca 0%, #2792b6 100%);
+  background-image: -o-linear-gradient(top, #2ea1ca 0%, #2792b6 100%);
+  background-image: -moz-linear-gradient(top, #2ea1ca 0%, #2792b6 100%);
+  background-image: -webkit-linear-gradient(top, #2ea1ca 0%, #2792b6 100%);
+  background-image: -ms-linear-gradient(top, #2ea1ca 0%, #2792b6 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #2ea1ca), color-stop(1, 0, #2792b6));
+  background-repeat: repeat-x;
+  color: #FFFFFF;
+}
+.header.rcue .navbar.primary .nav > li .dropdown.open .dropdown-toggle {
+  text-decoration: none;
+  box-shadow: inset 0px 2px 5px rgba(0, 0, 0, 0.2);
+  border-color: #7e8385;
+}
+.header.rcue .navbar.primary .button {
+  font-size: 0.84615384615385em;
+  margin-right: 1.36363636363636em;
+  margin-top: 0.63636363636364em;
+}
+.header.rcue .navbar.primary .button:focus {
+  text-decoration: none;
+}
 .bs-sidebar {
   background-color: #f9f9f9;
   padding-top: 4.3em;
@@ -197,6 +283,7 @@ table a:hover {
   width: 30.8em;
   padding-left: 1.5em;
   padding-right: 1.5em;
+  padding-top: .5em;
   background-color: #fff;
   border: 1px solid #b6b6b6;
   border-top: none;
@@ -221,6 +308,118 @@ table a:hover {
 td.token-cell button {
   margin-top: -1px;
 }
+/* Page: User Account */
+.user form fieldset div:first-child {
+  margin-top: 1em;
+}
+.user form fieldset p + div {
+  margin-top: 2.5em;
+}
+.user .bs-sidebar {
+  padding-top: 3.3em;
+}
+.user p.info {
+  font-size: 1.1em;
+}
+table.list {
+  border-left: none;
+  border-right: none;
+  margin-top: 1.5em;
+  border-color: #ededed;
+}
+table.list caption {
+  display: none;
+}
+table.list tbody tr:first-child td {
+  border-top: 1px solid #ededed;
+}
+table.list tbody tr:nth-child(2n) {
+  background-color: #fff;
+}
+table.list tbody tr td {
+  border-right: none;
+  border-left: none;
+}
+table.list tbody tr td.provider {
+  font-weight: bold;
+  font-size: 1.2em;
+}
+table.list tbody tr td.provider a {
+  padding-top: 0.41666666666667em;
+  padding-bottom: 0.33333333333333em;
+  display: inline-block;
+}
+table.list tbody tr td.soft {
+  color: #a1a1a1;
+}
+table.list tbody tr td.action {
+  text-align: right;
+  font-size: 1em;
+}
+table.list tbody tr.expanded {
+  background-color: #f6f6f6;
+}
+table.list tbody tr.expanded .provider {
+  font-size: 1.39130434782609em;
+  padding-top: 0.5em;
+  display: block;
+}
+table.list tbody tr.expanded p {
+  margin-top: 1.30434782608696em;
+  margin-bottom: 1.73913043478261em;
+}
+table.list tbody tr.expanded ul li {
+  margin-left: 1.30434782608696em;
+}
+table.list tbody tr.expanded ul li .item,
+table.list tbody tr.expanded ul li .status {
+  margin-right: 2.60869565217391em;
+}
+table.list tbody tr.expanded ul li .red {
+  color: #BA1212;
+}
+table.list tbody tr.expanded .form-actions {
+  font-size: 0.8695652173913em;
+  margin-top: 0.5em;
+  margin-bottom: 1.5em;
+}
+/* Page: TOTP setup */
+.totp ol li {
+  margin-bottom: 2.5em;
+  margin-left: 2.4em;
+  width: 100%;
+}
+.totp ol li p {
+  font-size: 1.3em;
+  margin-bottom: 1.53846153846154em;
+}
+.totp ol li p strong {
+  text-indent: -1em;
+  float: left;
+  font-size: 1.84615384615385em;
+  font-weight: normal;
+  margin-top: -0.375em;
+  color: #999;
+}
+.totp ol li img {
+  width: 136px;
+}
+.totp ol li .code {
+  font-size: 1.3em;
+  margin-left: 1.53846153846154em;
+  vertical-align: bottom;
+}
+.totp ol li:last-child {
+  margin-bottom: 0;
+}
+.totp ol li .form-actions {
+  margin-right: 2.4em;
+}
+.totp ol li .form-actions input[type="button"],
+.totp ol li .form-actions button,
+.totp ol li .form-actions a.button {
+  font-size: 1.1em;
+}
 /* Break Points */
 @media (max-width: 1200px) {
   #container-right-bg {
@@ -229,11 +428,13 @@ td.token-cell button {
   }
 }
 @media (max-width: 992px) {
-  .bs-sidebar {
+  .bs-sidebar,
+  .user .bs-sidebar {
     padding-top: 2em;
     width: 100%;
   }
-  .bs-sidebar ul li a {
+  .bs-sidebar ul li a,
+  .user .bs-sidebar ul li a {
     border-width: 1px;
   }
   #content-area .top-nav {
@@ -243,6 +444,9 @@ td.token-cell button {
     margin-left: 0;
     width: 750px;
   }
+  .user #content-area #content {
+    border-top: 1px solid #cecece;
+  }
 }
 @media (max-width: 768px) {
   .container {
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.less b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.less
index 409a44c..5fa386a 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.less
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/admin-console.less
@@ -15,6 +15,121 @@ body {
     font-family: @open-sans;
 }
 
+.feedback-aligner {
+    top: 0.9em;
+}
+
+
+/* Header */
+
+.header.rcue .navbar.primary {
+
+    .navbar-inner {
+        min-height: 42px;
+    }
+    
+    .nav > li {
+    
+        .dropdown-label {
+            font-size: 0.84615384615385em;
+            color: #dbdada;
+            margin-left: 1.36363636363636em;
+            display: inline-block;
+        }
+        
+        .dropdown {
+            display: inline-block;
+            margin-left: 0.53846153846154em;
+            margin-top: 0.46153846153846em;
+            min-width: 15.3846153846154em;
+            width: auto;
+            
+            .dropdown-toggle {
+                font-size: 0.84615384615385em;
+                color: #fff;
+                display: inline-block;
+                line-height: 2.36363636363636em;
+                border: 1px solid #676c6e;
+                border-radius: 2px;
+                padding: 0 0.54545454545455em;
+                background: #555a5e url(img/sprite-arrow-down.svg) no-repeat right -26px;
+                display: block;
+                
+                &:hover,
+                &:focus {
+                    text-decoration: none;
+                }
+                
+                &:hover {
+                    border-color: #7e8385;
+                }
+            }
+            
+            .dropdown-menu {
+            
+                left: 0;
+                min-width: 0;
+                width: 100%;
+                overflow: hidden;
+            
+                li,
+                li.selected {
+                    width: auto;
+                    
+                    a {
+                        width: auto;
+                        border-top: 1px solid transparent;
+                        border-bottom: 1px solid transparent;
+                        
+                        &:hover {
+                            background-color: #D5ECF9;
+                            background-image: none;
+                            border-bottom: 1px solid #A7D7F1;
+                            border-top: 1px solid #A7D7F1;
+                            color: #4D5258;
+                        }
+                    }
+                }
+                
+                li.selected a {
+                    background-color: #2B99C0;
+                    background-image: linear-gradient(top, #2EA1CA 0%, #2792B6 100%);
+                    background-image: -o-linear-gradient(top, #2EA1CA 0%, #2792B6 100%);
+                    background-image: -moz-linear-gradient(top, #2EA1CA 0%, #2792B6 100%);
+                    background-image: -webkit-linear-gradient(top, #2EA1CA 0%, #2792B6 100%);
+                    background-image: -ms-linear-gradient(top, #2EA1CA 0%, #2792B6 100%);
+                    background-image: -webkit-gradient(
+                      linear,
+                      left top,
+                      left bottom,
+                      color-stop(0.0, #2EA1CA),
+                      color-stop(1,0, #2792B6)
+                    );
+                    background-repeat: repeat-x;
+                    color: #FFFFFF;
+                }
+            }
+        
+            &.open .dropdown-toggle {
+                text-decoration: none;
+                box-shadow: inset 0px 2px 5px rgba(0,0,0,0.2);
+                border-color: #7e8385;
+            }
+        }
+    }
+    
+    .button {
+        font-size: 0.84615384615385em;
+        margin-right: 1.36363636363636em;
+        margin-top: 0.63636363636364em;
+        
+        &:focus {
+            text-decoration: none;
+        }
+    }
+} 
+
+
 .bs-sidebar {
     background-color: @bg-grey;
     padding-top: 4.3em;
@@ -256,6 +371,7 @@ table {
         width: 30.8em;
         padding-left: 1.5em;
         padding-right: 1.5em;
+        padding-top: .5em;
         background-color: #fff;
         border: 1px solid #b6b6b6;
         border-top: none;
@@ -287,6 +403,158 @@ td.token-cell button {
 }
 
 
+/* Page: User Account */
+
+.user {
+    
+    form fieldset div:first-child {
+        margin-top: 1em;
+    }
+    
+    form fieldset p + div {
+        margin-top: 2.5em;
+    }
+    
+    .bs-sidebar {
+        padding-top: 3.3em;
+    }
+    
+    p.info {
+        font-size: 1.1em;
+    }
+}
+
+table.list {
+    
+    border-left: none;
+    border-right: none;
+    margin-top: 1.5em;
+    border-color: #ededed;
+    
+    caption {
+        display: none;
+    }
+    
+    tbody tr {
+    
+        &:first-child td {
+            border-top: 1px solid #ededed;
+        }
+        
+        &:nth-child(2n) {
+            background-color: #fff;
+        }
+        
+        td {
+            border-right: none;
+            border-left: none;
+            
+            &.provider {
+                font-weight: bold;
+                font-size: 1.2em;
+                
+                a {
+                    padding-top: 0.41666666666667em;
+                    padding-bottom: 0.33333333333333em;
+                    display: inline-block;
+                }
+            }
+            
+            &.soft {
+                color: #a1a1a1;
+            }
+            
+            &.action {
+                text-align: right;
+                font-size: 1em;
+            }
+        }
+        
+        &.expanded {
+        
+            background-color: #f6f6f6;
+                
+            .provider {
+                font-size: 1.39130434782609em;
+                padding-top: 0.5em;
+                display: block;
+            }
+            
+            p {
+                margin-top: 1.30434782608696em;
+                margin-bottom: 1.73913043478261em;
+            }
+            
+            ul li {
+                margin-left: 1.30434782608696em;
+                
+                .item,
+                .status {
+                    margin-right: 2.60869565217391em;
+                }
+                
+                .red {
+                    color: #BA1212;
+                }
+            }
+            
+            .form-actions {
+                font-size: 0.8695652173913em;
+                margin-top: 0.5em;
+                margin-bottom: 1.5em;
+            }
+        }
+    }
+}
+
+/* Page: TOTP setup */
+
+.totp ol li {
+    margin-bottom: 2.5em;
+    margin-left: 2.4em;
+    width: 100%;
+    
+    p {
+        font-size: 1.3em;
+        margin-bottom: 1.53846153846154em;
+        
+        strong {
+            text-indent: -1em;
+            float: left;
+            font-size: 1.84615384615385em;
+            font-weight: normal;
+            margin-top: -0.375em;
+            color: #999;
+        }
+    }
+    
+    img {
+        width: 136px;
+    }
+    
+    .code {
+        font-size: 1.3em;
+        margin-left: 1.53846153846154em;
+        vertical-align: bottom;
+    }
+        
+    &:last-child {
+        margin-bottom: 0;
+    }
+    
+    .form-actions {
+        margin-right: 2.4em;
+        
+        input[type="button"], 
+        button, 
+        a.button {
+            font-size: 1.1em;
+        }
+    }
+}
+
+
+
 /* Break Points */
 
 @media (max-width: 1200px) {
@@ -299,7 +567,8 @@ td.token-cell button {
 
 @media (max-width: 992px) {
 
-    .bs-sidebar {
+    .bs-sidebar,
+    .user .bs-sidebar {
         padding-top: 2em;
         width: 100%;
         
@@ -316,6 +585,10 @@ td.token-cell button {
         margin-left: 0;
         width: 750px;
     }
+    
+    .user #content-area #content {
+        border-top: 1px solid #cecece;
+    }
 
 }
 
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.css b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.css
index 2576209..a23e981 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.css
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.css
@@ -29,12 +29,19 @@ a:hover {
   text-decoration: underline;
 }
 /* Styles from Gabriel */
+a:hover,
+a:focus {
+  color: #0099d3;
+}
 strong {
   font-weight: bold;
 }
 .hidden {
   display: none;
 }
+.feedback.show {
+  display: inline-block !important;
+}
 .pull-right {
   float: right;
 }
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.less b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.less
index 9af7c45..ee48322 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.less
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/base.less
@@ -33,6 +33,11 @@ a:hover {
 
 /* Styles from Gabriel */
 
+a:hover,
+a:focus {
+    color: #0099d3;
+}
+
 strong {
     font-weight: bold;
 }
@@ -41,6 +46,10 @@ strong {
     display: none;
 }
 
+.feedback.show {
+    display: inline-block!important;
+}
+
 .pull-right {
     float: right;
 }
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.css b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.css
index 5f105e2..6b3afd3 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.css
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.css
@@ -33,7 +33,6 @@ input[type="text"].error,
 input[type="password"].error,
 input[type="email"].error {
   border-color: #ba1212;
-  background-color: #f8e7e7;
   transition: all 0.33s ease-in-out;
   -moz-transition: all 0.33s ease-in-out;
   -webkit-transition: all 0.33s ease-in-out;
@@ -143,7 +142,8 @@ a.button {
   padding-bottom: 0;
   line-height: 2.18181818181818em;
 }
-button.primary {
+button.primary,
+.button.primary {
   border-color: #21799e;
   background-image: linear-gradient(top, #00a9ec 0%, #009bd3 100%);
   background-image: -o-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
@@ -154,14 +154,37 @@ button.primary {
   color: #fff;
 }
 button.primary:hover,
-button.primary:focus {
+button.primary:focus,
+.button.primary:hover,
+.button.primary:focus {
   background-color: #009BD3;
 }
-button.primary:enabled:active {
+button.primary:enabled:active,
+.button.primary:enabled:active {
   background-color: #0099d4;
   box-shadow: inset 0 0 5px 3px #0074ae;
 }
 /* Code from Gabriel */
+button.primary,
+.button.primary {
+  background-color: #00a2df;
+}
+button.primary:hover,
+.button.primary:hover,
+button.primary:active,
+.button.primary:active,
+button.primary:focus,
+.button.primary:focus {
+  background-image: none;
+  color: #fff;
+}
+.rcue-login-register.register .two-fields input[type="text"] {
+  width: 121px;
+  min-width: 0;
+}
+.rcue-login-register.register .two-fields input + input {
+  margin-left: 10px;
+}
 .search-comp {
   position: relative;
   display: inline-block;
@@ -187,6 +210,23 @@ button.primary:enabled:active {
   width: 20em;
   font-weight: normal;
 }
+.feedback-aligner {
+  position: absolute;
+  top: 1.5em;
+  text-align: center;
+  width: 100%;
+  height: 0;
+  z-index: 100;
+}
+.feedback-aligner .feedback {
+  position: relative;
+  display: inline-block;
+  text-align: left;
+  border-width: 1px;
+}
+.feedback-aligner .feedback p {
+  border-width: 1px;
+}
 .feedback {
   position: absolute;
   opacity: 0;
@@ -194,30 +234,49 @@ button.primary:enabled:active {
   -moz-transition: opacity 0.33s ease-in-out;
   -webkit-transition: opacity 0.33s ease-in-out;
 }
+.feedback p {
+  padding: 0.90909090909091em 3.63636363636364em;
+  border-style: solid;
+  border-width: 1px 1px 0px 1px;
+  background-repeat: no-repeat;
+  background-position: 1.27272727272727em center;
+  font-size: 1.1em;
+  line-height: 1.4em;
+  border-radius: 2px;
+  color: #4d5258;
+  margin-bottom: 0;
+}
 .feedback.show {
   opacity: 1;
 }
-.feedback.error {
-  background-image: url(img/feedback-error-arrow-down.svg);
+.feedback.bottom-left {
   background-position: left bottom;
   background-repeat: no-repeat;
   padding-bottom: 1em;
 }
+.feedback.bottom-left p {
+  background-position: 1.27272727272727em 1.63636363636364em;
+}
+.feedback.error {
+  background-image: url(img/feedback-error-arrow-down.svg);
+}
 .feedback.error p {
   border-color: #b91415;
   background-image: url(img/feedback-error-sign.svg);
   background-color: #f8e7e7;
-  color: #4d5258;
 }
-.feedback p {
-  padding: 1em 3.63636363636364em;
-  border-style: solid;
-  border-width: 1px 1px 0px 1px;
-  background-repeat: no-repeat;
-  background-position: 1.27272727272727em 1.63636363636364em;
-  font-size: 1.1em;
-  line-height: 1.27272727272727em;
-  border-radius: 2px;
+.feedback.success {
+  background-image: url(img/feedback-success-arrow-down.svg);
+}
+.feedback.success p {
+  border-color: #4b9e39;
+  background-image: url(img/feedback-success-sign.svg);
+  background-color: #e4f1e1;
+}
+.feedback.warning p {
+  border-color: #f17528;
+  background-image: url(img/feedback-warning-sign.svg);
+  background-color: #fef1e9;
 }
 button,
 a.button {
@@ -240,6 +299,20 @@ button[class^="icon-"] {
 button[class^="icon-"]:hover {
   background-image: url(img/sprites.png);
 }
+button.link {
+  border: none;
+  background-color: transparent;
+  background: none;
+  box-shadow: none;
+  font-weight: normal;
+  font-size: 1em;
+  color: #0099D3;
+  letter-spacing: 0;
+  padding: 0;
+}
+button.link:hover {
+  text-decoration: underline;
+}
 legend {
   font-size: 1em;
   border-width: 1px 0 0 0;
@@ -266,6 +339,12 @@ legend .icon-info {
 legend .icon-info:hover {
   background-image: url(img/sprites.png);
 }
+fieldset.border-top {
+  border-width: 1px 0 0 0;
+  border-style: solid;
+  border-color: #e9e8e8;
+  padding-top: 2em;
+}
 .form-group {
   display: block;
   margin-bottom: 1em;
@@ -295,14 +374,15 @@ legend .icon-info:hover {
   margin-top: 4px;
 }
 .form-group .required {
-  position: absolute;
-  left: 10em;
   font-size: 1.1em;
   color: #CB2915;
 }
 legend + .form-group {
   padding-top: 1em;
 }
+legend + table {
+  margin-top: 1em;
+}
 .code {
   font-family: Courier, ​monospace;
 }
@@ -437,6 +517,11 @@ input[type="email"].tiny {
 .select-rcue option:hover {
   background-color: #d5ecf9;
 }
+.select2-container {
+  float: left;
+  margin-top: 0.3em;
+  margin-bottom: 0.3em;
+}
 .select2-container .select2-choice > .select2-chosen {
   line-height: 2.1em;
   padding-left: 0.90909090909091em;
@@ -448,13 +533,18 @@ input[type="email"].tiny {
 .select2-container .select2-choice .select2-arrow {
   display: none;
 }
+.select2-dropdown-open {
+  background-color: #fff;
+}
 .select2-dropdown-open .select2-choice,
 .select2-dropdown-open .select2-choices {
-  background-image: url(img/chosen-arrow-down.png), -moz-linear-gradient(center top, #eeeeee 0%, #ffffff 50%);
   border-bottom: none;
   border-radius: 2px 2px 0 0;
+  background-image: url(img/chosen-arrow-down.png);
+  background-color: transparent;
   background-repeat: no-repeat;
   background-position: right top;
+  box-shadow: none;
 }
 .select2-dropdown-open .select2-choice,
 .select2-dropdown-open.select2-drop-above .select2-choice,
@@ -467,24 +557,53 @@ input[type="email"].tiny {
 }
 .select2-drop-active {
   border-radius: 0 0 2px 2px;
-  margin-top: -3px;
-  padding-top: 3px;
+  margin-top: -1px;
+  padding-top: 4px;
 }
 .select2-container.select2-drop-above .select2-choice {
   border-radius: 0 0 2px 2px;
-  background-image: url(img/chosen-arrow-up.png), -moz-linear-gradient(center top, #eeeeee 0%, #ffffff 50%);
+  background-image: url(img/chosen-arrow-up.png);
   background-repeat: no-repeat;
-  background-position: right -1px;
+  background-position: right 0;
+  box-shadow: none;
 }
 .select2-drop.select2-drop-above {
   border-radius: 2px 2px 0 0;
   padding-top: 0;
-  margin-top: 0;
+  margin-top: 2px;
 }
 .select2-drop.select2-drop-above.select2-drop-active,
 .select2-drop-active {
   border-color: #62AFDB;
 }
+.select2-results {
+  padding-left: 0;
+  margin-right: 0;
+}
+.select2-results li {
+  border-top: 1px solid transparent;
+  border-bottom: 1px solid transparent;
+}
+.select2-results .select2-result-label,
+.select2-results .select2-no-results,
+.select2-results .select2-searching,
+.select2-results .select2-selection-limit {
+  font-size: 1.1em;
+  padding-left: 1.09090909090909em;
+}
+.select2-results .select2-no-results,
+.select2-results .select2-searching,
+.select2-results .select2-selection-limit {
+  color: #838383;
+  padding-top: 3px;
+  padding-bottom: 4px;
+}
+.select2-results .select2-highlighted {
+  background-color: #d5ecf9;
+  border-top: 1px solid #a7d7f1;
+  border-bottom: 1px solid #a7d7f1;
+  color: #4d5258;
+}
 .input-group input + .select-rcue {
   border-radius: 0 2px 2px 0;
   border-left: 0;
@@ -543,6 +662,7 @@ input[type="email"].tiny {
   margin: 0.272727272727273em 0;
   box-shadow: none;
   outline: 0 none;
+  float: left;
 }
 .tokenfield.form-control:hover {
   border-color: #62afdb;
@@ -552,7 +672,7 @@ input[type="email"].tiny {
   box-shadow: #62afdb 0 0 5px;
 }
 .token {
-  display: inline-block;
+  float: left;
   background-color: #d4ecf8;
   border: 1px solid #a3d7f0;
   border-radius: 1px;
@@ -563,12 +683,12 @@ input[type="email"].tiny {
   outline: 0 none;
 }
 .token span {
-  display: inline-block;
+  float: left;
   font-size: 1.1em;
   line-height: 1.45454545454545em;
 }
 .token .close {
-  text-indent: -99999em;
+  text-indent: -9999999em;
   width: 1.6em;
   height: 1.6em;
   line-height: 1.6em;
@@ -586,5 +706,72 @@ input[type="email"].tiny {
 }
 .form-actions .primary {
   float: right;
-  margin-left: 8px;
+  margin-left: 0.90909090909091em;
+}
+.form-actions a {
+  font-size: 1.1em;
+  margin-right: 0.90909090909091em;
+}
+.changing-selectors .select-title {
+  display: inline-block;
+}
+.changing-selectors .select-title label {
+  font-size: 1.1em;
+  margin-left: 0.2em;
+  margin-bottom: 0.3em;
+  margin-top: 0.5em;
+  display: block;
+  font-weight: normal;
+}
+.changing-selectors select {
+  min-height: 150px;
+  font-size: 1.1em;
+  padding: 0.545454545454545em;
+  min-width: 18.1818181818182em;
+  border: 1px #b6b6b6 solid;
+  border-radius: 2px;
+  box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.1);
+  color: #333;
+  max-width: 200px;
+  width: auto;
+  min-width: 150px;
+  display: inline-block;
+}
+.changing-selectors select:hover {
+  border-color: #62afdb;
+}
+.changing-selectors select option {
+  padding: 0.36363636363636em 0.45454545454545em;
+  display: block;
+}
+.changing-selectors select option[disabled="disabled"] {
+  color: #aaa;
+}
+.changing-selectors .middle-buttons {
+  display: inline-block;
+  width: 4.5em;
+  margin-left: 0.8em;
+  margin-right: 0.8em;
+  vertical-align: middle;
+}
+.changing-selectors .middle-buttons button:first-child {
+  margin-bottom: 0.5em;
+}
+.changing-selectors .middle-buttons button.disabled span {
+  opacity: 0.4;
+  filter: alpha(opacity=40);
+}
+.changing-selectors .middle-buttons button span {
+  margin-right: 0;
+}
+.breadcrumb {
+  background: none;
+  margin: 5px 0 5px 0;
+  padding: 0;
+}
+.breadcrumb li a {
+  font-size: 1.1em;
+}
+.breadcrumb > li + li:before {
+  content: "» ";
 }
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.less b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.less
index dfc353d..962e7b1 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.less
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/forms.less
@@ -35,7 +35,6 @@ input[type="email"],
     
     &.error {
         border-color: #ba1212;
-        background-color: #f8e7e7;
         transition: all .33s ease-in-out;
         -moz-transition: all .33s ease-in-out;
         -webkit-transition: all .33s ease-in-out;
@@ -150,7 +149,8 @@ a.button {
       line-height: 2.18181818181818em;
 }
 
-button.primary {
+button.primary,
+.button.primary {
   border-color: #21799e;
   background-image: linear-gradient(top, #00A9EC 0%, #009BD3 100%);
   background-image: -o-linear-gradient(top, #00A9EC 0%, #009BD3 100%);
@@ -168,11 +168,14 @@ button.primary {
 }
 
 button.primary:hover,
-button.primary:focus {
+button.primary:focus,
+.button.primary:hover,
+.button.primary:focus {
   background-color: #009BD3;
 }
 
-button.primary:enabled:active {
+button.primary:enabled:active,
+.button.primary:enabled:active {
   background-color: #0099d4;
   box-shadow: inset 0 0 5px 3px #0074ae;
 }
@@ -180,6 +183,30 @@ button.primary:enabled:active {
 
 /* Code from Gabriel */
 
+button.primary,
+.button.primary {
+    background-color: #00a2df;
+    
+    &:hover,
+    &:active,
+    &:focus {
+        background-image: none;
+        color: #fff;
+    }
+}
+
+.rcue-login-register.register .two-fields {
+    
+    input[type="text"] {
+        width: 121px;
+        min-width: 0;
+    }
+    
+    input + input {
+        margin-left: 10px;
+    }  
+} 
+
 .search-comp {
     position: relative;
     display: inline-block;
@@ -210,40 +237,88 @@ button.primary:enabled:active {
     }
 }
 
+.feedback-aligner {
+    position: absolute;
+    top: 1.5em;
+    text-align: center;
+    width: 100%;
+    height: 0;
+    z-index: 100;
+    
+    .feedback {
+        position: relative;
+        display: inline-block;
+        text-align: left;
+        border-width: 1px;
+        
+        p {
+            border-width: 1px;
+        }
+    }
+}
+
 .feedback {
     position: absolute;
     opacity: 0;
     transition: opacity .33s ease-in-out;
     -moz-transition: opacity .33s ease-in-out;
     -webkit-transition: opacity .33s ease-in-out;
+    
+    p {
+        padding: 0.90909090909091em 3.63636363636364em;
+        border-style: solid;
+        border-width: 1px 1px 0px 1px;
+        background-repeat: no-repeat;
+        background-position: 1.27272727272727em center;
+        font-size: 1.1em;
+        line-height: 1.4em;
+        border-radius: 2px;
+        color: #4d5258;
+        margin-bottom: 0;
+    }
    
     &.show {
         opacity: 1;
     }
-
-    &.error {
-        background-image: url(img/feedback-error-arrow-down.svg);
+    
+    &.bottom-left {
         background-position: left bottom;
         background-repeat: no-repeat;
         padding-bottom: 1em;
         
         p {
+            background-position: 1.27272727272727em 1.63636363636364em;
+        }
+    }
+
+    &.error {
+        background-image: url(img/feedback-error-arrow-down.svg);
+        
+        p {
             border-color: #b91415;
             background-image: url(img/feedback-error-sign.svg);
             background-color: #f8e7e7;
-            color: #4d5258;
         }
     }
     
-    p {
-        padding: 1em 3.63636363636364em;
-        border-style: solid;
-        border-width: 1px 1px 0px 1px;
-        background-repeat: no-repeat;
-        background-position: 1.27272727272727em 1.63636363636364em;
-        font-size: 1.1em;
-        line-height: 1.27272727272727em;
-        border-radius: 2px;
+    &.success {
+        background-image: url(img/feedback-success-arrow-down.svg);
+                
+        p {
+            border-color: #4b9e39;
+            background-image: url(img/feedback-success-sign.svg);
+            background-color: #e4f1e1;
+        }
+    }
+    
+    &.warning {
+        
+        p {
+            border-color: #f17528;
+            background-image: url(img/feedback-warning-sign.svg);
+            background-color: #fef1e9;
+        }
+        
     }
 }
 
@@ -273,6 +348,22 @@ button[class^="icon-"] {
     }
 }
 
+button.link {
+    border: none;
+    background-color: transparent;
+    background: none;
+    box-shadow: none;
+    font-weight: normal;
+    font-size: 1em;
+    color: 	#0099D3;
+    letter-spacing: 0;
+    padding: 0;
+    
+    &:hover {
+        text-decoration: underline;
+    }
+}
+
 legend {
     font-size: 1em;
     border-width: 1px 0 0 0;
@@ -304,6 +395,13 @@ legend {
     }
 }
 
+fieldset.border-top {
+    border-width: 1px 0 0 0;
+    border-style: solid;
+    border-color: #e9e8e8;
+    padding-top: 2em;
+}
+
 .form-group {
     display: block;
     margin-bottom: 1em;
@@ -338,8 +436,6 @@ legend {
     }
     
     .required {
-        position: absolute;
-        left: 10em;
         font-size: 1.1em;
         color: #CB2915;
     }
@@ -349,6 +445,10 @@ legend + .form-group {
     padding-top: 1em;
 }
 
+legend + table {
+    margin-top: 1em;
+}
+
 .code {
     font-family: Courier, ​monospace;
 }
@@ -521,32 +621,42 @@ input[type="email"] {
     }
 }
 
-.select2-container .select2-choice {
+.select2-container {
+    float: left;
+    margin-top: 0.3em;
+    margin-bottom: 0.3em;
     
-    &> .select2-chosen {
-        line-height: 2.1em;
-        padding-left: 0.90909090909091em;
-        margin-right: 0;
-        font-size: 1.1em;
-        padding-right: 2.36363636363636em;
-        padding-right: 26px;
-    }
+    .select2-choice {
     
-    .select2-arrow {
-        display: none;
+        &> .select2-chosen {
+            line-height: 2.1em;
+            padding-left: 0.90909090909091em;
+            margin-right: 0;
+            font-size: 1.1em;
+            padding-right: 2.36363636363636em;
+            padding-right: 26px;
+        }
+        
+        .select2-arrow {
+            display: none;
+        }
     }
 }
 
 .select2-dropdown-open {
-    
+
     .select2-choice,
     .select2-choices {
-        background-image: url(img/chosen-arrow-down.png), -moz-linear-gradient(center top , #eee 0%, #fff 50%);
         border-bottom: none;
         border-radius: 2px 2px 0 0;
+        background-image: url(img/chosen-arrow-down.png);
+        background-color: transparent;
         background-repeat: no-repeat;
         background-position: right top;
+        box-shadow: none;
     }
+    
+    background-color: #fff;
 }
 
 .select2-dropdown-open,
@@ -564,21 +674,22 @@ input[type="email"] {
 
 .select2-drop-active {
     border-radius: 0 0 2px 2px;
-    margin-top: -3px;
-    padding-top: 3px;
+    margin-top: -1px;
+    padding-top: 4px;
 }
 
 .select2-container.select2-drop-above .select2-choice {
     border-radius: 0 0 2px 2px;
-    background-image: url(img/chosen-arrow-up.png), -moz-linear-gradient(center top , #eee 0%, #fff 50%);
+    background-image: url(img/chosen-arrow-up.png);
     background-repeat: no-repeat;
-    background-position: right -1px;
+    background-position: right 0;
+    box-shadow: none;
 }
 
 .select2-drop.select2-drop-above {
     border-radius: 2px 2px 0 0;
     padding-top: 0;
-    margin-top: 0;
+    margin-top: 2px;
 }
 
 .select2-drop.select2-drop-above.select2-drop-active,
@@ -586,6 +697,39 @@ input[type="email"] {
     border-color: #62AFDB;
 }
 
+.select2-results {
+    padding-left: 0;
+    margin-right: 0;
+    
+    li {
+        border-top: 1px solid transparent;
+        border-bottom: 1px solid transparent;
+    }
+    
+    .select2-result-label,
+    .select2-no-results, 
+    .select2-searching, 
+    .select2-selection-limit {
+        font-size: 1.1em;
+        padding-left: 1.09090909090909em;
+    }
+    
+    .select2-no-results, 
+    .select2-searching, 
+    .select2-selection-limit {
+        color: #838383;
+        padding-top: 3px;
+        padding-bottom: 4px;
+    }
+    
+    .select2-highlighted {
+        background-color: #d5ecf9;
+        border-top: 1px solid #a7d7f1;
+        border-bottom: 1px solid #a7d7f1;
+        color: #4d5258;
+    }
+}
+
 .input-group input + .select-rcue {
     border-radius: 0 2px 2px 0;
     border-left: 0;
@@ -649,6 +793,7 @@ input[type="email"] {
         margin: 0.272727272727273em 0;
         box-shadow: none;
         outline: 0 none;
+        float: left;
     }   
     
     &:hover {
@@ -662,7 +807,7 @@ input[type="email"] {
 }
 
 .token {
-    display: inline-block;
+    float: left;
     background-color: #d4ecf8;
     border: 1px solid #a3d7f0;
     border-radius: 1px;
@@ -673,13 +818,13 @@ input[type="email"] {
     outline: 0 none;
         
     span {
-        display: inline-block;
+        float: left;
         font-size: 1.1em;
         line-height: 1.45454545454545em;
     }
     
     .close {
-        text-indent: -99999em;
+        text-indent: -9999999em;
         width: 1.6em;
         height: 1.6em;
         line-height: 1.6em;
@@ -699,6 +844,99 @@ input[type="email"] {
     
     .primary {
         float: right;
-        margin-left: 8px;
+        margin-left: 0.90909090909091em;
+    }
+    
+    a {
+        font-size: 1.1em;
+        margin-right: 0.90909090909091em;
+    }
+}
+
+.changing-selectors {
+
+    .select-title {
+    
+        display: inline-block;
+        
+        label {
+            font-size: 1.1em;
+            margin-left: 0.2em;
+            margin-bottom: 0.3em;
+            margin-top: 0.5em;
+            display: block;
+            font-weight: normal;
+        }
+        
+    }
+    
+    select {
+        min-height: 150px;
+        font-size: 1.1em;
+        padding: 0.545454545454545em;
+        min-width: 18.1818181818182em;
+        border: 1px #b6b6b6 solid;
+        border-radius: 2px;
+        box-shadow: inset 0px 2px 2px rgba(0,0,0,0.1);
+        color: #333;
+        max-width: 200px;
+        width: auto;
+        min-width: 150px;
+        display: inline-block;
+        
+        &:hover {
+            border-color: #62afdb;
+        }
+                
+        option {
+            padding: 0.36363636363636em 0.45454545454545em;
+            display: block;
+            
+            &[disabled="disabled"] {
+                color: #aaa;
+            }
+        }
+    }
+    
+    .middle-buttons {
+        display: inline-block;
+        width: 4.5em;
+        margin-left: 0.8em;
+        margin-right: 0.8em;
+        vertical-align: middle;
+        
+        button {
+            
+            &:first-child {
+                margin-bottom: 0.5em;
+            }
+            
+            &.disabled span {
+                opacity: 0.4;
+                filter: alpha(opacity=40);
+            }
+            
+            span {
+                margin-right: 0;
+            }
+        }
+    }
+}
+
+.breadcrumb {
+    
+    background: none;
+    margin: 5px 0 5px 0;
+    padding: 0;
+    
+    li {
+        
+        a {
+            font-size: 1.1em;
+        }
+    }
+    
+    > li + li:before {
+        content: "» ";
     }
 }
\ No newline at end of file
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/img/sprite-arrow-down.png b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/img/sprite-arrow-down.png
new file mode 100644
index 0000000..fb65819
Binary files /dev/null and b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/img/sprite-arrow-down.png differ
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/img/sprite-arrow-down.svg b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/img/sprite-arrow-down.svg
new file mode 100644
index 0000000..87c4cda
--- /dev/null
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/img/sprite-arrow-down.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 width="22px" height="52px" viewBox="0 0 22 52" enable-background="new 0 0 22 52" xml:space="preserve">
+<polygon fill="#828487" points="11,16 6.818,11.818 7.525,11.111 11,14.586 14.475,11.111 15.182,11.818 "/>
+<polygon fill="#DBDADA" points="11,42 6.818,37.818 7.525,37.111 11,40.586 14.475,37.111 15.182,37.818 "/>
+</svg>
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.css b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.css
index 1b0f3da..15a1f34 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.css
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.css
@@ -88,25 +88,26 @@ table tbody tr:hover {
 table tbody tr {
   border-top: 1px solid #ededed;
 }
-table tbody tr.selected {
-  background-color: #eaf5fb;
-}
-table tbody tr.selected td:first-child {
-  background-image: url(img/icon-row-selected.svg);
-  background-position: 0.2em center;
-  background-repeat: no-repeat;
-}
 table tbody tr:hover {
   cursor: default;
 }
+table tbody tr td {
+  vertical-align: middle;
+}
 table tbody tr td.token-cell {
   padding: 0 0.7em;
+  line-height: 0;
 }
 table tbody tr td.token-cell .token {
   padding-top: 0.18181818181818em;
   padding-bottom: 0.18181818181818em;
-  margin-top: 7px;
+  margin-top: 6px;
+  margin-bottom: 5px;
+}
+table tbody tr td.token-cell button {
+  float: left;
   margin-bottom: 7px;
+  margin-top: 8px;
 }
 table tbody.selectable-rows tr:hover {
   cursor: pointer;
@@ -115,6 +116,16 @@ table tbody.selectable-rows tr:hover {
 table tbody.selectable-rows tr:first-child td {
   padding-top: 9px;
 }
+table tbody.selectable-rows tr.selected,
+table tbody.selectable-rows tr.selected:hover {
+  background-color: #eaf5fb;
+}
+table tbody.selectable-rows tr.selected td:first-child,
+table tbody.selectable-rows tr.selected:hover td:first-child {
+  background-image: url(img/icon-row-selected.svg);
+  background-position: 0.2em center;
+  background-repeat: no-repeat;
+}
 table tfoot tr {
   border-top: 1px solid #cecece;
 }
diff --git a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.less b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.less
index 0a35bc5..6426f29 100644
--- a/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.less
+++ b/admin-ui-styles/src/main/resources/META-INF/resources/admin-ui/css/tables.less
@@ -120,28 +120,29 @@ table {
         
             border-top: 1px solid #ededed;
                     
-            &.selected {
-                background-color: #eaf5fb;
-                
-                td:first-child {
-                    background-image: url(img/icon-row-selected.svg);
-                    background-position: 0.2em center;
-                    background-repeat: no-repeat;
-                }
-            }
-            
             &:hover {
                 cursor: default;
             }
             
+            td {
+                vertical-align: middle;
+            }
+            
             td.token-cell {
                 padding: 0 0.7em;
+                line-height: 0;
                 
                 .token {
                     padding-top: 0.18181818181818em;
                     padding-bottom: 0.18181818181818em;
-                    margin-top: 7px;
+                    margin-top: 6px;
+                    margin-bottom: 5px;
+                }
+                
+                button {
+                    float: left;
                     margin-bottom: 7px;
+                    margin-top: 8px;
                 }
             }
         }
@@ -156,6 +157,17 @@ table {
             tr:first-child td {
                 padding-top: 9px;
             }
+            
+            tr.selected,
+            tr.selected:hover {
+                background-color: #eaf5fb;
+                
+                td:first-child {
+                    background-image: url(img/icon-row-selected.svg);
+                    background-position: 0.2em center;
+                    background-repeat: no-repeat;
+                }
+            }
         }
     }    
     
diff --git a/forms/src/main/java/org/keycloak/forms/UrlBean.java b/forms/src/main/java/org/keycloak/forms/UrlBean.java
index fdb11fe..cb82aaa 100644
--- a/forms/src/main/java/org/keycloak/forms/UrlBean.java
+++ b/forms/src/main/java/org/keycloak/forms/UrlBean.java
@@ -120,6 +120,10 @@ public class UrlBean {
         return Urls.accountTotpPage(baseURI, realm.getId()).toString();
     }
 
+    public String getTotpRemoveUrl() {
+        return Urls.accountTotpRemove(baseURI, realm.getId()).toString();
+    }
+
     public String getEmailVerificationUrl() {
         return Urls.accountEmailVerification(baseURI, realm.getId()).toString();
     }
diff --git a/forms/src/main/java/org/keycloak/service/FormServiceImpl.java b/forms/src/main/java/org/keycloak/service/FormServiceImpl.java
index 1cd60fa..27c2df1 100644
--- a/forms/src/main/java/org/keycloak/service/FormServiceImpl.java
+++ b/forms/src/main/java/org/keycloak/service/FormServiceImpl.java
@@ -81,6 +81,10 @@ public class FormServiceImpl implements FormService {
 
         Map<String, Object> attributes = new HashMap<String, Object>();
 
+        if (dataBean.getError() != null){
+            attributes.put("message", new ErrorBean(dataBean.getError(), dataBean.getErrorType()));
+        }
+
         RealmBean realm = new RealmBean(dataBean.getRealm());
         attributes.put("template", new TemplateBean(realm, dataBean.getContextPath()));
 
@@ -145,10 +149,6 @@ public class FormServiceImpl implements FormService {
 
     private class CommandPassword implements Command {
         public void exec(Map<String, Object> attributes, FormServiceDataBean dataBean) {
-            if (dataBean.getError() != null){
-                attributes.put("message", new ErrorBean(dataBean.getError(), dataBean.getErrorType()));
-            }
-
             RealmBean realm = new RealmBean(dataBean.getRealm());
 
             attributes.put("realm", realm);
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/forms.css b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/forms.css
index 082dbdd..f3fadb5 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/forms.css
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/forms.css
@@ -75,19 +75,23 @@ a.button.btn-primary {
   border-style: solid;
 }
 input[type="button"].btn-primary:hover,
+input[type="submit"].btn-primary:hover,
 button.btn-primary:hover,
 a.button.btn-primary:hover,
 input[type="button"].btn-primary:focus,
+input[type="submit"].btn-primary:focus,
 button.btn-primary:focus,
 a.button.btn-primary:focus {
   background-color: #009BD3;
 }
 input[type="button"].btn-primary:active,
+input[type="submit"].btn-primary:active,
 button.btn-primary:active,
 a.button.btn-primary:active {
   background-color: #0099d4;
 }
 input[type="button"].disabled,
+input[type="submit"].disabled,
 button.disabled,
 a.button.disabled {
   border-color: #cfcdcd;
@@ -99,25 +103,30 @@ a.button.disabled {
   letter-spacing: 0.06363636363636em;
 }
 input[type="button"].disabled:hover,
+input[type="submit"].disabled:hover,
 button.disabled:hover,
 a.button.disabled:hover {
   cursor: default;
 }
 input[type="button"].disabled:active,
+input[type="submit"].disabled:active,
 button.disabled:active,
 a.button.disabled:active {
   box-shadow: none;
 }
 input[type="button"]:hover,
+input[type="submit"]:hover,
 button:hover,
 a.button:hover,
 input[type="button"]:focus,
+input[type="submit"]:focus,
 button:focus,
 a.button:focus {
   background-image: none;
   cursor: pointer;
 }
 input[type="button"]:active,
+input[type="submit"]:active,
 button:active,
 a.button:active {
   background-image: none;
@@ -616,7 +625,7 @@ input[type="email"].tiny {
   line-height: 1.45454545454545em;
 }
 .tokenfield.form-control .token .close {
-  text-indent: -9999999em;
+  text-indent: -99999em;
   width: 1.6em;
   height: 1.6em;
   line-height: 1.6em;
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/header.css b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/header.css
index c3b1bd7..04e3340 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/header.css
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/header.css
@@ -60,6 +60,7 @@ body {
 }
 .header.rcue .navbar {
   margin-bottom: 0;
+  z-index:auto;
 }
 .header.rcue .navbar.primary {
   font-size: 13px;
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/sprites.css b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/sprites.css
index fcfb0cc..1a35f74 100755
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/css/sprites.css
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/css/sprites.css
@@ -5,7 +5,7 @@
 	height: 16px;
 	background-image: url(img/sprites.png); /* Modified by Gabriel */
 	background-repeat: no-repeat;
-	text-indent: -9999999em;
+	text-indent: -99999em;
 	margin-right: 0.5em;
 	vertical-align: text-top;
 }
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl
index e456284..253ab75 100755
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/login-totp.ftl
@@ -25,7 +25,7 @@
             <!-- <p>Forgot <a href="#">Username</a> or <a href="#">Password</a>?</p> -->
         </div>
 
-        <input type="submit" value="Log In" />
+        <input class="btn-primary" type="submit" value="Log In" />
     </form>
 
     <#elseif section = "info">
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl
index d8cca1f..de023e1 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl
@@ -31,17 +31,16 @@
             <div class="form-area ${(realm.social)?string('social','')} clearfix">
                 <div class="section app-form">
                     <h3>Application login area</h3>
+                    <#if error?has_content>
+                        <div class="feedback error bottom-left show">
+                            <p>
+                                <strong id="loginError">${rb.getString(error.summary)}</strong><br/>${rb.getString('emailErrorInfo')}
+                            </p>
+                        </div>
+                    </#if>
                     <#nested "form">
                 </div>
 
-                <#if error?has_content>
-                    <div class="feedback error bottom-left show">
-                        <p>
-                            <strong id="loginError">${rb.getString(error.summary)}</strong>
-                        </p>
-                    </div>
-                </#if>
-
                 <#if social.displaySocialProviders>
                     <div class="section social-login"> <span>or</span>
                         <h3>Social login area</h3>
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-main.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-main.ftl
index 3cc7975..7cf9f71 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-main.ftl
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-main.ftl
@@ -3,7 +3,7 @@
 <html>
 <head>
     <meta charset="utf-8">
-    <title>Edit Account</title>
+    <title>Edit Account - <#nested "title"></title>
     <link rel="icon" href="img/favicon.ico">
 
     <!-- Frameworks -->
@@ -34,10 +34,14 @@
 </head>
 <body class="admin-console user ${bodyClass}">
 
-    <#if error?has_content>
-    <!--div class="feedback success show"><p><strong>Success!</strong> Your changes have been saved.</p></div-->
+    <#if message?has_content>
     <div class="feedback-aligner">
-        <div class="alert alert-danger">${rb.getString(error.summary)}</div>
+        <#if message.success>
+        <div class="feedback success show"><p><strong>${rb.getString('successHeader')}</strong> ${rb.getString(message.summary)}</p></div>
+        </#if>
+        <#if message.error>
+        <div class="feedback error show"><p><strong>${rb.getString('errorHeader')}</strong> ${rb.getString(message.summary)}</p></div>
+        </#if>
     </div>
     </#if>
 
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl
index 63de6ef..5f4d6dc 100755
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/totp.ftl
@@ -1,7 +1,9 @@
 <#import "template-main.ftl" as layout>
 <@layout.mainLayout active='totp' bodyClass='totp'; section>
 
-    <#if section = "header">
+    <#if section = "title">
+        Google Authenticator
+    <#elseif section = "header">
 
         <#if totp.enabled>
             <h2>Authenticators</h2>
@@ -12,7 +14,6 @@
     <#elseif section = "content">
 
         <#if totp.enabled>
-        <#-- TODO this is only mock page -->
         <form>
             <fieldset>
                 <p class="info">You have the following authenticators set up:</p>
@@ -21,11 +22,16 @@
                     <tbody>
                     <tr>
                         <td class="provider"><span class="social googleplus">Google</span></td>
-                        <td class="soft">Connected as john@google.com</td>
-                        <td class="action"><a href="user-totp-setup.html" class="button">Remove Google</a></td>
+                        <td class="action">
+                            <a href="${url.totpRemoveUrl}" class="button">Remove Google</a>
+                        </td>
                     </tr>
                     </tbody>
                 </table>
+                <p class="info">
+                    If the totp authentication is required by the realm and you remove your configured authenticator,
+                    you will have to reconfigure it immediately or on the next login.
+                </p>
             </fieldset>
         </form>
 
diff --git a/forms/src/main/resources/org/keycloak/forms/messages.properties b/forms/src/main/resources/org/keycloak/forms/messages.properties
index 92722f9..03943dc 100644
--- a/forms/src/main/resources/org/keycloak/forms/messages.properties
+++ b/forms/src/main/resources/org/keycloak/forms/messages.properties
@@ -37,6 +37,9 @@ invalidPasswordExisting=Invalid existing password
 invalidPasswordConfirm=Password confirmation doesn't match
 invalidTotp=Invalid authenticator code
 
+successTotp=Google authenticator configured.
+successTotpRemoved=Google authenticator removed.
+
 usernameExists=Username already exists
 
 error=A system error has occured, contact admin
@@ -50,4 +53,5 @@ emailForgotHeader=Forgot Your Password?
 emailUpdateHeader=Update password
 emailSent=You should receive an email shortly with further instructions.
 emailError=Invalid username or email.
+emailErrorInfo=Please, fill in the fields again.
 emailInstruction=Enter your username and email address and we will send you instructions on how to create a new password.
\ No newline at end of file
diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java
index b78d9ed..2874971 100755
--- a/services/src/main/java/org/keycloak/services/resources/AccountService.java
+++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java
@@ -164,6 +164,15 @@ public class AccountService {
         return accessCodeEntry;
     }
 
+    @Path("totp-remove")
+    @GET
+    public Response processTotpRemove() {
+        UserModel user = getUserFromAuthManager();
+        user.setTotp(false);
+        return Flows.forms(realm, request, uriInfo).setError("successTotpRemoved").setErrorType(FormFlows.ErrorType.SUCCESS)
+                .setUser(user).forwardToTotp();
+    }
+
     @Path("totp")
     @POST
     @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@@ -206,7 +215,8 @@ public class AccountService {
         if (accessCodeEntry != null) {
             return redirectOauth(user, accessCodeEntry);
         } else {
-            return Flows.forms(realm, request, uriInfo).setUser(user).forwardToTotp();
+            return Flows.forms(realm, request, uriInfo).setError("successTotp").setErrorType(FormFlows.ErrorType.SUCCESS)
+                    .setUser(user).forwardToTotp();
         }
     }
 
diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
index 1da6a61..b6a86a2 100755
--- a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
+++ b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java
@@ -55,6 +55,10 @@ public class Urls {
         return accountBase(baseUri).path(AccountService.class, "totpPage").build(realmId);
     }
 
+    public static URI accountTotpRemove(URI baseUri, String realmId) {
+        return accountBase(baseUri).path(AccountService.class, "processTotpRemove").build(realmId);
+    }
+
     public static URI accountEmailVerification(URI baseUri, String realmId) {
         return accountBase(baseUri).path(AccountService.class, "emailVerification").build(realmId);
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index d3322d4..89742bf 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -192,6 +192,11 @@ public class TokenService {
         String username = formData.getFirst("username");
         UserModel user = realm.getUser(username);
 
+        if (user == null){
+            return Flows.forms(realm, request, uriInfo).setError(Messages.INVALID_USER).setFormData(formData)
+                    .forwardToLogin();
+        }
+
         isTotpConfigurationRequired(user);
         isEmailVerificationRequired(user);
 
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index f0f3eea..3614016 100644
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -200,6 +200,13 @@
                     <target>1.6</target>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>exec-maven-plugin</artifactId>
+                <configuration>
+                    <workingDirectory>${project.basedir}</workingDirectory>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index b7f2318..17e755e 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -112,17 +112,27 @@ public class KeycloakServer {
 
         if (System.getProperties().containsKey("resources")) {
             String resources = System.getProperty("resources");
-            if (resources == null || resources.equals("")) {
-                for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
-                    if (c.contains("keycloak" + File.separator + "testsuite" + File.separator + "integration")) {
-                        config.setResourcesHome(c.replaceFirst("testsuite.integration.*", ""));
+            if (resources == null || resources.equals("") || resources.equals("true")) {
+                if (System.getProperties().containsKey("maven.home")) {
+                    resources = System.getProperty("user.dir").replaceFirst("testsuite.integration.*", "");
+                } else {
+                    for (String c : System.getProperty("java.class.path").split(File.pathSeparator)) {
+                        if (c.contains(File.separator + "testsuite" + File.separator + "integration")) {
+                            resources = c.replaceFirst("testsuite.integration.*", "");
+                        }
                     }
                 }
-            } else {
-                config.setResourcesHome(resources);
             }
+
+            File dir = new File(resources).getAbsoluteFile();
+            if (!dir.isDirectory() || !new File(dir, "admin-ui").isDirectory()) {
+                throw new RuntimeException("Invalid resources directory");
+            }
+
+            config.setResourcesHome(dir.getAbsolutePath());
         }
 
+
         final KeycloakServer keycloak = new KeycloakServer(config);
         keycloak.sysout = true;
         keycloak.start();
@@ -291,9 +301,9 @@ public class KeycloakServer {
                 if (path.startsWith("/forms")) {
                     file = file(resourcesHome, "forms", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
                 } else if (path.startsWith("/admin")) {
-                    file =  file(resourcesHome, "admin-ui", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
+                    file = file(resourcesHome, "admin-ui", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
                     if (!file.isFile()) {
-                        file =  file(resourcesHome, "admin-ui-styles", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
+                        file = file(resourcesHome, "admin-ui-styles", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
                     }
                 } else {
                     throw new IOException("Unknown resource " + path);
@@ -305,10 +315,9 @@ public class KeycloakServer {
 
     private static File file(String... path) {
         StringBuilder s = new StringBuilder();
-        s.append(path[0]);
-        for (int i = 1; i < path.length; i++) {
+        for (String p : path) {
             s.append(File.separator);
-            s.append(path[i]);
+            s.append(p);
         }
         return new File(s.toString());
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java
index 916513d..bb70d97 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/actions/RequiredActionTotpSetupTest.java
@@ -30,6 +30,8 @@ import org.keycloak.services.managers.RealmManager;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.models.UserModel.RequiredAction;
+import org.keycloak.testsuite.OAuthClient;
+import org.keycloak.testsuite.pages.AccountTotpPage;
 import org.keycloak.testsuite.pages.AppPage;
 import org.keycloak.testsuite.pages.AppPage.RequestType;
 import org.keycloak.testsuite.pages.LoginConfigTotpPage;
@@ -54,9 +56,6 @@ public class RequiredActionTotpSetupTest {
         public void config(RealmManager manager, RealmModel defaultRealm, RealmModel appRealm) {
             appRealm.addRequiredCredential(CredentialRepresentation.TOTP);
             appRealm.setResetPasswordAllowed(true);
-
-            UserModel user = appRealm.getUser("test-user@localhost");
-            user.addRequiredAction(RequiredAction.CONFIGURE_TOTP);
         }
 
     });
@@ -77,6 +76,12 @@ public class RequiredActionTotpSetupTest {
     protected LoginConfigTotpPage totpPage;
 
     @WebResource
+    protected AccountTotpPage accountTotpPage;
+
+    @WebResource
+    protected OAuthClient oauth;
+
+    @WebResource
     protected RegisterPage registerPage;
 
     protected TimeBasedOTP totp = new TimeBasedOTP();
@@ -101,9 +106,69 @@ public class RequiredActionTotpSetupTest {
 
         totpPage.assertCurrent();
 
-        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
+        String totpSecret = totpPage.getTotpSecret();
+
+        totpPage.configure(totp.generate(totpSecret));
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        oauth.openLogout();
+
+        loginPage.open();
+        loginPage.loginTotp("test-user@localhost", "password", totp.generate(totpSecret));
 
         Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
     }
 
+    @Test
+    public void setupTotpRegisteredAfterTotpRemoval() {
+        // Register new user
+        loginPage.open();
+        loginPage.clickRegister();
+        registerPage.register("firstName2", "lastName2", "email2", "setupTotp2", "password2", "password2");
+
+        // Configure totp
+        totpPage.assertCurrent();
+
+        String totpCode = totpPage.getTotpSecret();
+        totpPage.configure(totp.generate(totpCode));
+
+        // After totp config, user should be on the app page
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+        // Logout
+        oauth.openLogout();
+
+        // Try to login after logout
+        loginPage.open();
+        loginPage.login("setupTotp2", "password2");
+
+        // Totp is already configured, thus one-time password is needed, login page should be loaded
+        Assert.assertTrue(loginPage.isCurrent());
+        Assert.assertFalse(totpPage.isCurrent());
+
+        // Login with one-time password
+        loginPage.loginTotp("setupTotp2", "password2", totp.generate(totpCode));
+
+        // Open account page
+        accountTotpPage.open();
+        accountTotpPage.assertCurrent();
+
+        // Remove google authentificator
+        accountTotpPage.removeTotp();
+
+        // Logout
+        oauth.openLogout();
+
+        // Try to login
+        loginPage.open();
+        loginPage.login("setupTotp2", "password2");
+
+        // Since the authentificator was removed, it has to be set up again
+        totpPage.assertCurrent();
+        totpPage.configure(totp.generate(totpPage.getTotpSecret()));
+
+        Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType());
+
+    }
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountTotpPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountTotpPage.java
index 32cfb80..11cc502 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountTotpPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/AccountTotpPage.java
@@ -41,6 +41,9 @@ public class AccountTotpPage extends Page {
     @FindBy(css = "button[type=\"submit\"]")
     private WebElement submitButton;
 
+    @FindBy(linkText = "Remove Google")
+    private WebElement removeLink;
+
     public void configure(String totp) {
         totpInput.sendKeys(totp);
         submitButton.click();
@@ -51,11 +54,15 @@ public class AccountTotpPage extends Page {
     }
 
     public boolean isCurrent() {
-        return driver.getPageSource().contains("Google Authenticator Setup");
+        return driver.getTitle().contains("Edit Account - Google Authenticator");
     }
 
     public void open() {
         driver.navigate().to(PATH);
     }
 
+    public void removeTotp() {
+        removeLink.click();
+    }
+
 }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
index 1d9c949..d099690 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/LoginPage.java
@@ -41,6 +41,9 @@ public class LoginPage extends Page {
     @FindBy(id = "password")
     private WebElement passwordInput;
 
+    @FindBy(id = "totp")
+    private WebElement totp;
+
     @FindBy(css = "input[type=\"submit\"]")
     private WebElement submitButton;
 
@@ -63,6 +66,19 @@ public class LoginPage extends Page {
         submitButton.click();
     }
 
+    public void loginTotp(String username, String password, String code) {
+        usernameInput.clear();
+        usernameInput.sendKeys(username);
+
+        passwordInput.clear();
+        passwordInput.sendKeys(password);
+
+        totp.clear();
+        totp.sendKeys(code);
+
+        submitButton.click();
+    }
+
     public String getError() {
         return loginErrorMessage != null ? loginErrorMessage.getText() : null;
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/Page.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/Page.java
index cb56000..d38e2ac 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/Page.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/pages/Page.java
@@ -35,7 +35,7 @@ public abstract class Page {
 
     public void assertCurrent() {
         String name = getClass().getSimpleName();
-        Assert.assertTrue("Exptected " + name + " but was " + driver.getTitle() + " (" + driver.getCurrentUrl() + ")",
+        Assert.assertTrue("Expected " + name + " but was " + driver.getTitle() + " (" + driver.getCurrentUrl() + ")",
                 isCurrent());
     }