keycloak-memoizeit

merge

4/25/2014 11:03:56 AM

Changes

admin-ui/pom.xml 32(+0 -32)

admin-ui/src/main/resources/META-INF/resources/admin/css/reset.css 71(+0 -71)

admin-ui/src/main/resources/META-INF/resources/admin/lib/patternfly/css/patternfly.min.css 4(+0 -4)

admin-ui/src/main/resources/META-INF/web-fragment.xml 5(+0 -5)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/css/patternfly.css 9168(+0 -9168)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.svg 34(+0 -34)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/img/bg-login.jpg 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/img/brand.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/img/brand.svg 84(+0 -84)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/img/brand-lg.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/img/logo.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/img/logo.svg 22(+0 -22)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/js/patternfly.js 68(+0 -68)

forms/common-themes/src/main/resources/theme/account/patternfly/resources/lib/patternfly/js/patternfly.min.js 1(+0 -1)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/css/patternfly.css 9168(+0 -9168)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/css/patternfly.min.css 4(+0 -4)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-BoldItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Bold-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBoldItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-ExtraBold-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Italic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-LightItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Light-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Regular-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-SemiboldItalic-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.svg 146(+0 -146)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/OpenSans-Semibold-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.svg 34(+0 -34)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.ttf 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/fonts/PatternFlyIcons-webfont.woff 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/img/bg-login.jpg 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/img/brand.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/img/brand.svg 84(+0 -84)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/img/brand-lg.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/img/logo.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/img/logo.svg 22(+0 -22)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/js/patternfly.js 68(+0 -68)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/patternfly/js/patternfly.min.js 1(+0 -1)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/zocial/zocial-regular-webfont.eot 0(+0 -0)

forms/common-themes/src/main/resources/theme/login/patternfly/resources/lib/zocial/zocial-regular-webfont.woff 0(+0 -0)

integration/js/src/main/resources/META-INF/resources/js/keycloak.js 626(+0 -626)

pom.xml 1(+0 -1)

server/pom.xml 5(+0 -5)

server/src/main/webapp/jboss_community.png 0(+0 -0)

server/src/main/webapp/keycloak_logo.png 0(+0 -0)

services/src/main/java/org/keycloak/services/tmp/TmpAdminRedirectServlet.java 21(+0 -21)

Details

diff --git a/bundled-war-example/pom.xml b/bundled-war-example/pom.xml
index 751e7ab..5812399 100755
--- a/bundled-war-example/pom.xml
+++ b/bundled-war-example/pom.xml
@@ -253,6 +253,13 @@
             <scope>provided</scope>
         </dependency>
 
+        <!-- CDI -->
+        <dependency>
+            <groupId>javax.enterprise</groupId>
+            <artifactId>cdi-api</artifactId>
+            <version>1.1</version>
+            <scope>provided</scope>
+        </dependency>
 
     </dependencies>
 
diff --git a/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerDataProvider.java b/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerDataProvider.java
new file mode 100644
index 0000000..a9b938d
--- /dev/null
+++ b/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerDataProvider.java
@@ -0,0 +1,35 @@
+/**
+ * JBoss, Home of Professional Open Source
+ * Copyright Red Hat, Inc., and individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.example.oauth;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CustomerDataProvider {
+
+    public List<String> getCustomers() {
+        ArrayList<String> rtn = new ArrayList<String>();
+        rtn.add("Bill Burke");
+        rtn.add("Stian Thorgersen");
+        rtn.add("Stan Silvert");
+        rtn.add("Gabriel Cardoso");
+        rtn.add("Viliam Rockai");
+        rtn.add("Marek Posolda");
+        rtn.add("Boleslaw Dawidowicz");
+        return rtn;
+    }
+}
diff --git a/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerService.java b/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerService.java
index 8f5f5b1..4f1866a 100755
--- a/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerService.java
+++ b/bundled-war-example/src/main/java/org/keycloak/example/oauth/CustomerService.java
@@ -2,10 +2,10 @@ package org.keycloak.example.oauth;
 
 import org.jboss.resteasy.annotations.cache.NoCache;
 
+import javax.inject.Inject;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -14,18 +14,14 @@ import java.util.List;
  */
 @Path("customers")
 public class CustomerService {
+
+    @Inject
+    private CustomerDataProvider provider;
+
     @GET
     @Produces("application/json")
     @NoCache
     public List<String> getCustomers() {
-        ArrayList<String> rtn = new ArrayList<String>();
-        rtn.add("Bill Burke");
-        rtn.add("Stian Thorgersen");
-        rtn.add("Stan Silvert");
-        rtn.add("Gabriel Cardoso");
-        rtn.add("Viliam Rockai");
-        rtn.add("Marek Posolda");
-        rtn.add("Boleslaw Dawidowicz");
-        return rtn;
+          return provider.getCustomers();
     }
 }
diff --git a/bundled-war-example/src/main/resources/META-INF/beans.xml b/bundled-war-example/src/main/resources/META-INF/beans.xml
new file mode 100644
index 0000000..57025b5
--- /dev/null
+++ b/bundled-war-example/src/main/resources/META-INF/beans.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    JBoss, Home of Professional Open Source
+    Copyright Red Hat, Inc., and individual contributors.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    	http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://jboss.org/schema/cdi/beans_1_0.xsd">
+
+</beans>
\ No newline at end of file
diff --git a/distribution/appliance-dist/assembly.xml b/distribution/appliance-dist/assembly.xml
index 1b81f38..957cc36 100755
--- a/distribution/appliance-dist/assembly.xml
+++ b/distribution/appliance-dist/assembly.xml
@@ -47,7 +47,7 @@
             <outputDirectory>keycloak</outputDirectory>
         </fileSet>
         <fileSet>
-            <directory>${project.build.directory}/unpacked/deployments/auth-server.war</directory>
+            <directory>src/main/welcome-content</directory>
             <outputDirectory>keycloak/welcome-content</outputDirectory>
             <includes>
                 <include>*.*</include>
diff --git a/distribution/appliance-dist/pom.xml b/distribution/appliance-dist/pom.xml
index c1a7bb4..e981729 100755
--- a/distribution/appliance-dist/pom.xml
+++ b/distribution/appliance-dist/pom.xml
@@ -84,6 +84,7 @@
                                     <outputDirectory>${project.build.directory}/unpacked/adapter</outputDirectory>
                                 </artifactItem>
                             </artifactItems>
