keycloak-aplcache

Changes

Details

diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
index c261b48..f0e6ddd 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
@@ -253,7 +253,18 @@ module.config([ '$routeProvider', function($routeProvider) {
             },
             controller : 'ApplicationScopeMappingCtrl'
         })
-
+        .when('/realms/:realm/applications/:application/installation', {
+            templateUrl : 'partials/application-installation.html',
+            resolve : {
+                realm : function(RealmLoader) {
+                    return RealmLoader();
+                },
+                installation : function(ApplicationInstallationLoader) {
+                    return ApplicationInstallationLoader();
+                }
+            },
+            controller : 'ApplicationInstallationCtrl'
+        })
         .when('/create/application/:realm', {
             templateUrl : 'partials/application-detail.html',
             resolve : {
@@ -502,8 +513,8 @@ module.directive('onoffswitch', function() {
             offText: '@offText'
         },
         compile: function(element, attrs) {
-            if (!attrs.onText) { attrs.onText = "YES"; }
-            if (!attrs.offText) { attrs.offText = "NO"; }
+            if (!attrs.onText) { attrs.onText = "ON"; }
+            if (!attrs.offText) { attrs.offText = "OFF"; }
 
             var html = "<div class=\"onoffswitch\">" +
                 "<input type=\"checkbox\" data-ng-model=\"ngModel\" class=\"onoffswitch-checkbox\" name=\"" + attrs.name + "\" id=\"" + attrs.id + "\">" +
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
index c04d81f..ed435ee 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/applications.js
@@ -179,6 +179,12 @@ module.controller('ApplicationListCtrl', function($scope, realm, applications, A
     });
 });
 
+module.controller('ApplicationInstallationCtrl', function($scope, realm, installation, ApplicationInstallation, $routeParams) {
+    $scope.realm = realm;
+    $scope.installation = installation;
+    $scope.download = ApplicationInstallation.url({ realm: $routeParams.realm, application: $routeParams.application });
+});
+
 module.controller('ApplicationDetailCtrl', function($scope, realm, application, Application, $location, Dialog, Notifications) {
     console.log('ApplicationDetailCtrl');
 
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
index cf1b57e..7b72c48 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
@@ -87,6 +87,15 @@ module.factory('ApplicationRoleLoader', function(Loader, ApplicationRole, $route
     });
 });
 
+module.factory('ApplicationInstallationLoader', function(Loader, ApplicationInstallation, $route, $q) {
+    return Loader.get(ApplicationInstallation, function() {
+        return {
+            realm : $route.current.params.realm,
+            application : $route.current.params.application
+        }
+    });
+});
+
 module.factory('ApplicationRoleListLoader', function(Loader, ApplicationRole, $route, $q) {
     return Loader.query(ApplicationRole, function() {
         return {
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
index b692c30..88d4ec3 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
@@ -15,9 +15,16 @@ module.service('Auth', function() {
 
 module.service('Dialog', function($dialog) {
 	var dialog = {};
+
+	var escapeHtml = function(str) {
+		var div = document.createElement('div');
+		div.appendChild(document.createTextNode(str));
+		return div.innerHTML;
+	};
+
 	dialog.confirmDelete = function(name, type, success) {
-		var title = 'Delete ' + type.charAt(0).toUpperCase() + type.slice(1);
-		var msg = '<span class="primary">Are you sure you want to permanently delete the ' + type + ' "' + name + '"?</span>' +
+		var title = 'Delete ' + escapeHtml(type.charAt(0).toUpperCase() + type.slice(1));
+		var msg = '<span class="primary">Are you sure you want to permanently delete the ' + escapeHtml(type) + ' "' + escapeHtml(name) + '"?</span>' +
             '<span>This action can\'t be undone.</span>';
 		var btns = [ {
 			result : 'cancel',
@@ -202,6 +209,22 @@ module.factory('Application', function($resource) {
     });
 });
 
+module.factory('ApplicationInstallation', function($resource) {
+    var url = '/auth-server/rest/saas/admin/realms/:realm/applications/:application/installation';
+    var resource = $resource('/auth-server/rest/saas/admin/realms/:realm/applications/:application/installation', {
+        realm : '@realm',
+        application : '@application'
+    },  {
+        update : {
+            method : 'PUT'
+        }
+    });
+    resource.url = function(parameters) {
+        return url.replace(':realm', parameters.realm).replace(':application', parameters.application);
+    }
+    return resource;
+});
+
 module.factory('ApplicationCredentials', function($resource) {
     return $resource('/auth-server/rest/saas/admin/realms/:realm/applications/:application/credentials', {
         realm : '@realm',
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html
index 0f46176..fd7bb6d 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-credentials.html
@@ -6,7 +6,7 @@
                 <ul class="rcue-tabs">
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}">Settings</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
-                    <li><a href="#">Installation</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/installation">Installation</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
                     <li><a href="#">Sessions</a></li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html
index 78def73..2a21202 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-detail.html
@@ -6,7 +6,7 @@
                 <ul class="rcue-tabs">
                     <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}">Settings</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
-                    <li><a href="#">Installation</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/installation">Installation</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
                     <li><a href="#">Sessions</a></li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html
new file mode 100755
index 0000000..a63d552
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-installation.html
@@ -0,0 +1,27 @@
+<div id="wrapper" class="container">
+    <div class="row">
+        <div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
+        <div id="content-area" class="col-md-9" role="main">
+            <div class="top-nav" data-ng-show="!create">
+                <ul class="rcue-tabs">
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}">Settings</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
+                    <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}/installation">Installation</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
+                    <li><a href="#">Sessions</a></li>
+                </ul>
+            </div>
+            <div class="top-nav" data-ng-show="create">
+                <ul class="rcue-tabs">
+                    <li></li>
+                </ul>
+            </div>
+            <div id="content">
+                <a class="button primary" href="{{download}}" download="keycloak.json" type="submit">Download</a></br>
+                <textarea style="width: 100%;" rows="20" onclick="this.select()">{{installation | json}}</textarea>
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
+    </div>
+</div>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html
index 063ab84..5101392 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-detail.html
@@ -6,7 +6,7 @@
                 <ul class="rcue-tabs">
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}">Settings</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
-                    <li><a href="#">Installation</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/installation">Installation</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
                     <li><a href="#">Sessions</a></li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html
index 904cb67..1093a3f 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/application-role-list.html
@@ -6,7 +6,7 @@
                 <ul class="rcue-tabs">
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}">Settings</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/credentials">Credentials</a></li>
-                    <li><a href="#">Installation</a></li>
+                    <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/installation">Installation</a></li>
                     <li class="active"><a href="#/realms/{{realm.id}}/applications/{{application.id}}/roles">Roles</a></li>
                     <li><a href="#/realms/{{realm.id}}/applications/{{application.id}}/scope-mappings">Scope</a></li>
                     <li><a href="#">Sessions</a></li>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/notfound.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/notfound.html
index 12b2139..64c6566 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/notfound.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/notfound.html
@@ -1,5 +1,14 @@
 <div id="wrapper" class="container">
     <div class="row">
-        Page not found
+        <div class="bs-sidebar col-md-3 clearfix"></div>
+        <div id="content-area" class="col-md-9" role="main">
+            <div class="error-container">
+                <h2>Page <strong>not found</strong>...</h2>
+                <p class="instruction">We could not find the page you are looking for. Please make sure the URL you entered is correct.</p>
+                <a href="#" class="link-right">Go to the home page &raquo;</a>
+                <!-- <a href="#" class="link-right">Go to the realm page &raquo;</a> -->
+            </div>
+        </div>
+        <div id="container-right-bg"></div>
     </div>
 </div>
\ No newline at end of file
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 8f42e66..6d30cdf 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
@@ -94,6 +94,24 @@ body {
   margin-left: -2.27272727272727em;
   padding-top: 2.90909090909091em;
 }
+.error-container {
+  width: 54em;
+  margin-top: 6em;
+  margin-left: 8em;
+}
+.error-container h2 {
+  text-transform: uppercase;
+  font-size: 2.3em;
+  font-family: Overpass, sans-serif;
+  margin-bottom: 1.52173913043478em;
+}
+.error-container p.instruction {
+  font-size: 1.3em;
+}
+.error-container .link-right {
+  float: right;
+  font-size: 1.3em;
+}
 /* Header */
 .header.rcue {
   z-index: 50;
@@ -648,6 +666,7 @@ table.list tbody tr.expanded .form-actions {
   .header.rcue .navbar.utility .navbar-inner,
   .header.rcue .navbar.primary .navbar-inner {
     max-width: 970px;
+    min-width: 560px;
   }
   #container-right-bg {
     margin-left: 242.5px;
@@ -661,13 +680,17 @@ table.list tbody tr.expanded .form-actions {
   }
   .bs-sidebar,
   .user .bs-sidebar {
-    padding-top: 1em;
     width: 100%;
+    padding-top: 0;
   }
   .bs-sidebar ul li,
   .user .bs-sidebar ul li {
     margin-left: 0;
   }
+  .bs-sidebar ul li:first-child,
+  .user .bs-sidebar ul li:first-child {
+    margin-top: 1em;
+  }
   .bs-sidebar ul li a,
   .user .bs-sidebar ul li a {
     border-width: 1px;
@@ -704,8 +727,16 @@ table.list tbody tr.expanded .form-actions {
   #content-area {
     border: none;
   }
+  .bs-sidebar + #content-area {
+    margin-top: 0;
+  }
   #container-right-bg {
     border: none;
     width: 100%;
   }
+  .error-container {
+    width: inherit;
+    margin-right: 6em;
+    margin-left: 6em;
+  }
 }
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 527e707..1f49e26 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
@@ -117,6 +117,28 @@ body {
     }
 }
 
+.error-container {
+    width: 54em;
+    margin-top: 6em;
+    margin-left: 8em;
+    
+    h2 {
+        text-transform: uppercase;
+        font-size: 2.3em;
+        font-family: Overpass, sans-serif;
+        margin-bottom: 1.52173913043478em;
+    }
+    
+    p.instruction {
+        font-size: 1.3em;
+    }
+    
+    .link-right {
+        float: right;
+        font-size: 1.3em;
+    }
+}
+
 
 /* Header */
 
@@ -808,6 +830,7 @@ table.list {
         .navbar.utility .navbar-inner,
         .navbar.primary .navbar-inner {
             max-width: 970px;
+            min-width: 560px;
         }
     }
     
@@ -829,13 +852,17 @@ table.list {
     
     .bs-sidebar,
     .user .bs-sidebar {
-        padding-top: 1em;
         width: 100%;
+        padding-top: 0;
         
         ul li {
         
             margin-left: 0;
             
+            &:first-child {
+                margin-top: 1em;
+            }
+            
             a {
                 border-width: 1px;
                 padding-left: 1.53846153846154em;
@@ -889,8 +916,18 @@ table.list {
         border: none;
     }
     
+    .bs-sidebar + #content-area {
+        margin-top: 0;
+    }
+    
     #container-right-bg {
         border: none;
         width: 100%;
     }
+    
+    .error-container {
+        width: inherit;
+        margin-right: 6em;
+        margin-left: 6em;
+    }
 }
diff --git a/core/src/main/java/org/keycloak/representations/idm/ApplicationInstallationRepresentation.java b/core/src/main/java/org/keycloak/representations/idm/ApplicationInstallationRepresentation.java
new file mode 100755
index 0000000..fbad6df
--- /dev/null
+++ b/core/src/main/java/org/keycloak/representations/idm/ApplicationInstallationRepresentation.java
@@ -0,0 +1,80 @@
+package org.keycloak.representations.idm;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class ApplicationInstallationRepresentation {
+    protected String realm;
+    protected String resource;
+    @JsonProperty("realm-public-key")
+    protected String realmPublicKey;
+    @JsonProperty("auth-url")
+    protected String authUrl;
+    @JsonProperty("code-url")
+    protected String codeUrl;
+    @JsonProperty("ssl-not-required")
+    protected boolean sslNotRequired;
+    protected Map<String, String> credentials;
+
+    public String getRealm() {
+        return realm;
+    }
+
+    public void setRealm(String realm) {
+        this.realm = realm;
+    }
+
+    public String getResource() {
+        return resource;
+    }
+
+    public void setResource(String resource) {
+        this.resource = resource;
+    }
+
+    public String getRealmPublicKey() {
+        return realmPublicKey;
+    }
+
+    public void setRealmPublicKey(String realmPublicKey) {
+        this.realmPublicKey = realmPublicKey;
+    }
+
+    public String getAuthUrl() {
+        return authUrl;
+    }
+
+    public void setAuthUrl(String authUrl) {
+        this.authUrl = authUrl;
+    }
+
+    public String getCodeUrl() {
+        return codeUrl;
+    }
+
+    public void setCodeUrl(String codeUrl) {
+        this.codeUrl = codeUrl;
+    }
+
+    public boolean isSslNotRequired() {
+        return sslNotRequired;
+    }
+
+    public void setSslNotRequired(boolean sslNotRequired) {
+        this.sslNotRequired = sslNotRequired;
+    }
+
+    public Map<String, String> getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(Map<String, String> credentials) {
+        this.credentials = credentials;
+    }
+}
diff --git a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
index 4e4619f..8081979 100755
--- a/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/ApplicationManager.java
@@ -8,15 +8,20 @@ import org.keycloak.models.RoleModel;
 import org.keycloak.models.UserCredentialModel;
 import org.keycloak.models.UserModel;
 import org.keycloak.representations.idm.ApplicationRepresentation;
+import org.keycloak.representations.idm.ApplicationInstallationRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.representations.idm.RoleRepresentation;
 import org.keycloak.representations.idm.ScopeMappingRepresentation;
 import org.keycloak.representations.idm.UserRoleMappingRepresentation;
+import org.keycloak.services.resources.flows.Urls;
 
+import java.net.URI;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
 
 /**
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -167,4 +172,25 @@ public class ApplicationManager {
         return rep;
 
     }
+
+    public ApplicationInstallationRepresentation toInstallationRepresentation(RealmModel realmModel, ApplicationModel applicationModel, URI baseUri) {
+        ApplicationInstallationRepresentation rep = new ApplicationInstallationRepresentation();
+        rep.setRealm(realmModel.getId());
+        rep.setRealmPublicKey(realmModel.getPublicKeyPem());
+        rep.setSslNotRequired(realmModel.isSslNotRequired());
+
+        rep.setAuthUrl(Urls.realmLoginPage(baseUri, realmModel.getId()).toString());
+        rep.setCodeUrl(Urls.realmCode(baseUri, realmModel.getId()).toString());
+
+        rep.setResource(applicationModel.getId());
+
+        Map<String, String> creds = new HashMap<String, String>();
+        creds.put(CredentialRepresentation.PASSWORD, "INSERT APPLICATION PASSWORD");
+        if (applicationModel.getApplicationUser().isTotp()) {
+            creds.put(CredentialRepresentation.TOTP, "INSERT APPLICATION TOTP");
+        }
+        rep.setCredentials(creds);
+
+        return rep;
+    }
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
index aa0671f..0c05fc9 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java
@@ -1,11 +1,13 @@
 package org.keycloak.services.resources.admin;
 
+import org.codehaus.jackson.map.ObjectMapper;
 import org.jboss.resteasy.annotations.cache.NoCache;
 import org.jboss.resteasy.logging.Logger;
 import org.keycloak.models.ApplicationModel;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserCredentialModel;
+import org.keycloak.representations.idm.ApplicationInstallationRepresentation;
 import org.keycloak.representations.idm.ApplicationRepresentation;
 import org.keycloak.representations.idm.CredentialRepresentation;
 import org.keycloak.services.managers.ApplicationManager;
@@ -17,7 +19,10 @@ import javax.ws.rs.GET;
 import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
 import java.util.List;
 import java.util.Set;
 
@@ -30,6 +35,8 @@ public class ApplicationResource extends RoleContainerResource {
     protected RealmModel realm;
     protected ApplicationModel application;
     protected KeycloakSession session;
+    @Context
+    protected UriInfo uriInfo;
 
     public ApplicationResource(RealmModel realm, ApplicationModel applicationModel, KeycloakSession session) {
         super(applicationModel);
@@ -54,6 +61,20 @@ public class ApplicationResource extends RoleContainerResource {
         return applicationManager.toRepresentation(application);
     }
 
+
+    @GET
+    @NoCache
+    @Path("installation")
+    @Produces(MediaType.APPLICATION_JSON)
+    public String getInstallation() throws IOException {
+        ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
+        ApplicationInstallationRepresentation rep = applicationManager.toInstallationRepresentation(realm, application, uriInfo.getBaseUri());
+
+        // TODO Temporary solution to pretty-print
+        ObjectMapper mapper = new ObjectMapper();
+        return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
+    }
+
     @DELETE
     @NoCache
     public void deleteApplication() {
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 a2061aa..169da3f 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
@@ -120,6 +120,10 @@ public class Urls {
         return tokenBase(baseUri).path(TokenService.class, "registerPage").build(realmId);
     }
 
+    public static URI realmCode(URI baseUri, String realmId) {
+        return tokenBase(baseUri).path(TokenService.class, "accessCodeToToken").build(realmId);
+    }
+
     private static UriBuilder saasBase(URI baseUri) {
         return UriBuilder.fromUri(baseUri).path(SaasService.class);
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
index c7945bd..93682c4 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -7,12 +7,10 @@ import org.keycloak.models.ModelProvider;
 import org.keycloak.services.managers.SocialRequestManager;
 import org.keycloak.services.managers.TokenManager;
 
-import javax.annotation.PreDestroy;
 import javax.servlet.ServletContext;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.Context;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.ServiceLoader;
 import java.util.Set;