keycloak-aplcache

Changes

forms/common-themes/src/main/resources/theme/email/keycloak/email-verification.ftl 1(+0 -1)

forms/common-themes/src/main/resources/theme/email/keycloak/event-login_error.ftl 1(+0 -1)

forms/common-themes/src/main/resources/theme/email/keycloak/event-remove_totp.ftl 1(+0 -1)

forms/common-themes/src/main/resources/theme/email/keycloak/event-update_password.ftl 1(+0 -1)

forms/common-themes/src/main/resources/theme/email/keycloak/event-update_totp.ftl 1(+0 -1)

forms/common-themes/src/main/resources/theme/email/keycloak/messages/messages_de.properties 12(+0 -12)

forms/common-themes/src/main/resources/theme/email/keycloak/messages/messages_en.properties 12(+0 -12)

forms/common-themes/src/main/resources/theme/email/keycloak/password-reset.ftl 1(+0 -1)

forms/common-themes/src/main/resources/theme/login/base/login.ftl 84(+0 -84)

forms/common-themes/src/main/resources/theme/login/base/login-config-totp.ftl 45(+0 -45)

forms/common-themes/src/main/resources/theme/login/base/login-oauth-grant.ftl 66(+0 -66)

forms/common-themes/src/main/resources/theme/login/base/login-reset-password.ftl 33(+0 -33)

forms/common-themes/src/main/resources/theme/login/base/login-totp.ftl 37(+0 -37)

forms/common-themes/src/main/resources/theme/login/base/login-update-password.ftl 39(+0 -39)

forms/common-themes/src/main/resources/theme/login/base/login-update-profile.ftl 48(+0 -48)

forms/common-themes/src/main/resources/theme/login/base/messages/messages_de.properties 154(+0 -154)

forms/common-themes/src/main/resources/theme/login/base/messages/messages_en.properties 152(+0 -152)

forms/common-themes/src/main/resources/theme/login/base/register.ftl 124(+0 -124)

forms/common-themes/src/main/resources/theme/login/base/template.ftl 91(+0 -91)

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

forms/common-themes/src/main/resources/theme/login/patternfly/resources/img/favicon.ico 0(+0 -0)

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

forms/common-themes/src/main/resources/theme/login/patternfly/theme.properties 29(+0 -29)

forms/common-themes/src/main/resources/theme/welcome/keycloak/resources/favicon.ico 0(+0 -0)

forms/common-themes/src/main/resources/theme/welcome/keycloak/resources/index.html 50(+0 -50)

forms/common-themes/src/main/resources/theme/welcome/keycloak/resources/jboss_community.png 0(+0 -0)

forms/common-themes/src/main/resources/theme/welcome/keycloak/resources/keycloak.css 65(+0 -65)

project-integrations/aerogear-ups/auth-server/src/main/resources/theme/account/aerogear/resources/img/logo.png 0(+0 -0)

project-integrations/aerogear-ups/auth-server/src/main/resources/theme/admin/aerogear/resources/css/styles.css 45(+0 -45)

project-integrations/aerogear-ups/auth-server/src/main/resources/theme/admin/aerogear/resources/img/logo.png 0(+0 -0)

project-integrations/aerogear-ups/auth-server/src/main/resources/theme/admin/aerogear/theme.properties 4(+0 -4)

project-integrations/aerogear-ups/auth-server/src/main/resources/theme/login/aerogear/resources/img/logo.png 0(+0 -0)

Details

diff --git a/docbook/reference/en/en-US/modules/themes.xml b/docbook/reference/en/en-US/modules/themes.xml
index 3996b3a..db3d659 100755
--- a/docbook/reference/en/en-US/modules/themes.xml
+++ b/docbook/reference/en/en-US/modules/themes.xml
@@ -2,18 +2,18 @@
     <title>Themes</title>
 
     <para>
-        Keycloak provides theme support for login forms and account management. This allows customizing the look
-        and feel of end-user facing pages so they can be integrated with your brand and applications.
+        Keycloak provides theme support for web pages and emails. This allows customizing the look
+        and feel of end-user facing pages so they can be integrated with your applications.
     </para>
 
     <section>
         <title>Theme types</title>
         <para>
-            There are several types of themes in Keycloak:
+            A theme can support several types to customize different aspects of Keycloak. The types currently available
+            are:
             <itemizedlist>
                 <listitem>Account - Account management</listitem>
                 <listitem>Admin - Admin console</listitem>
-                <listitem>Common - Shared resources for themes</listitem>
                 <listitem>Email - Emails</listitem>
                 <listitem>Login - Login forms</listitem>
                 <listitem>Welcome - Welcome pages</listitem>
@@ -29,6 +29,11 @@
             from the drop-down box in the top left corner. Under <literal>Settings</literal> click on <literal>Theme</literal>.
         </para>
         <para>
+            To set the theme for the <literal>master</literal> Keycloak admin console set the admin console theme for
+            the <literal>master</literal> realm. To set the theme for per realm admin access control set the admin console
+            theme for the corresponding realm.
+        </para>
+        <para>
             To change the welcome theme you need to edit <literal>standalone/configuration/keycloak-server.json</literal>
             and add <literal>welcomeTheme</literal> to the theme element, for example:
 <programlisting>
@@ -43,9 +48,8 @@
     <section>
         <title>Default themes</title>
         <para>
-            Keycloak comes bundled with default themes in <literal>standalone/configuration/themes</literal>. It is
-            not recommended to edit these themes directly. Instead you should create a new theme to extend a default
-            theme. A good reference is to copy the keycloak themes as these extend the base theme to add styling.
+            Keycloak comes bundled with default themes in <literal>standalone/configuration/themes</literal>. You should
+            not edit the bundled themes directly. Instead create a new theme that extends a bundled theme.
         </para>
     </section>
 
@@ -65,24 +69,63 @@
         <para>
             A theme can extend another theme. When extending a theme you can override individual files (templates, stylesheets, etc.).
             The recommended way to create a theme is to extend the base theme. The base theme provides templates