+                            <excludes>**/welcome-content/*</excludes>
                         </configuration>
                     </execution>
                 </executions>
diff --git a/distribution/appliance-dist/src/main/welcome-content/index.html b/distribution/appliance-dist/src/main/welcome-content/index.html
new file mode 100644
index 0000000..ad7660e
--- /dev/null
+++ b/distribution/appliance-dist/src/main/welcome-content/index.html
@@ -0,0 +1,32 @@
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags. See the copyright.txt file in the
+  ~ distribution for a full listing of individual contributors.
+  ~
+  ~ This is free software; you can redistribute it and/or modify it
+  ~ under the terms of the GNU Lesser General Public License as
+  ~ published by the Free Software Foundation; either version 2.1 of
+  ~ the License, or (at your option) any later version.
+  ~
+  ~ This software is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public
+  ~ License along with this software; if not, write to the Free
+  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+    <title>Welcome to Keycloak</title>
+    <meta http-equiv="refresh" content="0; url=/auth/" />
+</head>
+
+<body>
+</body>
+</html>
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/Theme.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/Theme.java
index c5c7e36..dd02e62 100644
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/Theme.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/Theme.java
@@ -10,12 +10,14 @@ import java.util.Properties;
  */
 public interface Theme {
 
-    public enum Type { LOGIN, ACCOUNT };
+    public enum Type { LOGIN, ACCOUNT, ADMIN, COMMON };
 
     public String getName();
 
     public String getParentName();
 
+    public String getImportName();
+
     public Type getType();
 
     public URL getTemplate(String name) throws IOException;
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java
index 74132b4..c64bff6 100755
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ThemeLoader.java
@@ -1,6 +1,5 @@
 package org.keycloak.freemarker;
 
-import org.jboss.logging.Logger;
 import org.keycloak.models.Config;
 import org.keycloak.util.ProviderLoader;
 
@@ -19,8 +18,6 @@ import java.util.Properties;
  */
 public class ThemeLoader {
 
-    private static final Logger logger = Logger.getLogger(ThemeLoader.class);
-
     public static Theme createTheme(String name, Theme.Type type) throws FreeMarkerException {
         if (name == null) {
             name = Config.getThemeDefault();
@@ -43,9 +40,19 @@ public class ThemeLoader {
             List<Theme> themes = new LinkedList<Theme>();
             themes.add(theme);
 
+            if (theme.getImportName() != null) {
+                String[] s = theme.getImportName().split("/");
+                themes.add(findTheme(providers, s[1], Theme.Type.valueOf(s[0].toUpperCase())));
+            }
+
             for (String parentName = theme.getParentName(); parentName != null; parentName = theme.getParentName()) {
                 theme = findTheme(providers, parentName, type);
                 themes.add(theme);
+
+                if (theme.getImportName() != null) {
+                    String[] s = theme.getImportName().split("/");
+                    themes.add(findTheme(providers, s[1], Theme.Type.valueOf(s[0].toUpperCase())));
+                }
             }
 
             return new ExtendingTheme(themes);
@@ -54,28 +61,17 @@ public class ThemeLoader {
         }
     }
 
-    private static Theme findTheme(Iterable<ThemeProvider> providers, String name, Theme.Type type) throws FreeMarkerException {
+    private static Theme findTheme(Iterable<ThemeProvider> providers, String name, Theme.Type type) {
         for (ThemeProvider p : providers) {
             if (p.hasTheme(name, type)) {
                 try {
                     return p.createTheme(name, type);
                 } catch (IOException e) {
-                    if (name.equals(Config.getThemeBase())) {
-                        throw new FreeMarkerException("Failed to create " + type.toString().toLowerCase() + " theme", e);
-                    } else {
-                        logger.error("Failed to create " + type.toString().toLowerCase() + " theme", e);
-                        return findTheme(providers, Config.getThemeBase(), type);
-                    }
+                    throw new RuntimeException("Failed to create " + type.toString().toLowerCase() + " theme", e);
                 }
             }
         }
-
-        if (name.equals(Config.getThemeBase())) {
-            throw new FreeMarkerException(type.toString().toLowerCase() + " theme '" + name + "' not found");
-        } else {
-            logger.error(type.toString().toLowerCase() + " theme '" + name + "' not found");
-            return findTheme(providers, Config.getThemeBase(), type);
-        }
+        throw new RuntimeException(type.toString().toLowerCase() + " theme '" + name + "' not found");
     }
 
     public static class ExtendingTheme implements Theme {
@@ -97,6 +93,11 @@ public class ThemeLoader {
         }
 
         @Override
+        public String getImportName() {
+            return themes.get(0).getImportName();
+        }
+
+        @Override
         public Type getType() {
             return themes.get(0).getType();
         }
diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/ClassLoaderTheme.java b/forms/common-themes/src/main/java/org/keycloak/theme/ClassLoaderTheme.java
index 7c6e02c..5a41cf7 100644
--- a/forms/common-themes/src/main/java/org/keycloak/theme/ClassLoaderTheme.java
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/ClassLoaderTheme.java
@@ -16,6 +16,8 @@ public class ClassLoaderTheme implements Theme {
 
     private final String parentName;
 
+    private final String importName;
+
     private final Type type;
 
     private final ClassLoader classLoader;
@@ -44,8 +46,10 @@ public class ClassLoaderTheme implements Theme {
         if (p != null) {
             properties.load(p.openStream());
             this.parentName = properties.getProperty("parent");
+            this.importName = properties.getProperty("import");
         } else {
             this.parentName = null;
+            this.importName = null;
         }
     }
 
@@ -60,6 +64,11 @@ public class ClassLoaderTheme implements Theme {
     }
 
     @Override
+    public String getImportName() {
+        return importName;
+    }
+
+    @Override
     public Type getType() {
         return type;
     }
diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java b/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java
index 3737aa1..aa2312e 100644
--- a/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/FolderTheme.java
@@ -15,6 +15,7 @@ import java.util.Properties;
 public class FolderTheme implements Theme {
 
     private String parentName;
+    private String importName;
     private File themeDir;
     private Type type;
     private final Properties properties;
@@ -28,6 +29,7 @@ public class FolderTheme implements Theme {
         if (propertiesFile .isFile()) {
             properties.load(new FileInputStream(propertiesFile));
             parentName = properties.getProperty("parent");
+            importName = properties.getProperty("import");
         }
     }
 
@@ -42,6 +44,11 @@ public class FolderTheme implements Theme {
     }
 
     @Override
+    public String getImportName() {
+        return importName;
+    }
+
+    @Override
     public Type getType() {
         return type;
     }
diff --git a/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProvider b/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProvider
index 8a9390d..f9f661b 100644
--- a/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProvider
+++ b/forms/common-themes/src/main/resources/META-INF/services/org.keycloak.freemarker.ThemeProvider
@@ -1,2 +1,2 @@
-org.keycloak.theme.DefaultLoginThemeProvider
+org.keycloak.theme.DefaultKeycloakThemeProvider
 org.keycloak.theme.FolderThemeProvider
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/account/keycloak/theme.properties b/forms/common-themes/src/main/resources/theme/account/keycloak/theme.properties
index b5952d5..611dff9 100644
--- a/forms/common-themes/src/main/resources/theme/account/keycloak/theme.properties
+++ b/forms/common-themes/src/main/resources/theme/account/keycloak/theme.properties
@@ -1,2 +1,4 @@
 parent=patternfly
+import=common/keycloak
+
 styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/account.css css/account.css
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/account/patternfly/theme.properties b/forms/common-themes/src/main/resources/theme/account/patternfly/theme.properties
index c142b5c..971b6c0 100644
--- a/forms/common-themes/src/main/resources/theme/account/patternfly/theme.properties
+++ b/forms/common-themes/src/main/resources/theme/account/patternfly/theme.properties
@@ -1,2 +1,4 @@
 parent=base
+import=common/keycloak
+
 styles=lib/patternfly/css/patternfly.css css/account.css
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/base/theme.properties b/forms/common-themes/src/main/resources/theme/admin/base/theme.properties
new file mode 100644
index 0000000..5eb8ef9
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/base/theme.properties
@@ -0,0 +1 @@
+import=common/keycloak
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/keycloak/resources/css/styles.css b/forms/common-themes/src/main/resources/theme/admin/keycloak/resources/css/styles.css
new file mode 100644
index 0000000..d5ca9aa
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/keycloak/resources/css/styles.css
@@ -0,0 +1,34 @@
+@import url("../lib/patternfly/css/patternfly.css");
+@import url("../lib/select2-3.4.1/select2.css");
+
+@import url("admin-console.css");
+@import url("tables.css");
+@import url("sprites.css");
+
+.navbar-pf {
+    background-image: url('../img/header-bkgrnd.png');
+    border-top: 3px solid rgba(255, 255, 255, 0.15);
+}
+
+.navbar-pf .navbar-primary {
+    font-size: 13px;
+    background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,.4) 100%);
+    background-image: linear-gradient(to bottom, rgba(0,0,0,.1) 0%, rgba(0,0,0,.4) 100%);
+}
+
+.navbar-pf .navbar-header {
+    border-bottom: 1px solid rgba(255,255,255,.15);
+}
+
+.navbar-pf .navbar-primary li.dropdown.context > a,
+.navbar-pf .navbar-primary li.dropdown.context > a:hover,
+.navbar-pf .navbar-primary li.dropdown.context.open > a,
+.navbar-pf .navbar-primary > .active > a,
+.navbar-pf .navbar-primary > .active > a:hover{
+    background-color: rgba(0,0,0,0.1);
+    background-image: -webkit-linear-gradient(top, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.1) 100%);
+    background-image: linear-gradient(to bottom, rgba(0,0,0,0.1) 0%, rgba(0,0,0,0.1) 100%);
+    border-bottom: none;
+    border-right-color: rgba(255,255,255,0.15);
+    border-top-color: rgba(255,255,255,0.05);
+}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/keycloak/theme.properties b/forms/common-themes/src/main/resources/theme/admin/keycloak/theme.properties
new file mode 100644
index 0000000..13a3608
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/keycloak/theme.properties
@@ -0,0 +1,2 @@
+parent=patternfly
+import=common/keycloak
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/admin/patternfly/resources/css/styles.css b/forms/common-themes/src/main/resources/theme/admin/patternfly/resources/css/styles.css
new file mode 100644
index 0000000..726012a
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/patternfly/resources/css/styles.css
@@ -0,0 +1,6 @@
+@import url("../lib/patternfly/css/patternfly.css");
+@import url("../lib/select2-3.4.1/select2.css");
+
+@import url("admin-console.css");
+@import url("tables.css");
+@import url("sprites.css");
diff --git a/forms/common-themes/src/main/resources/theme/admin/patternfly/theme.properties b/forms/common-themes/src/main/resources/theme/admin/patternfly/theme.properties
new file mode 100644
index 0000000..e67231f
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/admin/patternfly/theme.properties
@@ -0,0 +1,2 @@
+parent=base
+import=common/keycloak
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/common/keycloak/resources/lib/zocial/zocial-regular-webfont.eot b/forms/common-themes/src/main/resources/theme/common/keycloak/resources/lib/zocial/zocial-regular-webfont.eot
new file mode 100755
index 0000000..ff8829a
Binary files /dev/null and b/forms/common-themes/src/main/resources/theme/common/keycloak/resources/lib/zocial/zocial-regular-webfont.eot differ
diff --git a/forms/common-themes/src/main/resources/theme/common/keycloak/resources/lib/zocial/zocial-regular-webfont.woff b/forms/common-themes/src/main/resources/theme/common/keycloak/resources/lib/zocial/zocial-regular-webfont.woff
new file mode 100755
index 0000000..79b85a4
Binary files /dev/null and b/forms/common-themes/src/main/resources/theme/common/keycloak/resources/lib/zocial/zocial-regular-webfont.woff differ
diff --git a/forms/common-themes/src/main/resources/theme/login/keycloak/theme.properties b/forms/common-themes/src/main/resources/theme/login/keycloak/theme.properties
index 54da766..599759a 100644
--- a/forms/common-themes/src/main/resources/theme/login/keycloak/theme.properties
+++ b/forms/common-themes/src/main/resources/theme/login/keycloak/theme.properties
@@ -1,2 +1,4 @@
 parent=patternfly
+import=common/keycloak
+
 styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/login.css ../patternfly/lib/zocial/zocial.css css/login.css
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/login/patternfly/theme.properties b/forms/common-themes/src/main/resources/theme/login/patternfly/theme.properties
index 720d4ea..c6ae402 100644
--- a/forms/common-themes/src/main/resources/theme/login/patternfly/theme.properties
+++ b/forms/common-themes/src/main/resources/theme/login/patternfly/theme.properties
@@ -1,4 +1,6 @@
 parent=base
+import=common/keycloak
+
 styles=lib/patternfly/css/patternfly.css lib/zocial/zocial.css css/login.css
 meta=viewport==width=device-width,initial-scale=1
 
diff --git a/integration/js/src/main/resources/keycloak.js b/integration/js/src/main/resources/keycloak.js
new file mode 100755
index 0000000..ff333a8
--- /dev/null
+++ b/integration/js/src/main/resources/keycloak.js
@@ -0,0 +1,626 @@
+var Keycloak = function (config) {
+    if (!(this instanceof Keycloak)) {
+        return new Keycloak(config);
+    }
+
+    var kc = this;
+    var adapter;
+
+    kc.init = function (init) {
+        kc.authenticated = false;
+
+        if (window.Cordova) {
+            adapter = loadAdapter('cordova');
+        } else {
+            adapter = loadAdapter();
+        }
+
+        var promise = createPromise();
+
+        var initPromise = createPromise();
+        initPromise.promise.success(function() {
+            kc.onReady && kc.onReady(kc.authenticated);
+            promise.setSuccess(kc.authenticated);
+        }).error(function() {
+            promise.setError();
+        });
+
+        var configPromise = loadConfig(config);
+
+        function processInit() {
+            var callback = parseCallback(window.location.href);
+            if (callback) {
+                window.history.replaceState({}, null, location.protocol + '//' + location.host + location.pathname + (callback.fragment ? '#' + callback.fragment : ''));
+                processCallback(callback, initPromise);
+                return;
+            } else if (init) {
+                if (init.code || init.error) {
+                    processCallback(init, initPromise);
+                    return;
+                } else if (init.token || init.refreshToken) {
+                    setToken(init.token, init.refreshToken);
+                    initPromise.setSuccess();
+                } else if (init == 'login-required') {
+                    var p = kc.login();
+                    if (p) {
+                        p.success(function() {
+                            initPromise.setSuccess();
+                        }).error(function() {
+                            initPromise.setError();
+                        });
+                    };
+                } else if (init == 'check-sso') {
+                    var p = kc.login({ prompt: 'none' });
+                    if (p) {
+                        p.success(function() {
+                            initPromise.setSuccess();
+                        }).error(function() {
+                            initPromise.setSuccess();
+                        });
+                    };
+                } else {
+                    throw 'invalid init: ' + init;
+                }
+            } else {
+                initPromise.setSuccess();
+            }
+        }
+
+        configPromise.success(processInit);
+        configPromise.error(function() {
+            promise.setError();
+        });
+
+        return promise.promise;
+    }
+
+    kc.login = function (options) {
+        return adapter.login(options);
+    }
+
+    kc.createLoginUrl = function(options) {
+        var state = createUUID();
+
+        var redirectUri = adapter.redirectUri(options);
+        if (options && options.prompt) {
+            if (redirectUri.indexOf('?') == -1) {
+                redirectUri += '?prompt=' + options.prompt;
+            } else {
+                redirectUri += '&prompt=' + options.prompt;
+            }
+        }
+
+        sessionStorage.oauthState = state;
+
+        var url = getRealmUrl()
+            + '/tokens/login'
+            + '?client_id=' + encodeURIComponent(kc.clientId)
+            + '&redirect_uri=' + encodeURIComponent(redirectUri)
+            + '&state=' + encodeURIComponent(state)
+            + '&response_type=code';
+
+        if (options && options.prompt) {
+            url += '&prompt=' + options.prompt;
+        }
+
+        return url;
+    }
+
+    kc.logout = function(options) {
+        return adapter.logout(options);
+    }
+
+    kc.createLogoutUrl = function(options) {
+        var url = getRealmUrl()
+            + '/tokens/logout'
+            + '?redirect_uri=' + encodeURIComponent(adapter.redirectUri(options));
+
+        return url;
+    }
+
+    kc.createAccountUrl = function(options) {
+        var url = getRealmUrl()
+            + '/account'
+            + '?referrer=' + kc.clientId
+            + '&referrer_uri=' + encodeURIComponent(adapter.redirectUri(options));
+
+        return url;
+    }
+
+    kc.accountManagement = function() {
+        return adapter.accountManagement();
+    }
+
+    kc.hasRealmRole = function (role) {
+        var access = kc.realmAccess;
+        return access && access.roles.indexOf(role) >= 0 || false;
+    }
+
+    kc.hasResourceRole = function(role, resource) {
+        if (!kc.resourceAccess) {
+            return false;
+        }
+
+        var access = kc.resourceAccess[resource || kc.clientId];
+        return access && access.roles.indexOf(role) >= 0 || false;
+    }
+
+    kc.loadUserProfile = function() {
+        var url = getRealmUrl() + '/account';
+        var req = new XMLHttpRequest();
+        req.open('GET', url, true);
+        req.setRequestHeader('Accept', 'application/json');
+        req.setRequestHeader('Authorization', 'bearer ' + kc.token);
+
+        var promise = createPromise();
+
+        req.onreadystatechange = function () {
+            if (req.readyState == 4) {
+                if (req.status == 200) {
+                    kc.profile = JSON.parse(req.responseText);
+                    promise.setSuccess(kc.profile);
+                } else {
+                    promise.setError();
+                }
+            }
+        }
+
+        req.send();
+
+        return promise.promise;
+    }
+
+    kc.isTokenExpired = function(minValidity) {
+        if (!kc.tokenParsed || !kc.refreshToken) {
+            throw 'Not authenticated';
+        }
+
+        var expiresIn = kc.tokenParsed['exp'] - (new Date().getTime() / 1000);
+        if (minValidity) {
+            expiresIn -= minValidity;
+        }
+
+        return expiresIn < 0;
+    }
+
+    kc.updateToken = function(minValidity) {
+        if (!kc.tokenParsed || !kc.refreshToken) {
+            throw 'Not authenticated';
+        }
+
+        var promise = createPromise();
+
+        if (minValidity) {
+            if (!kc.isTokenExpired(minValidity)) {
+                promise.setSuccess(false);
+                return promise.promise;
+            }
+        }
+
+        var params = 'grant_type=refresh_token&' + 'refresh_token=' + kc.refreshToken;
+        var url = getRealmUrl() + '/tokens/refresh';
+
+        var req = new XMLHttpRequest();
+        req.open('POST', url, true);
+        req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+
+        if (kc.clientId && kc.clientSecret) {
+            req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
+        } else {
+            params += '&client_id=' + encodeURIComponent(kc.clientId);
+        }
+
+        req.onreadystatechange = function() {
+            if (req.readyState == 4) {
+                if (req.status == 200) {
+                    var tokenResponse = JSON.parse(req.responseText);
+                    setToken(tokenResponse['access_token'], tokenResponse['refresh_token']);
+                    kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
+                    promise.setSuccess(true);
+                } else {
+                    kc.onAuthRefreshError && kc.onAuthRefreshError();
+                    promise.setError();
+                }
+            }
+        };
+
+        req.send(params);
+
+        return promise.promise;
+    }
+
+    function getRealmUrl() {
+        return kc.authServerUrl + '/rest/realms/' + encodeURIComponent(kc.realm);
+    }
+
+    function processCallback(oauth, promise) {
+        var code = oauth.code;
+        var error = oauth.error;
+        var prompt = oauth.prompt;
+
+        if (code) {
+            var params = 'code=' + code;
+            var url = getRealmUrl() + '/tokens/access/codes';
+
+            var req = new XMLHttpRequest();
+            req.open('POST', url, true);
+            req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+
+            if (kc.clientId && kc.clientSecret) {
+                req.setRequestHeader('Authorization', 'Basic ' + btoa(kc.clientId + ':' + kc.clientSecret));
+            } else {
+                params += '&client_id=' + encodeURIComponent(kc.clientId);
+            }
+
+            req.withCredentials = true;
+
+            req.onreadystatechange = function() {
+                if (req.readyState == 4) {
+                    if (req.status == 200) {
+                        var tokenResponse = JSON.parse(req.responseText);
+                        setToken(tokenResponse['access_token'], tokenResponse['refresh_token']);
+                        kc.onAuthSuccess && kc.onAuthSuccess();
+                        promise && promise.setSuccess();
+                    } else {
+                        kc.onAuthError && kc.onAuthError();
+                        promise && promise.setError();
+                    }
+                }
+            };
+
+            req.send(params);
+        } else if (error) {
+            if (prompt != 'none') {
+                kc.onAuthError && kc.onAuthError();
+                promise && promise.setError();
+            } else {
+                promise && promise.setSuccess();
+            }
+        }
+    }
+
+    function loadConfig(url) {
+        var promise = createPromise();
+        var configUrl;
+
+        if (!config) {
+            configUrl = 'keycloak.json';
+        } else if (typeof config === 'string') {
+            configUrl = config;
+        }
+
+        if (configUrl) {
+            var req = new XMLHttpRequest();
+            req.open('GET', configUrl, true);
+            req.setRequestHeader('Accept', 'application/json');
+
+            req.onreadystatechange = function () {
+                if (req.readyState == 4) {
+                    if (req.status == 200) {
+                        var config = JSON.parse(req.responseText);
+
+                        kc.authServerUrl = config['auth-server-url'];
+                        kc.realm = config['realm'];
+                        kc.clientId = config['resource'];
+
+                        promise.setSuccess();
+                    } else {
+                        promise.setError();
+                    }
+                }
+            };
+
+            req.send();
+        } else {
+            if (!config['url']) {
+                var scripts = document.getElementsByTagName('script');
+                for (var i = 0; i < scripts.length; i++) {
+                    if (scripts[i].src.match(/.*keycloak\.js/)) {
+                        config.url = scripts[i].src.substr(0, scripts[i].src.indexOf('/js/keycloak.js'));
+                        break;
+                    }
+                }
+            }
+
+            if (!config.realm) {
+                throw 'realm missing';
+            }
+
+            if (!config.clientId) {
+                throw 'clientId missing';
+            }
+
+            kc.authServerUrl = config.url;
+            kc.realm = config.realm;
+            kc.clientId = config.clientId;
+
+            promise.setSuccess();
+        }
+
+        return promise.promise;
+    }
+
+    function clearToken() {
+        setToken(null, null);
+        kc.onAuthLogout && kc.onAuthLogout();
+    }
+
+    function setToken(token, refreshToken) {
+        if (token) {
+            kc.token = token;
+            kc.tokenParsed = JSON.parse(decodeURIComponent(escape(window.atob( token.split('.')[1] ))));
+            kc.authenticated = true;
+            kc.subject = kc.tokenParsed.sub;
+            kc.realmAccess = kc.tokenParsed.realm_access;
+            kc.resourceAccess = kc.tokenParsed.resource_access;
+
+            for (var i = 0; i < idTokenProperties.length; i++) {
+                var n = idTokenProperties[i];
+                if (kc.tokenParsed[n]) {
+                    if (!kc.idToken) {
+                        kc.idToken = {};
+                    }
+                    kc.idToken[n] = kc.tokenParsed[n];
+                }
+            }
+        } else {
+            delete kc.token;
+            delete kc.tokenParsed;
+            delete kc.subject;
+            delete kc.realmAccess;
+            delete kc.resourceAccess;
+            delete kc.idToken;
+
+            kc.authenticated = false;
+        }
+
+        if (refreshToken) {
+            kc.refreshToken = refreshToken;
+            kc.refreshTokenParsed = JSON.parse(atob(refreshToken.split('.')[1]));
+        } else {
+            delete kc.refreshToken;
+            delete kc.refreshTokenParsed;
+        }
+    }
+
+    function createUUID() {
+        var s = [];
+        var hexDigits = '0123456789abcdef';
+        for (var i = 0; i < 36; i++) {
+            s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
+        }
+        s[14] = '4';
+        s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
+        s[8] = s[13] = s[18] = s[23] = '-';
+        var uuid = s.join('');
+        return uuid;
+    }
+
+    function parseCallback(url) {
+        if (url.indexOf('?') != -1) {
+            var oauth = {};
+
+            var params = url.split('?')[1].split('&');
+            for (var i = 0; i < params.length; i++) {
+                var p = params[i].split('=');
+                switch (decodeURIComponent(p[0])) {
+                    case 'code':
+                        oauth.code = p[1];
+                        break;
+                    case 'error':
+                        oauth.error = p[1];
+                        break;
+                    case 'state':
+                        oauth.state = decodeURIComponent(p[1]);
+                        break;
+                    case 'redirect_fragment':
+                        oauth.fragment = decodeURIComponent(p[1]);
+                        break;
+                    case 'prompt':
+                        oauth.prompt = p[1];
+                        break;
+                }
+            }
+
+            if ((oauth.code || oauth.error) && oauth.state && oauth.state == sessionStorage.oauthState) {
+                delete sessionStorage.oauthState;
+                return oauth;
+            }
+        }
+    }
+
+    function createPromise() {
+        var p = {
+            setSuccess: function(result) {
+                p.success = true;
+                p.result = result;
+                if (p.successCallback) {
+                    p.successCallback(result);
+                }
+            },
+
+            setError: function(result) {
+                p.error = true;
+                p.result = result;
+                if (p.errorCallback) {
+                    p.errorCallback(result);
+                }
+            },
+
+            promise: {
+                success: function(callback) {
+                    if (p.success) {
+                        callback(p.result);
+                    } else if (!p.error) {
+                        p.successCallback = callback;
+                    }
+                    return p.promise;
+                },
+                error: function(callback) {
+                    if (p.error) {
+                        callback(p.result);
+                    } else if (!p.success) {
+                        p.errorCallback = callback;
+                    }
+                    return p.promise;
+                }
+            }
+        }
+        return p;
+    }
+
+    function loadAdapter(type) {
+        if (!type || type == 'default') {
+            return {
+                login: function(options) {
+                    window.location.href = kc.createLoginUrl(options);
+                },
+
+                logout: function(options) {
+                    window.location.href = kc.createLogoutUrl(options);
+                },
+
+                accountManagement : function() {
+                    window.location.href = kc.createAccountUrl();
+                },
+
+                redirectUri: function(options) {
+                    if (options && options.redirectUri) {
+                        return options.redirectUri;
+                    } else if (kc.redirectUri) {
+                        return kc.redirectUri;
+                    } else {
+                        var url = (location.protocol + '//' + location.hostname + (location.port && (':' + location.port)) + location.pathname);
+                        if (location.hash) {
+                            url += '?redirect_fragment=' + encodeURIComponent(location.hash.substring(1));
+                        }
+                        return url;
+                    }
+                }
+            };
+        }
+
+        if (type == 'cordova') {
+            console.debug('Enabling Cordova support');
+
+            return {
+                login: function(options) {
+                    var promise = createPromise();
+
+                    var o = 'location=no';
+                    if (options && options.prompt == 'none') {
+                        o += ',hidden=yes';
+                    }
+
+                    var loginUrl = kc.createLoginUrl(options);
+                    var ref = window.open(loginUrl, '_blank', o);
+
+                    var callback;
+                    var error;
+
+                    ref.addEventListener('loadstart', function(event) {
+                        if (event.url.indexOf('http://localhost') == 0) {
+                            callback = parseCallback(event.url);
+                            ref.close();
+                        }
+                    });
+
+                    ref.addEventListener('loaderror', function(event) {
+                        if (event.url.indexOf('http://localhost') != 0) {
+                            error = true;
+                            ref.close();
+                        }
+                    });
+
+                    ref.addEventListener('exit', function(event) {
+                        if (error || !callback) {
+                            promise.setError();
+                        } else {
+                            processCallback(callback, promise);
+                        }
+                    });
+
+                    return promise.promise;
+                },
+
+                logout: function(options) {
+                    var promise = createPromise();
+
+                    var logoutUrl = kc.createLogoutUrl(options);
+                    var ref = window.open(logoutUrl, '_blank', 'location=no,hidden=yes');
+
+                    var error;
+
+                    ref.addEventListener('loadstart', function(event) {
+                        if (event.url.indexOf('http://localhost') == 0) {
+                            ref.close();
+                        }
+                    });
+
+                    ref.addEventListener('loaderror', function(event) {
+                        if (event.url.indexOf('http://localhost') != 0) {
+                            error = true;
+                            ref.close();
+                        }
+                    });
+
+                    ref.addEventListener('exit', function(event) {
+                        if (error) {
+                            promise.setError();
+                        } else {
+                            clearToken();
+                            promise.setSuccess();
+                        }
+                    });
+
+                    return promise.promise;
+                },
+
+                accountManagement : function() {
+                    var accountUrl = kc.createAccountUrl();
+                    var ref = window.open(accountUrl, '_blank', 'location=no');
+                    ref.addEventListener('loadstart', function(event) {
+                        if (event.url.indexOf('http://localhost') == 0) {
+                            ref.close();
+                        }
+                    });
+                },
+
+                redirectUri: function(options) {
+                    return 'http://localhost';
+                }
+            }
+        }
+
+        throw 'invalid adapter type: ' + type;
+    }
+
+    var idTokenProperties = [
+        "name", 
+        "given_name", 
+        "family_name", 
+        "middle_name", 
+        "nickname", 
+        "preferred_username", 
+        "profile", 
+        "picture", 
+        "website", 
+        "email", 
+        "email_verified", 
+        "gender", 
+        "birthdate", 
+        "zoneinfo", 
+        "locale", 
+        "phone_number", 
+        "phone_number_verified", 
+        "address", 
+        "updated_at", 
+        "formatted", 
+        "street_address", 
+        "locality", 
+        "region", 
+        "postal_code", 
+        "country", 
+        "claims_locales"
+    ]
+}
diff --git a/model/api/src/main/java/org/keycloak/models/Config.java b/model/api/src/main/java/org/keycloak/models/Config.java
index 25f5332..d1ed6af 100644
--- a/model/api/src/main/java/org/keycloak/models/Config.java
+++ b/model/api/src/main/java/org/keycloak/models/Config.java
@@ -25,6 +25,9 @@ public class Config {
     public static final String THEME_DEFAULT_KEY = "keycloak.theme.default";
     public static final String THEME_DEFAULT_DEFAULT = "keycloak";
     public static final String THEME_DIR_KEY = "keycloak.theme.dir";
+    public static final String THEME_ADMIN_KEY = "keycloak.theme.admin";
+    public static final String THEME_ADMIN_DEFAULT  = "keycloak";
+
     public static final String JBOSS_SERVER_CONFIG_DIR_KEY = "jboss.server.config.dir";
 
     public static final String TIMER_PROVIDER_KEY = "keycloak.timer";
@@ -106,4 +109,12 @@ public class Config {
         System.setProperty(THEME_DEFAULT_KEY, defaultTheme);
     }
 
+    public static String getThemeAdmin() {
+        return System.getProperty(THEME_ADMIN_KEY, THEME_ADMIN_DEFAULT);
+    }
+
+    public static void setThemeAdmin(String adminTheme) {
+        System.setProperty(THEME_ADMIN_KEY, adminTheme);
+    }
+
 }

pom.xml 1(+0 -1)

diff --git a/pom.xml b/pom.xml
index 31ae93b..e62a6d4 100755
--- a/pom.xml
+++ b/pom.xml
@@ -97,7 +97,6 @@
         <module>services</module>
         <module>social</module>
         <module>forms</module>
-        <module>admin-ui</module>
         <module>examples</module>
         <module>testsuite</module>
         <module>server</module>

server/pom.xml 5(+0 -5)

diff --git a/server/pom.xml b/server/pom.xml
index a4313c2..fc93352 100755
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -133,11 +133,6 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-ui</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-js-adapter</artifactId>
             <version>${project.version}</version>
         </dependency>
diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml
index 626ec53..356425f 100755
--- a/server/src/main/webapp/WEB-INF/web.xml
+++ b/server/src/main/webapp/WEB-INF/web.xml
@@ -15,25 +15,16 @@
         </init-param>
         <init-param>
             <param-name>resteasy.servlet.mapping.prefix</param-name>
-            <param-value>/rest</param-value>
+            <param-value>/</param-value>
         </init-param>
         <load-on-startup>1</load-on-startup>
         <async-supported>true</async-supported>
     </servlet>
 
-    <servlet>
-        <servlet-name>TmpAdminRedirectServlet</servlet-name>
-        <servlet-class>org.keycloak.services.tmp.TmpAdminRedirectServlet</servlet-class>
-    </servlet>
-
     <listener>
         <listener-class>org.keycloak.services.listeners.KeycloakSessionDestroyListener</listener-class>
     </listener>
 
-    <welcome-file-list>
-        <welcome-file>index.html</welcome-file>
-    </welcome-file-list>
-
     <filter>
         <filter-name>Keycloak Client Connection Filter</filter-name>
         <filter-class>org.keycloak.services.filters.ClientConnectionFilter</filter-class>
@@ -56,13 +47,7 @@
 
     <servlet-mapping>
         <servlet-name>Resteasy</servlet-name>
-        <url-pattern>/rest/*</url-pattern>
-    </servlet-mapping>
-
-    <servlet-mapping>
-        <servlet-name>TmpAdminRedirectServlet</servlet-name>
-        <url-pattern>/admin</url-pattern>
-        <url-pattern>/admin/</url-pattern>
+        <url-pattern>/*</url-pattern>
     </servlet-mapping>
 
     <!--
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
index 54c4da0..7be45c5 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminService.java
@@ -47,7 +47,7 @@ import java.util.Set;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-@Path("/admin")
+@Path("/rest/admin")
 public class AdminService {
     protected static final Logger logger = Logger.getLogger(AdminService.class);
 
@@ -74,7 +74,7 @@ public class AdminService {
     @Context
     protected ProviderSession providerSession;
 
-    protected String adminPath = "/admin/index.html";
+    protected String adminPath = "/admin/";
     protected AppAuthManager authManager;
     protected TokenManager tokenManager;
 
@@ -373,7 +373,7 @@ public class AdminService {
             logger.debug("loginRedirect SUCCESS");
             NewCookie cookie = authManager.createCookie(adminRealm, adminConsole, code, AdminService.saasCookiePath(uriInfo).build());
 
-            URI redirectUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path("../").path(adminPath).build();
+            URI redirectUri = UriBuilder.fromUri(uriInfo.getBaseUri()).path(adminPath).build();
             if (path != null) {
                 redirectUri = redirectUri.resolve("#" + UriBuilder.fromPath(path).build().toString());
             }
diff --git a/services/src/main/java/org/keycloak/services/resources/AdminResource.java b/services/src/main/java/org/keycloak/services/resources/AdminResource.java
new file mode 100755
index 0000000..668ffa5
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/AdminResource.java
@@ -0,0 +1,60 @@
+package org.keycloak.services.resources;
+
+import org.jboss.resteasy.logging.Logger;
+import org.keycloak.models.Config;
+import org.keycloak.freemarker.Theme;
+import org.keycloak.freemarker.ThemeLoader;
+
+import javax.activation.FileTypeMap;
+import javax.activation.MimetypesFileTypeMap;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@Path("/admin")
+public class AdminResource {
+
+    private static final Logger logger = Logger.getLogger(AdminResource.class);
+
+    private static FileTypeMap mimeTypes = MimetypesFileTypeMap.getDefaultFileTypeMap();
+
+    @Context
+    private UriInfo uriInfo;
+
+    @GET
+    public Response getResource() throws URISyntaxException {
+        String requestUri = uriInfo.getRequestUri().toString();
+        if (!requestUri.endsWith("/")) {
+            return Response.seeOther(new URI(requestUri + "/")).build();
+        } else {
+            return getResource("index.html");
+        }
+    }
+
+    @GET
+    @Path("/{path:.*}")
+    public Response getResource(@PathParam("path") String path) {
+        try {
+            Theme theme = ThemeLoader.createTheme(Config.getThemeAdmin(), Theme.Type.ADMIN);
+            InputStream resource = theme.getResourceAsStream(path);
+            if (resource != null) {
+                return Response.ok(resource).type(mimeTypes.getContentType(path)).build();
+            } else {
+                return Response.status(Response.Status.NOT_FOUND).build();
+            }
+        } catch (Exception e) {
+            logger.warn("Failed to get theme resource", e);
+            return Response.serverError().build();
+        }
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/JsResource.java b/services/src/main/java/org/keycloak/services/resources/JsResource.java
new file mode 100644
index 0000000..c28d8bd
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/JsResource.java
@@ -0,0 +1,27 @@
+package org.keycloak.services.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@Path("/js")
+public class JsResource {
+
+    @GET
+    @Path("/keycloak.js")
+    @Produces("text/javascript")
+    public Response getJs() {
+        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("keycloak.js");
+        if (inputStream != null) {
+            return Response.ok(inputStream).build();
+        } else {
+            return Response.status(Response.Status.NOT_FOUND).build();
+        }
+    }
+
+}
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 7f49ff5..7c8371b 100755
--- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
+++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java
@@ -78,7 +78,10 @@ public class KeycloakApplication extends Application {
         singletons.add(new SocialResource(tokenManager, socialRequestManager));
         classes.add(SkeletonKeyContextResolver.class);
         classes.add(QRCodeResource.class);
+        classes.add(AdminResource.class);
         classes.add(ThemeResource.class);
+        classes.add(JsResource.class);
+        classes.add(WelcomeResource.class);
 
         setupDefaultRealm(context.getContextPath());
 
diff --git a/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java b/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
index 4638f17..b219613 100755
--- a/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/QRCodeResource.java
@@ -1,56 +1,56 @@
-package org.keycloak.services.resources;
-
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.WriterException;
-import com.google.zxing.client.j2se.MatrixToImageWriter;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.qrcode.QRCodeWriter;
-
-import javax.servlet.ServletException;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.StreamingOutput;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
- */
-@Path("/qrcode")
-public class QRCodeResource {
-
-    @GET
-    @Produces("image/png")
-    public Response createQrCode(@QueryParam("contents") String contents, @QueryParam("size") String size) throws ServletException, IOException, WriterException {
-        int width = 256;
-        int height = 256;
-
-        if (size != null) {
-            String[] s = size.split("x");
-            width = Integer.parseInt(s[0]);
-            height = Integer.parseInt(s[1]);
-        }
-
-        if (contents == null) {
-            return Response.status(Response.Status.BAD_REQUEST).build();
-        }
-
-        QRCodeWriter writer = new QRCodeWriter();
-        final BitMatrix bitMatrix = writer.encode(contents, BarcodeFormat.QR_CODE, width, height);
-
-        StreamingOutput stream = new StreamingOutput() {
-            @Override
-            public void write(OutputStream os) throws IOException,
-                    WebApplicationException {
-                MatrixToImageWriter.writeToStream(bitMatrix, "png", os);
-            }
-        };
-
-        return Response.ok(stream).build();
-    }
-
-}
+package org.keycloak.services.resources;
+
+import com.google.zxing.BarcodeFormat;
+import com.google.zxing.WriterException;
+import com.google.zxing.client.j2se.MatrixToImageWriter;
+import com.google.zxing.common.BitMatrix;
+import com.google.zxing.qrcode.QRCodeWriter;
+
+import javax.servlet.ServletException;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@Path("/rest/qrcode")
+public class QRCodeResource {
+
+    @GET
+    @Produces("image/png")
+    public Response createQrCode(@QueryParam("contents") String contents, @QueryParam("size") String size) throws ServletException, IOException, WriterException {
+        int width = 256;
+        int height = 256;
+
+        if (size != null) {
+            String[] s = size.split("x");
+            width = Integer.parseInt(s[0]);
+            height = Integer.parseInt(s[1]);
+        }
+
+        if (contents == null) {
+            return Response.status(Response.Status.BAD_REQUEST).build();
+        }
+
+        QRCodeWriter writer = new QRCodeWriter();
+        final BitMatrix bitMatrix = writer.encode(contents, BarcodeFormat.QR_CODE, width, height);
+
+        StreamingOutput stream = new StreamingOutput() {
+            @Override
+            public void write(OutputStream os) throws IOException,
+                    WebApplicationException {
+                MatrixToImageWriter.writeToStream(bitMatrix, "png", os);
+            }
+        };
+
+        return Response.ok(stream).build();
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 0b8126c..daa8762 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -28,7 +28,7 @@ import javax.ws.rs.core.UriInfo;
  * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  * @version $Revision: 1 $
  */
-@Path("/realms")
+@Path("/rest/realms")
 public class RealmsResource {
     protected static Logger logger = Logger.getLogger(RealmsResource.class);
 
diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
index b59a28c..683a399 100755
--- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java
@@ -76,7 +76,7 @@ import java.util.Map.Entry;
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-@Path("/social")
+@Path("/rest/social")
 public class SocialResource {
 
     protected static Logger logger = Logger.getLogger(SocialResource.class);
diff --git a/services/src/main/java/org/keycloak/services/resources/ThemeResource.java b/services/src/main/java/org/keycloak/services/resources/ThemeResource.java
index 4d06466..8a2df04 100755
--- a/services/src/main/java/org/keycloak/services/resources/ThemeResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/ThemeResource.java
@@ -16,7 +16,7 @@ import java.io.InputStream;
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-@Path("/theme")
+@Path("/rest/theme")
 public class ThemeResource {
 
     private static final Logger logger = Logger.getLogger(ThemeResource.class);
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 ed223ce..aa2bade 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -241,7 +241,7 @@ public class TokenService {
 
         audit.success();
 
-        return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
+        return Cors.add(request, Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).auth().allowedOrigins(client).allowedMethods("POST").build();
     }
 
     @Path("auth/request/login")
diff --git a/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
new file mode 100644
index 0000000..6df21f2
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/resources/WelcomeResource.java
@@ -0,0 +1,46 @@
+package org.keycloak.services.resources;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+@Path("/")
+public class WelcomeResource {
+
+    @Context
+    private UriInfo uriInfo;
+
+    @GET
+    @Produces("text/html")
+    public Response getWelcomePage() throws URISyntaxException {
+        String requestUri = uriInfo.getRequestUri().toString();
+        if (!requestUri.endsWith("/")) {
+            return Response.seeOther(new URI(requestUri + "/")).build();
+        } else {
+            return getResource("index.html");
+        }
+    }
+
+    @GET
+    @Path("/welcome-content/{name}")
+    @Produces("text/html")
+    public Response getResource(@PathParam("name") String name) {
+        InputStream inputStream = getClass().getClassLoader().getResourceAsStream("welcome-content/" + name);
+        if (inputStream != null) {
+            return Response.ok(inputStream).build();
+        } else {
+            return Response.status(Response.Status.NOT_FOUND).build();
+        }
+    }
+
+}
diff --git a/services/src/main/resources/META-INF/mime.types b/services/src/main/resources/META-INF/mime.types
index 432f4c8..1f77e9d 100644
--- a/services/src/main/resources/META-INF/mime.types
+++ b/services/src/main/resources/META-INF/mime.types
@@ -1 +1,4 @@
-text/css css CSS
\ No newline at end of file
+text/css css CSS
+text/javascript js JS
+text/javascript js JS
+image/svg+xml svg SVG
\ No newline at end of file
diff --git a/services/src/main/resources/welcome-content/favicon.ico b/services/src/main/resources/welcome-content/favicon.ico
new file mode 100644
index 0000000..b30dce5
Binary files /dev/null and b/services/src/main/resources/welcome-content/favicon.ico differ
diff --git a/services/src/main/resources/welcome-content/jboss_community.png b/services/src/main/resources/welcome-content/jboss_community.png
new file mode 100644
index 0000000..946e8f9
Binary files /dev/null and b/services/src/main/resources/welcome-content/jboss_community.png differ
diff --git a/services/src/main/resources/welcome-content/keycloak_logo.png b/services/src/main/resources/welcome-content/keycloak_logo.png
new file mode 100644
index 0000000..1f62687
Binary files /dev/null and b/services/src/main/resources/welcome-content/keycloak_logo.png differ
diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml
index f2d9eb0..28fc5cb 100755
--- a/testsuite/integration/pom.xml
+++ b/testsuite/integration/pom.xml
@@ -87,11 +87,6 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-admin-ui</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.keycloak</groupId>
             <artifactId>keycloak-audit-api</artifactId>
             <version>${project.version}</version>
         </dependency>
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 167bdd6..e8c4029 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -23,42 +23,32 @@ package org.keycloak.testutils;
 
 import io.undertow.Undertow;
 import io.undertow.Undertow.Builder;
-import io.undertow.server.handlers.resource.FileResource;
-import io.undertow.server.handlers.resource.FileResourceManager;
-import io.undertow.server.handlers.resource.Resource;
-import io.undertow.server.handlers.resource.ResourceChangeListener;
-import io.undertow.server.handlers.resource.ResourceManager;
-import io.undertow.server.handlers.resource.URLResource;
 import io.undertow.servlet.Servlets;
 import io.undertow.servlet.api.DefaultServletConfig;
 import io.undertow.servlet.api.DeploymentInfo;
 import io.undertow.servlet.api.FilterInfo;
-import io.undertow.servlet.api.ServletInfo;
 import org.jboss.resteasy.logging.Logger;
 import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
 import org.jboss.resteasy.spi.ResteasyDeployment;
 import org.keycloak.models.Config;
-import org.keycloak.provider.ProviderSessionFactory;
-import org.keycloak.services.filters.ClientConnectionFilter;
-import org.keycloak.theme.DefaultLoginThemeProvider;
-import org.keycloak.services.tmp.TmpAdminRedirectServlet;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.models.Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
 import org.keycloak.models.RealmModel;
 import org.keycloak.models.UserModel;
+import org.keycloak.provider.ProviderSessionFactory;
 import org.keycloak.representations.idm.RealmRepresentation;
+import org.keycloak.services.filters.ClientConnectionFilter;
 import org.keycloak.services.filters.KeycloakSessionServletFilter;
 import org.keycloak.services.managers.RealmManager;
 import org.keycloak.services.resources.KeycloakApplication;
+import org.keycloak.theme.DefaultKeycloakThemeProvider;
+import org.keycloak.util.JsonSerialization;
 
 import javax.servlet.DispatcherType;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URL;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -135,12 +125,12 @@ public class KeycloakServer {
             }
 
             File dir = new File(resources).getAbsoluteFile();
-            if (!dir.isDirectory() || !new File(dir, "admin-ui").isDirectory()) {
+            if (!dir.isDirectory() || !new File(dir, "forms").isDirectory()) {
                 throw new RuntimeException("Invalid resources directory");
             }
 
             if (Config.getThemeDir() == null) {
-                System.setProperty(DefaultLoginThemeProvider.class.getName() + ".disabled", "");
+                System.setProperty(DefaultKeycloakThemeProvider.class.getName() + ".disabled", "");
                 Config.setThemeDir(file(dir.getAbsolutePath(), "forms", "common-themes", "src", "main", "resources", "theme").getAbsolutePath());
             }
 
@@ -258,26 +248,21 @@ public class KeycloakServer {
 
         server = new UndertowJaxrsServer().start(builder);
 
-        DeploymentInfo di = server.undertowDeployment(deployment, "rest");
+        DeploymentInfo di = server.undertowDeployment(deployment, "");
         di.setClassLoader(getClass().getClassLoader());
         di.setContextPath("/auth");
         di.setDeploymentName("Keycloak");
-        di.setResourceManager(new KeycloakResourceManager(config.getResourcesHome()));
 
         di.setDefaultServletConfig(new DefaultServletConfig(true));
-        di.addWelcomePage("index.html");
+        di.addWelcomePage("welcome-content/index.html");
 
         FilterInfo filter = Servlets.filter("SessionFilter", KeycloakSessionServletFilter.class);
         di.addFilter(filter);
-        di.addFilterUrlMapping("SessionFilter", "/rest/*", DispatcherType.REQUEST);
+        di.addFilterUrlMapping("SessionFilter", "/*", DispatcherType.REQUEST);
 
         FilterInfo connectionFilter = Servlets.filter("ClientConnectionFilter", ClientConnectionFilter.class);
         di.addFilter(connectionFilter);
-        di.addFilterUrlMapping("ClientConnectionFilter", "/rest/*", DispatcherType.REQUEST);
-
-        ServletInfo tmpAdminRedirectServlet = Servlets.servlet("TmpAdminRedirectServlet", TmpAdminRedirectServlet.class);
-        tmpAdminRedirectServlet.addMappings("/admin", "/admin/");
-        di.addServlet(tmpAdminRedirectServlet);
+        di.addFilterUrlMapping("ClientConnectionFilter", "/*", DispatcherType.REQUEST);
 
         server.deploy(di);
 
@@ -310,52 +295,6 @@ public class KeycloakServer {
         info("Stopped Keycloak");
     }
 
-    public static class KeycloakResourceManager implements ResourceManager {
-
-        private String resourcesHome;
-
-        public KeycloakResourceManager(String resourcesHome) {
-            this.resourcesHome = resourcesHome;
-        }
-
-        @Override
-        public Resource getResource(String path) throws IOException {
-            if (resourcesHome == null) {
-                String realPath = "META-INF/resources" + path;
-                URL url = getClass().getClassLoader().getResource(realPath);
-                return new URLResource(url, url.openConnection(), path);
-            } else {
-                File file;
-                if (path.startsWith("/admin/")) {
-                    file = file(resourcesHome, "admin-ui", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
-                } else if (path.startsWith("/js/")) {
-                    file = file(resourcesHome, "integration", "js", "src", "main", "resources", "META-INF", "resources", path.replace('/', File.separatorChar));
-                } else {
-                    throw new IOException("Unknown resource " + path);
-                }
-                return new FileResource(file, new FileResourceManager(file.getParentFile(), 1), path);
-            }
-        }
-
-        @Override
-        public boolean isResourceChangeListenerSupported() {
-            return false;
-        }
-
-        @Override
-        public void registerResourceChangeListener(ResourceChangeListener listener) {
-        }
-
-        @Override
-        public void removeResourceChangeListener(ResourceChangeListener listener) {
-        }
-
-        @Override
-        public void close() throws IOException {
-        }
-
-    }
-
     private static File file(String... path) {
         StringBuilder s = new StringBuilder();
         for (String p : path) {