-            and a default message bundle. It should be possible to achieve the customization required by styling these
-            templates.
+            and a default message bundle. If you decide to override templates bear in mind that you may need to update
+            your templates when upgrading to a new release to include any changes made to the original template.
+        </para>
+        <para>
+            Before creating a theme it's a good idea to disable caching as this makes it possible to edit theme resources
+            without restarting the server. To do this open <literal>../standalone/configuration/keycloak-server.json</literal>
+            for <literal>theme</literal> set <literal>staticMaxAge</literal> to <literal>-1</literal> and
+            <literal>cacheTemplates</literal> and <literal>cacheThemes</literal> to <literal>false</literal>. For example:
+<programlisting>[<![CDATA[
+"theme": {
+    "default": "keycloak",
+    "staticMaxAge": 01,
+    "cacheTemplates": false,
+    "cacheThemes": false,
+    "folder": {
+      "dir": "${jboss.server.config.dir}/themes"
+    }
+},
+]]></programlisting>
+            Remember to re-enable caching in production as it will significantly impact performance.
         </para>
         <para>
-            To create a new theme, create a folder in <literal>.../standalone/configuration/themes/&lt;theme type&gt;</literal>.
-            The name of the folder is the name of the theme. Then create a file <literal>theme.properties</literal> inside the theme folder.
-            The contents of the file should be:
+            To create a new theme create a directory for the theme in <literal>.../standalone/configuration/themes</literal>.
+            The name of the directory should be the name of the theme. For example to create a theme called <literal>example-theme</literal>
+            create the directory <literal>.../standalone/configuration/themes/example-theme</literal>. Inside the theme
+            directory you then need to create a directory for each of the types your theme is going to provide. For example
+            to add the login type to the <literal>example-theme</literal> theme create the directory
+            <literal>.../standalone/configuration/themes/example-theme/login</literal>.
         </para>
-        <programlisting>parent=base</programlisting>
         <para>
-            You have now created your theme. Check that it works by configuring it for a realm. It should look the same
-            as the base theme as you've not added anything to it yet. The next sections will describe how to modify
-            the theme.</para>
+            For each type create a file <literal>theme.properties</literal> which allows setting some configuration for
+            the theme, for example what theme it overrides and if it should import any themes. For the above example we
+            want to override the base theme and import common resources from the Keycloak theme. To do this create the
+            file <literal>.../standalone/configuration/themes/example-theme/login/theme.properties</literal> with the
+            following contents:
+<programlisting>[<![CDATA[
+parent=base
+import=common/keycloak
+]]></programlisting>
+        </para>
+        <para>
+            You have now created a theme with support for the login type. To check that it works open the admin console.
+            Select your realm and click on <literal>Themes</literal>. For <literal>Login Theme</literal> select
+            <literal>example-theme</literal> and click <literal>Save</literal>. Then open the login page for the realm.
+            You can do this either by login through your application or by opening <literal>http://localhost:8080/realms/&lt;realm name&gt;/account</literal>.
+        </para>
+        <para>
+            To see the effect of changing the parent theme, set <literal>parent=keycloak</literal> in <literal>theme.properties</literal>
+            and refresh the login page. To follow the rest of the documentation set it back to <literal>parent=base</literal>
+            before continuing.
+        </para>
         <section>
             <title>Stylesheets</title>
             <para>
-                A theme can have one or more stylesheets, to add a stylesheet create a file inside <literal>resources/css</literal> (for example <literal>resources/css/styles.css</literal>)
-                inside your theme folder. Then registering it in <literal>theme.properties</literal> by adding:
+                A theme can have one or more stylesheets, to add a stylesheet create a file inside <literal>resources/css</literal>
+                (for example <literal>resources/css/styles.css</literal>) inside your theme folder. Then registering it
+                in <literal>theme.properties</literal> by adding:
             </para>
             <programlisting>styles=css/styles.css</programlisting>
             <para>
@@ -90,6 +133,17 @@
                 as you want. For example:
             </para>
             <programlisting>styles=css/styles.css css/more-styles.css</programlisting>
+            For the example-theme above add <literal>example-theme/login/resources/css/styles.css</literal> with the
+            following content:
+<programlisting>[<![CDATA[
+#kc-form {
+    background-color: #000;
+    color: #fff;
+    padding: 20px;
+}]]></programlisting>
+            Then edit <literal>example-theme/login/theme.properties</literal> and add <programlisting>styles=css/styles.css</programlisting>.
+            Refresh the login page to see your changes. It's not pretty, but you can see how easily you can modify the
+            styles for your theme.
         </section>
         <section>
             <title>Scripts</title>
@@ -121,9 +175,8 @@
         <section>
             <title>Messages</title>
             <para>
-                Text in the templates are loaded from message bundles. Currently internationalization isn't supported,
-                but that will be added in a later release. A theme that extends another theme will inherit all messages
-                from the parents message bundle, but can override individual messages. For example to replace
+                Text in the templates are loaded from message bundles. A theme that extends another theme will inherit
+                all messages from the parents message bundle, but can override individual messages. For example to replace
                 <literal>Username</literal> on the login form with <literal>Your Username</literal> create the file
                 <literal>messages/messages.properties</literal> inside your theme folder and add the following content:
             </para>
@@ -134,31 +187,80 @@
             <para>
                 Keycloak uses <ulink url="http://freemarker.org">Freemarker Templates</ulink> in order to generate HTML.
                 These templates are defined in <literal>.ftl</literal> files and can be overriden from the base theme.
-                Check out the Freemarker website on how to form a template file.
+                Check out the Freemarker website on how to form a template file. To override the login template for the
+                <literal>example-theme</literal> copy <literal>../standalone/configuration/themes/base/login/login.ftl</literal>
+                to <literal>../standalone/configuration/themes/example-theme/login</literal> and open it in an editor. After
+                the first line (&lt;#import ...&gt;) add <literal>&lt;h1&gt;HELLO WORLD!&lt;/h1&gt;</literal> then refresh
+                the page.
             </para>
         </section>
     </section>
 
     <section>
+        <title>Deploying themes</title>
+        <para>
+            Themes can be deployed to Keycloak by copying the theme directory to <literal>../standalone/configuration/themes</literal>
+            or it can be deployed as a module. For a single server or during development just copying the theme is fine, but
+            in a cluster or domain it's recommended to deploy as a module.
+        </para>
+        <para>
+            To deploy a theme as a module you need to create an jar (it's basically just a zip with jar extension) with
+            the theme resources and a file <literal>META/keycloak-server.json</literal> that describes the themes contained
+            in the archive. For example <literal>example-theme.jar</literal> with the contents:
+            <itemizedlist>
+                <listitem>META-INF/keycloak-themes.json</listitem>
+                <listitem>theme/example-theme/login/theme.properties</listitem>
+                <listitem>theme/example-theme/login/login.ftl</listitem>
+                <listitem>theme/example-theme/login/resources/css/styles.css</listitem>
+            </itemizedlist>
+            The contents of META-INF/keycloak-server.json in this case would be:
+<programlisting>[<![CDATA[
+{
+    "themes": [{
+        "name" : "example-theme",
+        "types": [ "login" ]
+    }]
+}
+]]></programlisting>
+            As you can see a single jar can contain multiple themes and each theme can support one or more types.
+        </para>
+        <para>
+            The deploy the jar as a module to Keycloak you can either manually create the module or use <literal>jboss-cli</literal>.
+            It's simplest to use <literal>jboss-cli</literal> as it creates the required directories and module descriptor
+            for you. To deploy the above jar <literal>jboss-cli</literal> run:
+<programlisting>[<![CDATA[
+    KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.example.exampletheme --resources=example-theme.jar"
+]]></programlisting>
+            If you're on windows run <programlisting>KEYCLOAK_HOME/bin/jboss-cli.bat</programlisting>.
+        </para>
+        <para>
+            This command creates <literal>modules/org/example/exampletheme/main</literal> containing <literal>example-theme.jar</literal>
+            and <literal>module.xml</literal>.
+        </para>
+        <para>
+            Once you've created the module you need to register it with Keycloak do this by editing
+            <literal>../standalone/configuration/keycloak-server.json</literal> and adding the module to <literal>theme/module/modules</literal>. For example:
+<programlisting>[<![CDATA[
+"theme": {
+    ...
+    "module": {
+        "modules": [ "org.example.exampletheme" ]
+    }
+}
+]]></programlisting>
+        </para>
+        <para>
+            If a theme is deployed to <literal>../standalone/configuration/themes</literal> and as a module the first
+            is used.
+        </para>
+    </section>
+
+    <section>
         <title>SPIs</title>
         <para>
             For full control of login forms and account management Keycloak provides a number of SPIs.
         </para>
         <section>
-            <title>Theme SPI</title>
-            <para>
-                The Theme SPI allows creating different mechanisms to load themes for the default FreeMarker based
-                implementations of login forms and account management. To create a theme provider you will need to implement
-                <literal>org.keycloak.freemarker.ThemeProviderFactory</literal> and <literal>org.keycloak.freemarker.ThemeProvider</literal>.
-            </para>
-            <para>
-                Keycloak comes with two theme providers, one that loads themes from the classpath (used by default themes)
-                and another that loads themes from a folder (used by custom themes). Looking at these
-                would be a good place to start to create your own theme provider. You can find them inside
-                <literal>forms/common-themes</literal> on GitHub or the source download.
-            </para>
-        </section>
-        <section>
             <title>Account SPI</title>
             <para>
                 The Account SPI allows implementing the account management pages using whatever web framework or templating
diff --git a/examples/themes/README.md b/examples/themes/README.md
index 75ec61a..ad60677 100644
--- a/examples/themes/README.md
+++ b/examples/themes/README.md
@@ -21,7 +21,7 @@ Then open $KEYCLOAK_HOME/standalone/configuration/keycloak-server.json and regis
         }
     }
 
-Alternatively you can copy `src/main/resources/theme/login` to `standalone/configuration/themes/login/`. 
+Alternatively you can copy `src/main/resources/theme/sunrise` to `standalone/configuration/themes/`. 
 
 Once you've added the theme open the admin console, select your realm, click on `Theme`. In the dropdown for `Login Theme` select `sunrise`. Click `Save` and login to the realm to see the new theme in action.
 
@@ -46,13 +46,7 @@ Then open $KEYCLOAK_HOME/standalone/configuration/keycloak-server.json and regis
         }
     }
 
-Alternatively you can copy:
-
-* `account/logo-example` to `standalone/configuration/themes/account/`
-* `login/logo-example` to `standalone/configuration/themes/login/`
-* `admin/logo-example` to `standalone/configuration/themes/admin/`
-* `welcome/logo-example` to `standalone/configuration/themes/welcome/`
-
+Alternatively you can copy `src/main/resources/theme/logo-example` to `standalone/configuration/themes/`. 
 
 Once you've added the theme open the admin console, select your realm, click on `Theme`. In the dropdowns for `Login Theme`, `Account Theme` and `Admin Console Theme` select `logo-example`. Click `Save` and login to the realm to see the new theme in action.
 
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java
index 2fdaf05..42fa50e 100755
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManagerFactory.java
@@ -11,9 +11,7 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class ExtendingThemeManagerFactory implements ThemeProviderFactory {
 
-    private ConcurrentHashMap<ThemeKey, Theme> themeCache = new ConcurrentHashMap<ThemeKey, Theme>();
-
-    private ExtendingThemeManager themeManager;
+    private ConcurrentHashMap<ThemeKey, Theme> themeCache;
 
     @Override
     public ThemeProvider create(KeycloakSession session) {
@@ -23,7 +21,7 @@ public class ExtendingThemeManagerFactory implements ThemeProviderFactory {
     @Override
     public void init(Config.Scope config) {
         if(Config.scope("theme").getBoolean("cacheThemes", true)) {
-            themeCache = new ConcurrentHashMap<ThemeKey, Theme>();
+            themeCache = new ConcurrentHashMap<>();
         }
     }
 
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java
index 8f2dc0e..e41d671 100755
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/FreeMarkerUtil.java
@@ -20,7 +20,7 @@ public class FreeMarkerUtil {
 
     public FreeMarkerUtil() {
         if (Config.scope("theme").getBoolean("cacheTemplates", true)) {
-            cache = new ConcurrentHashMap<String, Template>();
+            cache = new ConcurrentHashMap<>();
         }
     }
 
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 c95edd2..3e92be8 100755
--- a/forms/common-themes/src/main/java/org/keycloak/theme/ClassLoaderTheme.java
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/ClassLoaderTheme.java
@@ -2,13 +2,11 @@ package org.keycloak.theme;
 
 import org.keycloak.freemarker.Theme;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.Locale;
 import java.util.Properties;
-import java.util.ResourceBundle;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -42,7 +40,7 @@ public class ClassLoaderTheme implements Theme {
         this.type = type;
         this.classLoader = classLoader;
 
-        String themeRoot = "theme/" + type.toString().toLowerCase() + "/" + name + "/";
+        String themeRoot = "theme/" + name + "/" + type.toString().toLowerCase() + "/";
 
         this.templateRoot = themeRoot;
         this.resourceRoot = themeRoot + "resources/";
@@ -60,10 +58,6 @@ public class ClassLoaderTheme implements Theme {
         }
     }
 
-    public ClassLoaderTheme() {
-
-    }
-
     @Override
     public String getName() {
         return name;
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 0edc92e..7d9ce2a 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
@@ -18,11 +18,13 @@ public class FolderTheme implements Theme {
     private String parentName;
     private String importName;
     private File themeDir;
+    private String name;
     private Type type;
     private final Properties properties;
 
-    public FolderTheme(File themeDir, Type type) throws IOException {
+    public FolderTheme(File themeDir, String name, Type type) throws IOException {
         this.themeDir = themeDir;
+        this.name = name;
         this.type = type;
         this.properties = new Properties();
 
@@ -36,7 +38,7 @@ public class FolderTheme implements Theme {
 
     @Override
     public String getName() {
-        return themeDir.getName();
+        return name;
     }
 
     @Override
diff --git a/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java b/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java
index b8c7c89..90d8ba6 100755
--- a/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java
+++ b/forms/common-themes/src/main/java/org/keycloak/theme/FolderThemeProvider.java
@@ -15,10 +15,10 @@ import java.util.Set;
  */
 public class FolderThemeProvider implements ThemeProvider {
 
-    private File rootDir;
+    private File themesDir;
 
-    public FolderThemeProvider(File rootDir) {
-        this.rootDir = rootDir;
+    public FolderThemeProvider(File themesDir) {
+        this.themesDir = themesDir;
     }
 
     @Override
@@ -28,51 +28,41 @@ public class FolderThemeProvider implements ThemeProvider {
 
     @Override
     public Theme getTheme(String name, Theme.Type type) throws IOException {
-        if (hasTheme(name, type)) {
-            return new FolderTheme(new File(getTypeDir(type), name), type);
-        }
-        return null;
+        File themeDir = getThemeDir(name, type);
+        return themeDir.isDirectory() ? new FolderTheme(themeDir, name, type) : null;
     }
 
     @Override
     public Set<String> nameSet(Theme.Type type) {
-        File typeDir = getTypeDir(type);
-        if (typeDir != null) {
-            File[] themes = typeDir.listFiles(new FileFilter() {
-                @Override
-                public boolean accept(File pathname) {
-                    return pathname.isDirectory();
-                }
-            });
-
+        final String typeName = type.name().toLowerCase();
+        File[] themeDirs = themesDir.listFiles(new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+                return pathname.isDirectory() && new File(pathname, typeName).isDirectory();
+            }
+        });
+        if (themeDirs != null) {
             Set<String> names = new HashSet<String>();
-            for (File t : themes) {
-                names.add(t.getName());
+            for (File themeDir : themeDirs) {
+                names.add(themeDir.getName());
             }
             return names;
+        } else {
+            return Collections.emptySet();
         }
-
-        return Collections.emptySet();
-    }
-
-    private File getTypeDir(Theme.Type type) {
-        if (rootDir != null && rootDir.isDirectory()) {
-            File typeDir = new File(rootDir, type.name().toLowerCase());
-            if (typeDir.isDirectory()) {
-                return typeDir;
-            }
-        }
-        return null;
     }
 
     @Override
     public boolean hasTheme(String name, Theme.Type type) {
-        File typeDir = getTypeDir(type);
-        return typeDir != null && new File(typeDir, name).isDirectory();
+        return getThemeDir(name, type).isDirectory();
     }
 
     @Override
     public void close() {
     }
 
+    private File getThemeDir(String name, Theme.Type type) {
+        return new File(themesDir, name + File.separator + type.name().toLowerCase());
+    }
+
 }
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login.ftl b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
new file mode 100755
index 0000000..505e185
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
@@ -0,0 +1,84 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout displayInfo=social.displayInfo; section>
+    <#if section = "title">
+        <#if client.application>
+            ${msg("loginTitle",(realm.name!''))}
+        <#elseif client.oauthClient>
+            ${msg("loginOauthTitle",(realm.name!''))}
+        </#if>
+    <#elseif section = "header">
+        <#if client.application>
+            ${msg("loginTitleHtml",(realm.name!''))}
+        <#elseif client.oauthClient>
+            ${msg("loginOauthTitleHtml",(realm.name!''), (client.clientId!''))}
+        </#if>
+    <#elseif section = "form">
+        <#if realm.password>
+            <form id="kc-form-login" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
+                <div class="${properties.kcFormGroupClass!}">
+                    <div class="${properties.kcLabelWrapperClass!}">
+                        <label for="username" class="${properties.kcLabelClass!}"><#if !realm.registrationEmailAsUsername>${msg("usernameOrEmail")}<#else>${msg("email")}</#if></label>
+                    </div>
+
+                    <div class="${properties.kcInputWrapperClass!}">
+                        <input id="username" class="${properties.kcInputClass!}" name="username" value="${(login.username!'')?html}" type="text" autofocus />
+                    </div>
+                </div>
+
+                <div class="${properties.kcFormGroupClass!}">
+                    <div class="${properties.kcLabelWrapperClass!}">
+                        <label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
+                    </div>
+
+                    <div class="${properties.kcInputWrapperClass!}">
+                        <input id="password" class="${properties.kcInputClass!}" name="password" type="password" />
+                    </div>
+                </div>
+
+                <div class="${properties.kcFormGroupClass!}">
+                    <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                        <#if realm.rememberMe>
+                            <div class="checkbox">
+                                <label>
+                                    <#if login.rememberMe??>
+                                        <input id="rememberMe" name="rememberMe" type="checkbox" tabindex="3" checked> ${msg("rememberMe")}
+                                    <#else>
+                                        <input id="rememberMe" name="rememberMe" type="checkbox" tabindex="3"> ${msg("rememberMe")}
+                                    </#if>
+                                </label>
+                            </div>
+                        </#if>
+                        <div class="${properties.kcFormOptionsWrapperClass!}">
+                            <#if realm.resetPasswordAllowed>
+                                <span><a href="${url.loginPasswordResetUrl}">${msg("doForgotPassword")}</a></span>
+                            </#if>
+                        </div>
+                    </div>
+
+                    <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                        <div class="${properties.kcFormButtonsWrapperClass!}">
+                            <input class="btn btn-primary btn-lg" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
+                            <input class="btn btn-default btn-lg" name="cancel" id="kc-cancel" type="submit" value="${msg("doCancel")}"/>
+                        </div>
+                     </div>
+                </div>
+            </form>
+        </#if>
+    <#elseif section = "info" >
+        <#if realm.password && realm.registrationAllowed>
+            <div id="kc-registration">
+                <span>${msg("noAccount")} <a href="${url.registrationUrl}">${msg("doRegister")}</a></span>
+            </div>
+        </#if>
+
+        <#if realm.password && social.providers??>
+            <div id="kc-social-providers">
+                <ul>
+                    <#list social.providers as p>
+                        <li><a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${p.providerId}"> <span class="text">${p.alias}</span></a></li>
+                    </#list>
+                </ul>
+            </div>
+        </#if>
+    </#if>
+</@layout.registrationLayout>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl
new file mode 100755
index 0000000..94f264a
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-config-totp.ftl
@@ -0,0 +1,45 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout displayInfo=true; section>
+    <#if section = "title">
+        ${msg("loginTotpTitle")}
+    <#elseif section = "header">
+        ${msg("loginTotpTitle")}
+    <#elseif section = "form">
+        <form action="${url.loginUpdateTotpUrl}" class="${properties.kcFormClass!}" id="kc-totp-settings-form" method="post">
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="otp" class="${properties.kcLabelClass!}">${msg("loginTotpOneTime")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="totp" name="totp" class="${properties.kcInputClass!}" />
+                </div>
+                <input type="hidden" id="totpSecret" name="totpSecret" value="${totp.totpSecret}" />
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <input class="btn btn-primary btn-lg" type="submit" value="${msg("doSubmit")}"/>
+                </div>
+            </div>
+        </form>
+    <#elseif section = "info" >
+        <ol id="kc-totp-settings">
+            <li>
+                <p>${msg("loginTotpStep1")}</p>
+            </li>
+            <li>
+                <p>${msg("loginTotpStep2")}</p>
+                <img src="${totp.totpSecretQrCodeUrl}" alt="Figure: Barcode"><br/>
+                <span class="code">${totp.totpSecretEncoded}</span>
+            </li>
+            <li>
+                <p>${msg("loginTotpStep3")}</p>
+            </li>
+        </ol>
+    </#if>
+</@layout.registrationLayout>
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl
new file mode 100755
index 0000000..9b0637b
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-oauth-grant.ftl
@@ -0,0 +1,66 @@
+<#-- TODO: Only a placeholder, implementation needed -->
+<#import "template.ftl" as layout>
+<@layout.registrationLayout bodyClass="oauth"; section>
+    <#if section = "title">
+        ${msg("oauthGrantTitle")}
+    <#elseif section = "header">
+        ${msg("oauthGrantTitleHtml",(realm.name!''), (client.clientId!''))}
+    <#elseif section = "form">
+        <div id="kc-oauth" class="content-area">
+            <h3>${msg("oauthGrantRequest")}</h3>
+            <ul>
+                <#if oauth.claimsRequested??>
+                    <li>
+                        <span>
+                            ${msg("personalInfo")}&nbsp;
+                            <#list oauth.claimsRequested as claim>
+                                ${advancedMsg(claim)}<#if claim_has_next>,&nbsp;</#if>
+                            </#list>
+                        </span>
+                    </li>
+                </#if>
+                <#if oauth.accessRequestMessage??>
+                    <li>
+                        <span>
+                            ${oauth.accessRequestMessage}
+                        </span>
+                    </li>
+                </#if>
+                <#if oauth.realmRolesRequested??>
+                    <#list oauth.realmRolesRequested as role>
+                        <li>
+                            <span><#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)}</#if></span>
+                        </li>
+                    </#list>
+                </#if>
+                <#if oauth.resourceRolesRequested??>
+                    <#list oauth.resourceRolesRequested?keys as resource>
+                        <#list oauth.resourceRolesRequested[resource] as role>
+                            <li>
+                                <span class="kc-role"><#if role.description??>${advancedMsg(role.description)}<#else>${advancedMsg(role.name)}</#if></span>
+                                <span class="kc-resource">${msg("inResource", resource)}</span>
+                            </li>
+                        </#list>
+                    </#list>
+                </#if>
+            </ul>
+
+            <form class="form-actions" action="${url.oauthAction}" method="POST">
+                <input type="hidden" name="code" value="${oauth.code}">
+                <div class="${properties.kcFormGroupClass!}">
+                    <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                        <div class="${properties.kcFormOptionsWrapperClass!}">
+                        </div>
+                    </div>
+
+                    <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                        <div class="${properties.kcFormButtonsWrapperClass!}">
+                            <input class="btn btn-primary btn-lg" name="accept" id="kc-login" type="submit" value="${msg("doYes")}"/>
+                            <input class="btn btn-default btn-lg" name="cancel" id="kc-cancel" type="submit" value="${msg("doNo")}"/>
+                        </div>
+                    </div>
+                </div>
+            </form>
+        </div>
+    </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-reset-password.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-reset-password.ftl
new file mode 100755
index 0000000..ec327c2
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-reset-password.ftl
@@ -0,0 +1,33 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout displayInfo=true; section>
+    <#if section = "title">
+        ${msg("emailForgotTitle")}
+    <#elseif section = "header">
+        ${msg("emailForgotTitle")}
+    <#elseif section = "form">
+        <form id="kc-reset-password-form" class="${properties.kcFormClass!}" action="${url.loginPasswordResetUrl}" method="post">
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="username" class="${properties.kcLabelClass!}">${msg("usernameOrEmail")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="username" name="username" class="${properties.kcInputClass!}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                        <span><a href="${url.loginUrl}">${msg("backToLogin")}</a></span>
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <input class="btn btn-primary btn-lg" type="submit" value="${msg("doSubmit")}"/>
+                </div>
+            </div>
+        </form>
+    <#elseif section = "info" >
+        ${msg("emailInstruction")}
+    </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-totp.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-totp.ftl
new file mode 100755
index 0000000..ec07935
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-totp.ftl
@@ -0,0 +1,37 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout; section>
+    <#if section = "title">
+        ${msg("loginTitle",realm.name)}
+    <#elseif section = "header">
+        ${msg("loginTitleHtml",realm.name)}
+    <#elseif section = "form">
+        <form id="kc-totp-login-form" class="${properties.kcFormClass!}" action="${url.loginAction}" method="post">
+            <input id="username" name="username" value="${login.username!''}" type="hidden" />
+            <input id="password-token" name="password-token" value="${login.passwordToken!''}" type="hidden" />
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="totp" class="${properties.kcLabelClass!}">${msg("doLogIn")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input id="totp" name="totp" type="text" class="${properties.kcInputClass!}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <div class="${properties.kcFormButtonsWrapperClass!}">
+                        <input class="btn btn-primary btn-lg" name="login" id="kc-login" type="submit" value="${msg("doLogIn")}"/>
+                        <input class="btn btn-default btn-lg" name="cancel" id="kc-cancel" type="submit" value="${msg("doCancel")}"/>
+                    </div>
+                </div>
+            </div>
+        </form>
+    </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-update-password.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-update-password.ftl
new file mode 100755
index 0000000..d201616
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-update-password.ftl
@@ -0,0 +1,39 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout displayInfo=true; section>
+    <#if section = "title">
+        ${msg("updatePasswordTitle")}
+    <#elseif section = "header">
+        ${msg("updatePasswordTitle")}
+    <#elseif section = "form">
+        <form id="kc-passwd-update-form" class="${properties.kcFormClass!}" action="${url.loginUpdatePasswordUrl}" method="post">
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="password-new" class="${properties.kcLabelClass!}">${msg("passwordNew")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="password" id="password-new" name="password-new" class="${properties.kcInputClass!}" autofocus />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="password-confirm" class="${properties.kcLabelClass!}">${msg("passwordConfirm")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="password" id="password-confirm" name="password-confirm" class="${properties.kcInputClass!}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <input class="btn btn-primary btn-lg" type="submit" value="${msg("doSubmit")}"/>
+                </div>
+            </div>
+        </form>
+    </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl b/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl
new file mode 100755
index 0000000..56b5cbe
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/login-update-profile.ftl
@@ -0,0 +1,48 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout; section>
+    <#if section = "title">
+        ${msg("loginProfileTitle")}
+    <#elseif section = "header">
+        ${msg("loginProfileTitle")}
+    <#elseif section = "form">
+        <form id="kc-update-profile-form" class="${properties.kcFormClass!}" action="${url.loginUpdateProfileUrl}" method="post">
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="email" name="email" value="${(user.email!'')?html}" class="${properties.kcInputClass!}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="firstName" class="${properties.kcLabelClass!}">${msg("firstName")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="firstName" name="firstName" value="${(user.firstName!'')?html}" class="${properties.kcInputClass!}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="lastName" class="${properties.kcLabelClass!}">${msg("lastName")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="lastName" name="lastName" value="${(user.lastName!'')?html}" class="${properties.kcInputClass!}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <input class="btn btn-primary btn-lg" type="submit" value="${msg("doSubmit")}" />
+                </div>
+            </div>
+        </form>
+    </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
new file mode 100644
index 0000000..dc5acea
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_de.properties
@@ -0,0 +1,154 @@
+doLogIn=Anmelden
+doRegister=Registrieren
+doCancel=Abbrechen
+doSubmit=Absenden
+doYes=Ja
+doNo=Nein
+doForgotPassword=Passwort vergessen?
+doClickHere=hier klicken
+
+registerWithTitle=Registrierung bei {0}
+registerWithTitleHtml=Registrierung bei <strong>{0}</strong>
+loginTitle=Anmeldung bei {0}
+loginTitleHtml=Anmeldung bei <strong>{0}</strong>
+loginOauthTitle=Tempor�rer zugriff auf {0}
+loginOauthTitleHtml=Tempor�rer zugriff auf <strong>{0}</strong> angefordert von <strong>{1}</strong>.
+loginTotpTitle=Mobile Authentifizierung Einrichten
+loginProfileTitle=Benutzerkonto Informationen aktualisieren
+oauthGrantTitle=OAuth gew�hren
+oauthGrantTitleHtml=Tempor�rer zugriff auf <strong>{0}</strong> angefordert von <strong>{1}</strong>.
+errorTitle=Es tut uns leid...
+errorTitleHtml=Es tut uns leid...
+emailVerifyTitle=E-Mail verifizieren
+emailForgotTitle=Passwort vergessen?
+updatePasswordTitle=Passwort aktualisieren
+codeSuccessTitle=Erfolgreicher code
+codeErrorTitle=Fehler code\: {0}
+
+noAccount=Neuer Benutzer?
+username=Benutzername
+usernameOrEmail=Benutzername oder E-Mail
+firstName=Vorname
+fullName=Name
+lastName=Nachname
+email=E-Mail
+password=Passwort
+passwordConfirm=Passwort best�tigen
+passwordNew=Neues Passwort
+passwordNewConfirm=Neues Passwort best�tigen
+rememberMe=Angemeldet bleiben
+authenticatorCode=One-time Code
+street=Strasse
+region=Staat, Provinz, Region
+postal_code=PLZ
+locality=Stadt oder Ortschaft
+country=Land
+
+loginTotpStep1=Installieren Sie <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> oder <a href="http://code.google.com/p/google-authenticator/" target="_blank">Google Authenticator</a> auf Ihrem Smartphone.
+loginTotpStep2=�ffnen Sie die Applikation und scannen Sie den Barcode oder geben sie den Code ein.
+loginTotpStep3=Geben Sie den One-time Code welcher die Applikation generiert hat ein und klicken Sie auf Absenden.
+loginTotpOneTime=One-time Code
+
+oauthGrantRequest=Wollen Sie diese Zugriffsreche gew�hren?
+inResource=in <strong>{0}</strong>
+
+emailVerifyInstruction1=Ein E-Mail mit weitern Anweisungen wurde an Sie versendet.
+emailVerifyInstruction2=Falls Sie kein E-Mail erhalten haben, dann k�nnen Sie 
+emailVerifyInstruction3=um ein neues E-Mail zu verschicken.
+
+backToLogin=&laquo; Zur�ck zur Anmeldung
+backToApplication=&laquo; Zur�ck zur Applikation
+
+emailInstruction=Geben Sie ihren Benutzernamen oder E-Mail Adresse ein und klicken Sie auf Absenden. Danach werden wir ihnen ein E-Mail mit weiteren Instruktionen zusenden.
+
+copyCodeInstruction=Bitte kopieren sie den folgenden Code und f�gen ihn in die Applikation ein\:
+
+personalInfo=Pers�nliche Informationen:
+
+invalidUserMessage=Ung�ltiger Benutzername oder Passwort.
+invalidEmailMessage=Ung�ltige E-Mail Adresse.
+accountDisabledMessage=Benutzerkonto ist gesperrt, bitte kontaktieren Sie den Admin.
+accountTemporarilyDisabledMessage=Benutzerkonto ist tempor�r gesperrt, bitte kontaktieren Sie den Admin oder versuchen Sie es sp�ter noch einmal.
+expiredCodeMessage=Zeit�berschreitung bei der Anmeldung. Bitter melden Sie sich erneut an.
+
+missingFirstNameMessage=Bitte geben Sie einen Vornamen ein.
+missingLastNameMessage=Bitte geben Sie einen Nachnamen ein.
+missingEmailMessage=Bitte geben Sie eine E-Mail Adresse ein.
+missingUsernameMessage=Bitte geben Sie einen Benutzernamen ein.
+missingPasswordMessage=Bitte geben Sie ein Passwort ein.
+missingTotpMessage=Bitte geben Sie den One-time Code ein.
+notMatchPasswordMessage=Passw�rter sind nicht identisch.
+
+invalidPasswordExistingMessage=Das aktuelle Passwort is ung�ltig.
+invalidPasswordConfirmMessage=Die Passwortbest�tigung ist nicht identisch.
+invalidTotpMessage=Ung�ltiger One-time Code.
+
+usernameExistsMessage=Benutzername existiert bereits.
+emailExistsMessage=E-Mail existiert bereits.
+
+federatedIdentityEmailExistsMessage=Es existiert bereits ein Benutzer mit dieser E-Mail Adresse. Bitte melden Sie sich bei der Benutzerverwaltung an um das Benutzerkonto zu verkn�pfen.
+federatedIdentityUsernameExistsMessage=Es existiert bereits ein Benutzer mit diesem Benutzernamen. Bitte melden Sie sich bei der Benutzerverwaltung an um das Benutzerkonto zu verkn�pfen.
+
+configureTotpMessage=Sie m�ssen eine Mobile Authentifizierung einrichten um das Benutzerkonto zu aktivieren.
+updateProfileMessage=Sie m�ssen ihr Benutzerkonto aktualisieren um das Benutzerkonto zu aktivieren.
+updatePasswordMessage=Sie m�ssen ihr Passwort �ndern um das Benutzerkonto zu aktivieren.
+verifyEmailMessage=Sie m�ssen ihre E-Mail Adresse verifizieren um das Benutzerkonto zu aktivieren.
+
+emailSentMessage=Sie sollten in k�rze ein E-Mail mit weiteren Instruktionen erhalten.
+emailSendErrorMessage=Das E-Mail konnte nicht versendet werden, bitte versuchen Sie es sp�ter nochmals.
+
+accountUpdatedMessage=Ihr Benutzerkonto wurde aktualisiert.
+accountPasswordUpdatedMessage=Ihr Passwort wurde aktualisiert.
+
+noAccessMessage=Kein Zugriff
+
+invalidPasswordMinLengthMessage=Ung�ltiges Passwort: minimum l�nge {0}.
+invalidPasswordMinDigitsMessage=Ung�ltiges Passwort: muss mindestens {0} Zahl(en) beinhalten.
+invalidPasswordMinLowerCaseCharsMessage=Ung�ltiges Passwort: muss mindestens {0} Kleinbuchstaben beinhalten.
+invalidPasswordMinUpperCaseCharsMessage=Ung�ltiges Passwort: muss mindestens {0} Grossbuchstaben beinhalten.
+invalidPasswordMinSpecialCharsMessage=Ung�ltiges Passwort: muss mindestens {0} Spezialzeichen beinhalten.
+invalidPasswordNotUsernameMessage=Ung�ltiges Passwort\: darf nicht gleich sein wie Benutzername.
+
+failedToProcessResponseMessage=Konnte Response nicht verarbeiten.
+httpsRequiredMessage=HTTPS erforderlich.
+realmNotEnabledMessage=Realm nicht aktiviert.
+invalidRequestMessage=Ung�ltiger Request.
+unknownLoginRequesterMessage=Ung�ltiger login requester
+loginRequesterNotEnabledMessage=Login requester nicht aktiviert.
+bearerOnlyMessage=Bearer-only Applikationen k�nne sich nicht via Browser anmelden.
+directGrantsOnlyMessage=Direct-grants-only Clients k�nne sich nicht via Browser anmelden.
+invalidRedirectUriMessage=Ung�ltige redirect uri.
+unsupportedNameIdFormatMessage=Nicht unterst�tztes NameIDFormat.
+invlidRequesterMessage=Ung�ltiger requester.
+registrationNotAllowedMessage=Registrierung nicht erlaubt.
+
+permissionNotApprovedMessage=Berechtigung nicht best�tigt.
+noRelayStateInResponseMessage=Kein relay state in der Antwort von dem Identity Provider [{0}].
+identityProviderAlreadyLinkedMessage=Die Identit�t welche von dem Identity Provider [{0}] zur�ckgegeben wurde, ist bereits mit einem anderen Benutzer verkn�pft.
+insufficientPermissionMessage=Nicht gen�gend Rechte um die Identit�t zu verkn�pfen.
+couldNotProceedWithAuthenticationRequestMessage=Konnte den Authentifizierungs Request nicht weiter verarbeiten.
+couldNotObtainTokenMessage=Konnte kein token vom Identity Provider [{0}] entnehmen.
+unexpectedErrorRetrievingTokenMessage=Unerwarteter Fehler w�hrend dem Empfang des Token von dem Identity Provider [{0}].
+unexpectedErrorHandlingResponseMessage=Unerwarteter Fehler w�hrend der Bearbeitung des Respons vom Identity Provider [{0}].
+identityProviderAuthenticationFailedMessage=Authentifizierung Fehlgeschlagen. Konnte sich mit dem Identity Provider [{0}] nicht authentifizieren.
+couldNotSendAuthenticationRequestMessage=Konnte Authentifizierungs Request nicht an den Identity Provider [{0}] schicken.
+unexpectedErrorHandlingRequestMessage=Unerwarteter Fehler w�hrend der Bearbeitung des Requests zum Identity Provider [{0}].
+invalidAccessCodeMessage=Ung�ltiger Access-Code.
+sessionNotActiveMessage=Session nicht aktiv.
+unknownCodeMessage=Unbekannter Code, bitte melden Sie sich erneut �ber die Applikation an.
+invalidCodeMessage=Ung�ltiger Code, bitte melden Sie sich erneut �ber die Applikation an.
+identityProviderUnexpectedErrorMessage=Unerwarteter Fehler w�hrend der Authentifizierung mit dem Identity Provider.
+identityProviderNotFoundMessage=Konnte kein Identity Provider mit der Identit�t [{0}] finden.
+realmSupportsNoCredentialsMessage=Realm [{0}] unterst�tzt keine Credential Typen.
+identityProviderNotUniqueMessage=Realm [{0}] unterst�tz mehrere Identity Providers.
+
+invalidParameterMessage=Invalid parameter\: {0}
+missingParameterMessage=Missing parameter\: {0}
+clientNotFoundMessage=Client not found.
+
+emailVerifiedMessage=Ihr E-Mail Adresse wurde erfolgreich verifiziert.
+
+locale_de=Deutsch
+locale_en=Englisch
+
+poweredByKeycloak=Powered by Keycloak
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
new file mode 100755
index 0000000..5ed7cec
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/messages/messages_en.properties
@@ -0,0 +1,152 @@
+doLogIn=Log in
+doRegister=Register
+doCancel=Cancel
+doSubmit=Submit
+doYes=Yes
+doNo=No
+doForgotPassword=Forgot Password?
+doClickHere=Click here
+
+registerWithTitle=Register with {0}
+registerWithTitleHtml=Register with <strong>{0}</strong>
+loginTitle=Log in to {0}
+loginTitleHtml=Log in to <strong>{0}</strong>
+loginOauthTitle=Temporary access for {0}
+loginOauthTitleHtml=Temporary access for <strong>{0}</strong> requested by <strong>{1}</strong>.
+loginTotpTitle=Mobile Authenticator Setup
+loginProfileTitle=Update Account Information
+oauthGrantTitle=OAuth Grant
+oauthGrantTitleHtml=Temporary access for <strong>{0}</strong> requested by <strong>{1}</strong>.
+errorTitle=We''re sorry...
+errorTitleHtml=We''re <strong>sorry</strong> ...
+emailVerifyTitle=Email verification
+emailForgotTitle=Forgot Your Password?
+updatePasswordTitle=Update password
+codeSuccessTitle=Success code
+codeErrorTitle=Error code\: {0}
+
+noAccount=New user?
+username=Username
+usernameOrEmail=Username or email
+firstName=First name
+fullName=Full name
+lastName=Last name
+email=Email
+password=Password
+passwordConfirm=Confirm password
+passwordNew=New Password
+passwordNewConfirm=New Password confirmation
+rememberMe=Remember me
+authenticatorCode=One-time code
+street=Street
+locality=City or Locality
+region=State, Province, or Region
+postal_code=Zip or Postal code
+country=Country
+
+loginTotpStep1=Install <a href="https://fedorahosted.org/freeotp/" target="_blank">FreeOTP</a> or <a href="http://code.google.com/p/google-authenticator/" target="_blank">Google Authenticator</a> on your mobile
+loginTotpStep2=Open the application and scan the barcode or enter the key
+loginTotpStep3=Enter the one-time code provided by the application and click Submit to finish the setup
+loginTotpOneTime=One-time code
+
+oauthGrantRequest=Do you grant these access privileges?
+inResource=in <strong>{0}</strong>
+
+emailVerifyInstruction1=An email with instructions to verify your email address has been sent to you.
+emailVerifyInstruction2=Haven''t received a verification code in your email?
+emailVerifyInstruction3=to re-send the email.
+
+backToLogin=&laquo; Back to Login
+
+emailInstruction=Enter your username or email address and we will send you instructions on how to create a new password.
+
+copyCodeInstruction=Please copy this code and paste it into your application:
+
+personalInfo=Personal Info:
+
+invalidUserMessage=Invalid username or password.
+invalidEmailMessage=Invalid email address.
+accountDisabledMessage=Account is disabled, contact admin.
+accountTemporarilyDisabledMessage=Account is temporarily disabled, contact admin or try again later.
+expiredCodeMessage=Login timeout. Please login again.
+
+missingFirstNameMessage=Please specify first name.
+missingLastNameMessage=Please specify last name.
+missingEmailMessage=Please specify email.
+missingUsernameMessage=Please specify username.
+missingPasswordMessage=Please specify password.
+missingTotpMessage=Please specify authenticator code.
+notMatchPasswordMessage=Passwords don''t match.
+
+invalidPasswordExistingMessage=Invalid existing password.
+invalidPasswordConfirmMessage=Password confirmation doesn''t match.
+invalidTotpMessage=Invalid authenticator code.
+
+usernameExistsMessage=Username already exists.
+emailExistsMessage=Email already exists.
+
+federatedIdentityEmailExistsMessage=User with email already exists. Please login to account management to link the account.
+federatedIdentityUsernameExistsMessage=User with username already exists. Please login to account management to link the account.
+
+configureTotpMessage=You need to set up Mobile Authenticator to activate your account.
+updateProfileMessage=You need to update your user profile to activate your account.
+updatePasswordMessage=You need to change your password to activate your account.
+verifyEmailMessage=You need to verify your email address to activate your account.
+
+emailSentMessage=You should receive an email shortly with further instructions.
+emailSendErrorMessage=Failed to send email, please try again later.
+
+accountUpdatedMessage=Your account has been updated.
+accountPasswordUpdatedMessage=Your password has been updated.
+
+noAccessMessage=No access
+
+invalidPasswordMinLengthMessage=Invalid password: minimum length {0}.
+invalidPasswordMinDigitsMessage=Invalid password: must contain at least {0} numerical digits.
+invalidPasswordMinLowerCaseCharsMessage=Invalid password: must contain at least {0} lower case characters.
+invalidPasswordMinUpperCaseCharsMessage=Invalid password: must contain at least {0} upper case characters.
+invalidPasswordMinSpecialCharsMessage=Invalid password: must contain at least {0} special characters.
+invalidPasswordNotUsernameMessage=Invalid password\: must not be equal to the username.
+
+failedToProcessResponseMessage=Failed to process response
+httpsRequiredMessage=HTTPS required
+realmNotEnabledMessage=Realm not enabled
+invalidRequestMessage=Invalid Request
+unknownLoginRequesterMessage=Unknown login requester
+loginRequesterNotEnabledMessage=Login requester not enabled
+bearerOnlyMessage=Bearer-only applications are not allowed to initiate browser login
+directGrantsOnlyMessage=Direct-grants-only clients are not allowed to initiate browser login
+invalidRedirectUriMessage=Invalid redirect uri
+unsupportedNameIdFormatMessage=Unsupported NameIDFormat
+invlidRequesterMessage=Invalid requester
+registrationNotAllowedMessage=Registration not allowed
+
+permissionNotApprovedMessage=Permission not approved.
+noRelayStateInResponseMessage=No relay state in response from identity provider [{0}].
+identityProviderAlreadyLinkedMessage=The identity returned by the identity provider [{0}] is already linked to another user.
+insufficientPermissionMessage=Insufficient permissions to link identities.
+couldNotProceedWithAuthenticationRequestMessage=Could not proceed with authentication request to identity provider.
+couldNotObtainTokenMessage=Could not obtain token from identity provider [{0}].
+unexpectedErrorRetrievingTokenMessage=Unexpected error when retrieving token from identity provider [{0}].
+unexpectedErrorHandlingResponseMessage=Unexpected error when handling response from identity provider [{0}].
+identityProviderAuthenticationFailedMessage=Authentication failed. Could not authenticate with identity provider [{0}].
+couldNotSendAuthenticationRequestMessage=Could not send authentication request to identity provider [{0}].
+unexpectedErrorHandlingRequestMessage=Unexpected error when handling authentication request to identity provider [{0}].
+invalidAccessCodeMessage=Invalid access code.
+sessionNotActiveMessage=Session not active.
+unknownCodeMessage=Unknown code, please login again through your application.
+invalidCodeMessage=Invalid code, please login again through your application.
+identityProviderUnexpectedErrorMessage=Unexpected error when authenticating with identity provider
+identityProviderNotFoundMessage=Could not find an identity provider with the identifier [{0}].
+realmSupportsNoCredentialsMessage=Realm [{0}] does not support any credential type.
+identityProviderNotUniqueMessage=Realm [{0}] supports multiple identity providers. Could not determine which identity provider should be used to authenticate with.
+emailVerifiedMessage=Your email address has been verified.
+
+locale_de=German
+locale_en=English
+
+poweredByKeycloak=Powered by Keycloak
+backToApplication=&laquo; Back to Application
+missingParameterMessage=Missing parameters\: {0}
+clientNotFoundMessage=Client not found.
+invalidParameterMessage=Invalid parameter\: {0}
diff --git a/forms/common-themes/src/main/resources/theme/base/login/register.ftl b/forms/common-themes/src/main/resources/theme/base/login/register.ftl
new file mode 100755
index 0000000..930a07d
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/register.ftl
@@ -0,0 +1,124 @@
+<#import "template.ftl" as layout>
+<@layout.registrationLayout; section>
+    <#if section = "title">
+        ${msg("registerWithTitle",(realm.name!''))}
+    <#elseif section = "header">
+         ${msg("registerWithTitleHtml",(realm.name!''))}
+    <#elseif section = "form">
+        <form id="kc-register-form" class="${properties.kcFormClass!}" action="${url.registrationAction}" method="post">
+          <#if !realm.registrationEmailAsUsername>
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="username" class="${properties.kcLabelClass!}">${msg("username")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="username" class="${properties.kcInputClass!}" name="username" value="${(register.formData.username!'')?html}" />
+                </div>
+            </div>
+          </#if>
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="firstName" class="${properties.kcLabelClass!}">${msg("firstName")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="firstName" class="${properties.kcInputClass!}" name="firstName" value="${(register.formData.firstName!'')?html}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="lastName" class="${properties.kcLabelClass!}">${msg("lastName")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="lastName" class="${properties.kcInputClass!}" name="lastName" value="${(register.formData.lastName!'')?html}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="email" class="${properties.kcLabelClass!}">${msg("email")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" id="email" class="${properties.kcInputClass!}" name="email" value="${(register.formData.email!'')?html}" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="password" class="${properties.kcLabelClass!}">${msg("password")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="password" id="password" class="${properties.kcInputClass!}" name="password" />
+                </div>
+            </div>
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="password-confirm" class="${properties.kcLabelClass!}">${msg("passwordConfirm")}</label>
+                </div>
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="password" id="password-confirm" class="${properties.kcInputClass!}" name="password-confirm" />
+                </div>
+            </div>
+
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.street" class="${properties.kcLabelClass!}">${msg("street")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.street" name="user.attributes.street"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.locality" class="${properties.kcLabelClass!}">${msg("locality")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.locality" name="user.attributes.locality"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.region" class="${properties.kcLabelClass!}">${msg("region")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.region" name="user.attributes.region"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.postal_code" class="${properties.kcLabelClass!}">${msg("postal_code")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.postal_code" name="user.attributes.postal_code"/>
+                </div>
+            </div>
+            <div class="form-group">
+                <div class="${properties.kcLabelWrapperClass!}">
+                    <label for="user.attributes.country" class="${properties.kcLabelClass!}">${msg("country")}</label>
+                </div>
+
+                <div class="${properties.kcInputWrapperClass!}">
+                    <input type="text" class="${properties.kcInputClass!}"  id="user.attributes.country" name="user.attributes.country"/>
+                </div>
+            </div>
+
+
+            <div class="${properties.kcFormGroupClass!}">
+                <div id="kc-form-options" class="${properties.kcFormOptionsClass!}">
+                    <div class="${properties.kcFormOptionsWrapperClass!}">
+                        <span><a href="${url.loginUrl}">${msg("backToLogin")}</a></span>
+                    </div>
+                </div>
+
+                <div id="kc-form-buttons" class="${properties.kcFormButtonsClass!}">
+                    <input class="btn btn-primary btn-lg" type="submit" value="${msg("doRegister")}"/>
+                </div>
+            </div>
+        </form>
+    </#if>
+</@layout.registrationLayout>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/login/template.ftl b/forms/common-themes/src/main/resources/theme/base/login/template.ftl
new file mode 100644
index 0000000..907cfd5
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/login/template.ftl
@@ -0,0 +1,91 @@
+<#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" class="${properties.kcHtmlClass!}">
+
+<head>
+    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+    <#if properties.meta?has_content>
+        <#list properties.meta?split(' ') as meta>
+            <meta name="${meta?split('==')[0]}" content="${meta?split('==')[1]}"/>
+        </#list>
+    </#if>
+    <title><#nested "title"></title>
+    <link rel="icon" href="${url.resourcesPath}/img/favicon.ico" />
+    <#if properties.styles?has_content>
+        <#list properties.styles?split(' ') as style>
+            <link href="${url.resourcesPath}/${style}" rel="stylesheet" />
+        </#list>
+    </#if>
+    <#if properties.scripts?has_content>
+        <#list properties.scripts?split(' ') as script>
+            <script src="${url.resourcesPath}/${script}" type="text/javascript"></script>
+        </#list>
+    </#if>
+</head>
+
+<body class="${properties.kcBodyClass!}">
+    <div id="kc-logo"><div id="kc-logo-wrapper"></div></div>
+
+    <div id="kc-container" class="${properties.kcContainerClass!}">
+        <div id="kc-container-wrapper" class="${properties.kcContainerWrapperClass!}">
+
+            <div id="kc-header" class="${properties.kcHeaderClass!}">
+                <div id="kc-header-wrapper" class="${properties.kcHeaderWrapperClass!}"><#nested "header"></div>
+            </div>
+
+            <#if displayMessage && message?has_content>
+                <div id="kc-feedback" class="feedback-${message.type} ${properties.kcFeedBackClass!}">
+                    <div id="kc-feedback-wrapper">
+                        <span class="kc-feedback-text">${message.summary}</span>
+                    </div>
+                </div>
+            <#else>
+                <div id="kc-feedback-placeholder" class="${properties.kcFeedBackPlaceholderClass!}">
+                    <div id="kc-feedback-placeholder-wrapper"></div>
+                </div>
+            </#if>
+
+            <#if realm.internationalizationEnabled>
+                <div id="kc-locale" class="${properties.kcLocaleClass!}">
+                    <div id="kc-locale-wrapper" class="${properties.kcLocaleWrapperClass!}">
+                        <div class="kc-dropdown">
+                            <a href="#">${locale.current}</a>
+                            <ul>
+                                <#list locale.supported as l>
+                                    <li class="kc-dropdown-item"><a href="${l.url}">${l.label}</a></li>
+                                </#list>
+                            </ul>
+                        </div>
+                    </div>
+                </div>
+            </#if>
+
+            <div id="kc-content" class="${properties.kcContentClass!}">
+                <div id="kc-content-wrapper" class="${properties.kcContentWrapperClass!}">
+                    <div id="kc-form" class="${properties.kcFormAreaClass!}">
+                        <div id="kc-form-wrapper" class="${properties.kcFormAreaWrapperClass!}">
+                            <#nested "form">
+                        </div>
+                    </div>
+
+                    <#if displayInfo>
+                        <div id="kc-info" class="${properties.kcInfoAreaClass!}">
+                            <div id="kc-info-wrapper" class="${properties.kcInfoAreaWrapperClass!}">
+                                <#nested "info">
+                            </div>
+                        </div>
+                    </#if>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!--
+        <p class="powered">
+            <a href="http://www.keycloak.org">${msg("poweredByKeycloak")}</a>
+        </p>
+    </div>
+    -->
+</body>
+</html>
+</#macro>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/email-verification.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/email-verification.ftl
new file mode 100644
index 0000000..5f2490b
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/email-verification.ftl
@@ -0,0 +1 @@
+${msg("emailVerificationBody",link, linkExpiration)}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-login_error.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/event-login_error.ftl
new file mode 100644
index 0000000..7835c91
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/event-login_error.ftl
@@ -0,0 +1 @@
+${msg("eventLoginErrorBody",event.date,event.ipAddress)}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-remove_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/event-remove_totp.ftl
new file mode 100644
index 0000000..8930b64
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/event-remove_totp.ftl
@@ -0,0 +1 @@
+${msg("eventRemoveTotpBody",event.date, event.ipAddress)}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_password.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_password.ftl
new file mode 100644
index 0000000..754daac
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_password.ftl
@@ -0,0 +1 @@
+${msg("eventUpdatePasswordBody",event.date, event.ipAddress)}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_totp.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_totp.ftl
new file mode 100644
index 0000000..3a7b0f7
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/event-update_totp.ftl
@@ -0,0 +1 @@
+${msg("eventUpdateTotpBody",event.date, event.ipAddress)}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
new file mode 100644
index 0000000..60228c3
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_de.properties
@@ -0,0 +1,12 @@
+emailVerificationSubject=E-Mail verifizieren
+passwordResetSubject=Passwort zur�ckzusetzen
+passwordResetBody=Jemand hat angefordert Ihr Keycloak Passwort zur�ckzusetzen. Falls das Sie waren, dann klicken Sie auf den folgenden Link um das Passwort zur�ckzusetzen.\n\n{0}\n\nDieser Link wird in {1} Minuten ablaufen.\n\nFalls Sie das Passwort nicht zur�cksetzen m�chten, dann k�nnen Sie diese E-Mail ignorieren.
+emailVerificationBody=Jemand hat ein Keycloak Konto mit dieser E-Mail Adresse erstellt. Fall das Sie waren, dann klicken Sie auf den Link um die E-Mail Adresse zu verifizieren.\n\n{0}\n\nDieser Link wird in {1} Minuten ablaufen.\n\nFalls Sie dieses Konto nicht erstellt haben, dann k�nnen sie diese Nachricht ignorieren.
+eventLoginErrorSubject=Fehlgeschlagene Anmeldung
+eventLoginErrorBody=Jemand hat um {0} von {1} versucht sich mit ihrem Konto anzumelden. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventRemoveTotpSubject=TOTP Entfernt
+eventRemoveTotpBody=TOTP wurde von ihrem Konto am {0} von {1} entfernt. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventUpdatePasswordSubject=Passwort Aktualisiert
+eventUpdatePasswordBody=Ihr Passwort wurde am {0} von {1} ge�ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
+eventUpdateTotpSubject=TOTP Aktualisiert
+eventUpdateTotpBody=TOTP wurde am {0} von {1} ge�ndert. Falls das nicht Sie waren, dann kontaktieren Sie bitte Ihren Admin.
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
new file mode 100755
index 0000000..c23daf6
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/messages/messages_en.properties
@@ -0,0 +1,12 @@
+emailVerificationSubject=Verify email
+emailVerificationBody=Someone has created a Keycloak account with this email address. If this was you, click the link below to verify your email address\n\n{0}\n\nThis link will expire within {1} minutes.\n\nIf you didn''t create this account, just ignore this message.
+passwordResetSubject=Reset password
+passwordResetBody=Someone just requested to change your Keycloak account''s password. If this was you, click on the link below to set a new password\n\n{0}\n\nThis link will expire within {1} minutes.\n\nIf you don''t want to reset your password, just ignore this message and nothing will be changed.
+eventLoginErrorSubject=Login error
+eventLoginErrorBody=A failed login attempt was dettected to your account on {0} from {1}. If this was not you, please contact an admin.
+eventRemoveTotpSubject=Remove TOTP
+eventRemoveTotpBody=TOTP was removed from your account on {0} from {1}. If this was not you, please contact an admin.
+eventUpdatePasswordSubject=Update password
+eventUpdatePasswordBody=Your password was changed on {0} from {1}. If this was not you, please contact an admin.
+eventUpdateTotpSubject=Update TOTP
+eventUpdateTotpBody=TOTP was updated for your account on {0} from {1}. If this was not you, please contact an admin.
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/email/password-reset.ftl b/forms/common-themes/src/main/resources/theme/keycloak/email/password-reset.ftl
new file mode 100644
index 0000000..d7150d6
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/email/password-reset.ftl
@@ -0,0 +1 @@
+${msg("passwordResetBody",link, linkExpiration)}
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/index.html b/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/index.html
new file mode 100755
index 0000000..dd0b909
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/index.html
@@ -0,0 +1,50 @@
+<!--
+  ~ 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>
+    <link rel="shortcut icon" href="welcome-content/favicon.ico" type="image/x-icon">
+    <link rel="StyleSheet" href="welcome-content/keycloak.css" type="text/css">
+</head>
+
+<body>
+<div class="wrapper">
+    <div class="content">
+        <div class="logo">
+                <img src="welcome-content/keycloak_logo.png" alt="Keycloak" border="0" />
+        </div>
+        <h1>Welcome to Keycloak</h1>
+
+        <h3>Your Keycloak is running.</h3>
+
+        <p><a href="http://www.keycloak.org/docs">Documentation</a> | <a href="admin/">Administration Console</a> </p>
+
+        <p><a href="http://www.keycloak.org">Keycloak Project</a> |
+            <a href="https://lists.jboss.org/mailman/listinfo/keycloak-user">Mailing List</a> |
+            <a href="https://issues.jboss.org/browse/KEYCLOAK">Report an issue</a></p>
+        <p class="logos"><a href="http://www.jboss.org"><img src="welcome-content/jboss_community.png" alt="JBoss and JBoss Community" width="254" height="31" border="0"></a></p>
+    </div>
+</div>
+</body>
+</html>
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/jboss_community.png b/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/jboss_community.png
new file mode 100644
index 0000000..946e8f9
Binary files /dev/null and b/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/jboss_community.png differ
diff --git a/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/keycloak.css b/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/keycloak.css
new file mode 100644
index 0000000..5152862
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/keycloak/welcome/resources/keycloak.css
@@ -0,0 +1,65 @@
+/*
+  ~ 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.
+*/
+
+body {
+	/*background: url(bkg.gif) repeat-x;*/
+	color: #5B5B5B;
+	font-family: "Lucida Sans Unicode", "Lucida Grande", Geneva, Verdana, Arial, sans-serif;
+	margin-top: 100px;
+	text-align: center;
+}
+.wrapper {
+	margin-left: auto;
+	margin-right: auto;
+	width: 50em;
+	text-align: left;
+}
+a {
+	text-decoration: none;
+	color: #5e8a9a;
+}
+h1 {
+	padding-top: 20px;
+	color: #7b1e1e;
+}
+a:hover {
+	text-decoration: underline;
+	color: #8ec6d9;
+}
+.content {
+    margin: 0;
+    padding: 0;
+}
+.dualbrand {
+	padding-top: 20px;
+}
+.wildfly {
+	float:left;
+	margin-left: 10px;
+}
+.logo{
+    margin-bottom: 10px;
+}
+.note {
+	font-size: 8pt;
+	color: #aaaaaa;
+}
diff --git a/forms/common-themes/src/main/resources/theme/patternfly/account/resources/img/favicon.ico b/forms/common-themes/src/main/resources/theme/patternfly/account/resources/img/favicon.ico
new file mode 100644
index 0000000..b30dce5
Binary files /dev/null and b/forms/common-themes/src/main/resources/theme/patternfly/account/resources/img/favicon.ico differ
diff --git a/forms/common-themes/src/main/resources/theme/patternfly/login/resources/css/login.css b/forms/common-themes/src/main/resources/theme/patternfly/login/resources/css/login.css
new file mode 100644
index 0000000..345f594
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/patternfly/login/resources/css/login.css
@@ -0,0 +1,322 @@
+.kc-dropdown{
+    position: relative;
+}
+.kc-dropdown > a{
+    position: absolute;
+    right: 0px;
+    display:block;
+    padding: 11px 10px 12px;
+    line-height: 12px;
+    font-size: 12px;
+    color: #fff !important;
+    text-decoration: none;
+}
+.kc-dropdown > a::after{
+    content: "\2c5";
+    margin-left: 4px;
+}
+.kc-dropdown:hover > a{
+    background-color: rgba(0,0,0,0.2);
+}
+.kc-dropdown ul li a{
+    padding: 1px 11px;
+    font-size: 12px;
+    color: #000 !important;
+    border: 1px solid #fff;
+    text-decoration: none;
+    display:block;
+    line-height: 20px;
+}
+.kc-dropdown ul li a:hover{
+    color: #4d5258;
+    background-color: #d4edfa;
+    border-color: #b3d3e7;
+}
+.kc-dropdown ul{
+    position: absolute;
+    right: 0px;
+    top: 35px;
+    z-index: 2000;
+    list-style:none;
+    display:none;
+    padding: 5px 0px;
+    margin: 0px;
+    background-color: #fff !important;
+    border: 1px solid #b6b6b6;
+    border-radius: 1px;
+    -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+    box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+    background-clip: padding-box;
+    min-width: 100px;
+}
+.kc-dropdown:hover ul{
+    display:block;
+}
+
+.login-pf .container {
+    padding-top: 40px;
+}
+
+.login-pf a:hover {
+    color: #0099d3;
+}
+
+#kc-logo {
+    width: 100%;
+}
+
+#kc-logo-wrapper {
+    background-image: url("../img/keycloak-logo.png");
+    background-repeat: no-repeat;
+    background-position: top right;
+
+    height: 37px;
+
+    margin: 50px;
+}
+
+#kc-header {
+    overflow: visible;
+    padding-left: 80px;
+    white-space: nowrap;
+}
+
+#kc-header-wrapper {
+    font-size: 26px;
+    text-transform: uppercase;
+    line-height: 1.2em;
+    margin-bottom: 15px;
+}
+
+#kc-container-wrapper {
+    bottom: 13%;
+    position: absolute;
+    width: 100%;
+}
+
+#kc-content {
+    position: relative;
+}
+
+#kc-content-wrapper {
+    overflow-y: hidden;
+}
+
+#kc-info {
+    padding-bottom: 200px;
+    margin-bottom: -200px;
+}
+
+#kc-info-wrapper {
+    font-size: 13px;
+}
+
+#kc-form-options span {
+    display: block;
+}
+
+#kc-login {
+    float: right;
+    margin-left: 10px;
+}
+
+#kc-feedback-wrapper {
+    display: inline-block;
+    width: auto;
+    background-position: left bottom;
+    background-repeat: no-repeat;
+    padding-bottom: 10px;
+}
+
+#kc-feedback span {
+    display: block;
+    padding: 0.90909090909091em 3.63636363636364em;
+    border-style: solid;
+    border-width: 1px 1px 0px 1px;
+    background-repeat: no-repeat;
+    background-position: 1.27272727272727em center;
+    font-weight: normal;
+    line-height: 1.4em;
+    border-radius: 2px;
+    color: #4d5258;
+    margin-bottom: 0;
+}
+
+.feedback-error #kc-feedback-wrapper {
+    background-image: url(../img/feedback-error-arrow-down.png);
+}
+.feedback-error span {
+    border-color: #b91415;
+    background-image: url(../img/feedback-error-sign.png);
+    background-color: #f8e7e7;
+}
+
+.feedback-success #kc-feedback-wrapper {
+    background-image: url(../img/feedback-success-arrow-down.png);
+}
+.feedback-success span {
+    border-color: #4b9e39;
+    background-image: url(../img/feedback-success-sign.png);
+    background-color: #e4f1e1;
+}
+
+.feedback-warning #kc-feedback-wrapper {
+    background-image: url(../img/feedback-warning-arrow-down.png);
+}
+.feedback-warning span {
+    border-color: #f17528;
+    background-image: url(../img/feedback-warning-sign.png);
+    background-color: #fef1e9;
+}
+
+#kc-registration {
+    margin-bottom: 15px;
+}
+
+/* TOTP */
+
+ol#kc-totp-settings {
+    margin: 0;
+    padding: 0;
+}
+
+ol#kc-totp-settings li {
+    margin-top: 1em;
+}
+
+ol#kc-totp-settings li:first-of-type {
+    margin-top: 0;
+}
+
+/* OAuth */
+
+#kc-oauth h3 {
+    margin-top: 0;
+}
+
+#kc-oauth ul {
+    list-style: none;
+    padding: 0;
+    margin: 0;
+}
+
+#kc-oauth ul li {
+    border-top: 1px solid rgba(255, 255, 255, 0.1);
+    font-size: 12px;
+    padding: 10px 30px;
+}
+
+#kc-oauth ul li:first-of-type {
+    border-top: 0;
+}
+
+#kc-oauth .kc-role {
+    display: inline-block;
+    width: 50%;
+}
+
+/* Code */
+#kc-code textarea {
+    width: 100%;
+    height: 8em;
+}
+
+/* Social */
+
+#kc-social-providers ul {
+    padding: 0;
+    margin: 0;
+}
+
+#kc-social-providers li {
+    display: block;
+    margin-top: 5px;
+}
+
+#kc-social-providers li:first-of-type {
+    margin-top: 0;
+}
+
+.zocial {
+    width: 125px;
+}
+
+.zocial:hover {
+    color: #fff !important;
+}
+
+.zocial.facebook,
+.zocial.github,
+.zocial.google,
+.zocial.twitter {
+    background-image: none;
+    border-radius: 2px;
+
+    font-family: "Open Sans", sans-serif;
+    font-weight: normal;
+
+    box-shadow: none;
+    text-shadow: none;
+}
+
+.zocial.google {
+    background-color: #dd4b39 !important;
+}
+.zocial.google .text:after {
+    content: "+";
+}
+
+.zocial.facebook:hover,
+.zocial.github:hover,
+.zocial.google:hover,
+.zocial.twitter:hover {
+    background-image: linear-gradient(rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0.2) 100%) !important;
+}
+
+@media (max-width: 767px) {
+    #kc-logo-wrapper {
+        margin-top: 30px;
+        margin-right: 15px;
+    }
+
+    #kc-header {
+        padding-left: 15px;
+        padding-right: 15px;
+        float: none;
+    }
+
+    #kc-feedback {
+        padding-left: 15px;
+        padding-right: 15px;
+        float: none;
+    }
+
+    #kc-form {
+        float: none;
+    }
+
+    #kc-info-wrapper {
+        border-top: 1px solid rgba(255, 255, 255, 0.1);
+        margin-top: 15px;
+        padding-top: 15px;
+        padding-left: 0px;
+        padding-right: 15px;
+    }
+
+    #kc-social-providers li {
+        display: inline-block;
+        margin-right: 5px;
+    }
+
+    .login-pf .container {
+        padding-top: 15px;
+        padding-bottom: 15px;
+    }
+}
+
+@media (max-height: 500px) {
+    #kc-container-wrapper {
+        position: inherit;
+        float: none;
+    }
+}
diff --git a/forms/common-themes/src/main/resources/theme/patternfly/login/resources/img/favicon.ico b/forms/common-themes/src/main/resources/theme/patternfly/login/resources/img/favicon.ico
new file mode 100644
index 0000000..b30dce5
Binary files /dev/null and b/forms/common-themes/src/main/resources/theme/patternfly/login/resources/img/favicon.ico differ
diff --git a/forms/common-themes/src/main/resources/theme/patternfly/login/resources/img/keycloak-logo.png b/forms/common-themes/src/main/resources/theme/patternfly/login/resources/img/keycloak-logo.png
new file mode 100644
index 0000000..9555748
Binary files /dev/null and b/forms/common-themes/src/main/resources/theme/patternfly/login/resources/img/keycloak-logo.png differ
diff --git a/forms/common-themes/src/main/resources/theme/patternfly/login/theme.properties b/forms/common-themes/src/main/resources/theme/patternfly/login/theme.properties
new file mode 100644
index 0000000..25427a7
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/patternfly/login/theme.properties
@@ -0,0 +1,29 @@
+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
+
+kcHtmlClass=login-pf
+
+kcContentClass=col-sm-12 col-md-12 col-lg-12 container
+kcContentWrapperClass=row
+
+kcHeaderClass=col-xs-12 col-sm-7 col-md-6 col-lg-5
+kcFeedBackClass=col-xs-12 col-sm-4 col-md-5 col-lg-6
+kcFeedBackPlaceholderClass=col-xs-12 col-sm-4 col-md-5 col-lg-6
+kcLocaleClass=col-xs-12 col-sm-1
+
+kcFormAreaClass=col-xs-12 col-sm-8 col-md-8 col-lg-6 login
+
+kcFormClass=form-horizontal
+kcFormGroupClass=form-group
+kcLabelClass=control-label
+kcLabelWrapperClass=col-xs-12 col-sm-12 col-md-4 col-lg-3
+kcInputClass=form-control
+kcInputWrapperClass=col-xs-12 col-sm-12 col-md-8 col-lg-9
+kcFormOptionsClass=col-xs-4 col-sm-5 col-md-offset-4 col-md-4 col-lg-offset-3 col-lg-5
+kcFormButtonsClass=col-xs-8 col-sm-7 col-md-4 col-lg-4 submit
+kcTextareaClass=form-control
+
+kcInfoAreaClass=col-xs-12 col-sm-4 col-md-4 col-lg-6 details
\ No newline at end of file
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/account/resources/img/logo.png b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/account/resources/img/logo.png
new file mode 100755
index 0000000..d55812d
Binary files /dev/null and b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/account/resources/img/logo.png differ
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/resources/css/styles.css b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/resources/css/styles.css
new file mode 100755
index 0000000..84300fe
--- /dev/null
+++ b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/resources/css/styles.css
@@ -0,0 +1,45 @@
+@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);
+}
+
+/* this is what I added */
+
+.navbar-title {
+    background-image: url('../img/logo.png');
+    height: 65px;
+    background-repeat: no-repeat;
+    width: 203px;
+    margin: 3px 10px 5px;
+    text-indent: -99999px;
+}
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/resources/img/logo.png b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/resources/img/logo.png
new file mode 100755
index 0000000..d55812d
Binary files /dev/null and b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/resources/img/logo.png differ
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/theme.properties b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/theme.properties
new file mode 100755
index 0000000..e328b3f
--- /dev/null
+++ b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/admin/theme.properties
@@ -0,0 +1,4 @@
+parent=keycloak
+import=common/keycloak
+
+styles= ../keycloak/css/styles.css css/styles.css
\ No newline at end of file
diff --git a/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/login/resources/img/logo.png b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/login/resources/img/logo.png
new file mode 100755
index 0000000..d55812d
Binary files /dev/null and b/project-integrations/aerogear-ups/auth-server/src/main/resources/theme/aerogear/login/resources/img/logo.png differ
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 73c78e0..79b36de 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -47,7 +47,6 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Properties;
-import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -292,7 +291,7 @@ public class KeycloakServer {
         di.setDeploymentName("Keycloak");
 
         di.setDefaultServletConfig(new DefaultServletConfig(true));
-        di.addWelcomePage("theme/welcome/keycloak/resources/index.html");
+        di.addWelcomePage("theme/keycloak/welcome/resources/index.html");
 
         FilterInfo filter = Servlets.filter("SessionFilter", KeycloakSessionServletFilter.class);
         di.addFilter(filter);