keycloak-memoizeit

Details

diff --git a/sdk-html/src/main/java/org/keycloak/sdk/LoginBean.java b/sdk-html/src/main/java/org/keycloak/sdk/LoginBean.java
index b070e12..a5f3dc8 100644
--- a/sdk-html/src/main/java/org/keycloak/sdk/LoginBean.java
+++ b/sdk-html/src/main/java/org/keycloak/sdk/LoginBean.java
@@ -1,11 +1,14 @@
 package org.keycloak.sdk;
 
 import java.net.URI;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import javax.annotation.PostConstruct;
+import javax.faces.application.FacesMessage;
 import javax.faces.bean.ManagedBean;
 import javax.faces.bean.RequestScoped;
 import javax.faces.context.FacesContext;
@@ -19,129 +22,174 @@ import org.keycloak.services.models.RequiredCredentialModel;
 @RequestScoped
 public class LoginBean {
 
-    private String style = "saas";
-
-    private String clientId;
-
-    private String scope;
-
-    private String state;
-
-    private String redirectUri;
+    private RealmModel realm;
 
     private String loginAction;
 
     private String socialLoginUrl;
 
-    private String themeUrl;
+    private String username;
+
+    private List<RequiredCredential> requiredCredentials;
+
+    private List<Property> hiddenProperties;
 
     private List<SocialProvider> providers;
-    
-    private List<RequiredCredential> requiredCredentials; 
 
-    private RealmModel realm;
+    private String theme = "saas";
 
-    private String username;
+    private String themeUrl;
 
-    private String baseUrl;
+    private Map<String, Object> themeConfig;
 
     @PostConstruct
     public void init() {
-        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
+        FacesContext ctx = FacesContext.getCurrentInstance();
 
-        realm = (RealmModel) request.getAttribute(RealmModel.class.getName());
+        HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
 
-        clientId = (String) request.getAttribute("client_id");
-        scope = (String) request.getAttribute("scope");
-        state = (String) request.getAttribute("state");
-        redirectUri = (String) request.getAttribute("redirect_uri");
+        realm = (RealmModel) request.getAttribute(RealmModel.class.getName());
 
         loginAction = ((URI) request.getAttribute("KEYCLOAK_LOGIN_ACTION")).toString();
-
         socialLoginUrl = ((URI) request.getAttribute("KEYCLOAK_SOCIAL_LOGIN")).toString();
 
         username = (String) request.getAttribute("username");
 
-        providers = new LinkedList<SocialProvider>();
-        for (Iterator<org.keycloak.social.SocialProvider> itr = ServiceRegistry
-                .lookupProviders(org.keycloak.social.SocialProvider.class); itr.hasNext();) {
-            org.keycloak.social.SocialProvider p = itr.next();
-            providers.add(new SocialProvider(p.getId(), p.getName()));
+        if (request.getAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE") != null) {
+            FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
+                    (String) request.getAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE"), null);
+            ctx.addMessage(null, message);
         }
 
-        requiredCredentials = new LinkedList<RequiredCredential>();
-        for (RequiredCredentialModel m : realm.getRequiredCredentials()) {
-            if (m.isInput()) {
-                requiredCredentials.add(new RequiredCredential(m.getType(), m.isSecret()));
-            }
-        }
+        addRequiredCredentials();
+        addHiddenProperties(request, "client_id", "scope", "state", "redirect_uri");
+        addSocialProviders();
 
-        baseUrl = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath() + "/sdk";
-        themeUrl = baseUrl + "/theme/" + style;
+        // TODO Get theme name from realm
+        theme = "saas";
+        themeUrl = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath() + "/sdk/theme/" + theme;
 
-    }
+        themeConfig = new HashMap<String, Object>();
 
-    public List<RequiredCredential> getRequiredCredentials() {
-        return requiredCredentials;
+        themeConfig.put("styles", themeUrl + "/styles.css");
+
+        if (RealmModel.DEFAULT_REALM.equals(realm.getName())) {
+            themeConfig.put("logo", themeUrl + "/img/red-hat-logo.png");
+            themeConfig.put("background", themeUrl + "/img/login-screen-background.jpg");
+        } else {
+            themeConfig.put("background", themeUrl + "/img/customer-login-screen-bg2.jpg");
+            themeConfig.put("displayPoweredBy", true);
+        }
     }
 
-    public String getStylesheet() {
-        return themeUrl + "/styles.css";
+    public Map<String, Object> getThemeConfig() {
+        return themeConfig;
     }
 
-    public String getLoginTemplate() {
-        return "theme/" + style + "/login.xhtml";
+    public String getName() {
+        return realm.getName();
     }
 
     public String getLoginAction() {
         return loginAction;
     }
 
-    public String getStyle() {
-        return style;
+    public List<Property> getHiddenProperties() {
+        return hiddenProperties;
     }
 
-    public String getName() {
-        return realm.getName();
+    public List<RequiredCredential> getRequiredCredentials() {
+        return requiredCredentials;
     }
 
-    public String getClientId() {
-        return clientId;
+    public String getTheme() {
+        return theme;
     }
 
-    public String getScope() {
-        return scope;
+    public String getThemeUrl() {
+        return themeUrl;
     }
 
-    public String getState() {
-        return state;
+    public String getUsername() {
+        return username;
     }
 
-    public String getRedirectUri() {
-        return redirectUri;
+    public boolean isSocial() {
+        // TODO Check if social is enabled in realm
+        return true && providers.size() > 0;
     }
 
-    public String getUsername() {
-        return username;
+    public boolean isRegistrationAllowed() {
+        return realm.isRegistrationAllowed();
     }
 
-    public String getThemeUrl() {
-        return themeUrl;
+    private void addHiddenProperties(HttpServletRequest request, String... names) {
+        hiddenProperties = new LinkedList<Property>();
+        for (String name : names) {
+            Object v = request.getAttribute(name);
+            if (v != null) {
+                hiddenProperties.add(new Property(name, (String) v));
+            }
+        }
     }
 
-    public String socialLoginUrl(String id) {
-        StringBuilder sb = new StringBuilder();
-        sb.append(socialLoginUrl);
-        sb.append("?provider_id=" + id);
-        sb.append("&client_id=" + clientId);
-        if (scope != null) {
-            sb.append("&scope=" + scope);
+    private void addRequiredCredentials() {
+        requiredCredentials = new LinkedList<RequiredCredential>();
+        for (RequiredCredentialModel m : realm.getRequiredCredentials()) {
+            if (m.isInput()) {
+                requiredCredentials.add(new RequiredCredential(m.getType(), m.isSecret()));
+            }
         }
-        if (state != null) {
-            sb.append("&state=" + state);
+    }
+
+    private void addSocialProviders() {
+        // TODO Add providers configured for realm instead of all providers
+        providers = new LinkedList<SocialProvider>();
+        for (Iterator<org.keycloak.social.SocialProvider> itr = ServiceRegistry
+                .lookupProviders(org.keycloak.social.SocialProvider.class); itr.hasNext();) {
+            org.keycloak.social.SocialProvider p = itr.next();
+            providers.add(new SocialProvider(p.getId(), p.getName()));
+        }
+    }
+
+    public class Property {
+        private String name;
+        private String value;
+
+        public Property(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public String getValue() {
+            return value;
+        }
+    }
+
+    public class RequiredCredential {
+        private String type;
+        private boolean secret;
+
+        public RequiredCredential(String type, boolean secure) {
+            this.type = type;
+            this.secret = secure;
+        }
+
+        public String getName() {
+            return type;
+        }
+
+        public String getLabel() {
+            return type;
+        }
+
+        public String getInputType() {
+            return secret ? "password" : "text";
         }
-        sb.append("&redirect_uri=" + redirectUri);
-        return sb.toString();
     }
 
     public List<SocialProvider> getProviders() {
@@ -169,38 +217,11 @@ public class LoginBean {
             StringBuilder sb = new StringBuilder();
             sb.append(socialLoginUrl);
             sb.append("?provider_id=" + id);
-            sb.append("&client_id=" + clientId);
-            if (scope != null) {
-                sb.append("&scope=" + scope);
-            }
-            if (state != null) {
-                sb.append("&state=" + state);
+            for (Property p : hiddenProperties) {
+                sb.append("&" + p.getName() + "=" + p.getValue());
             }
-            sb.append("&redirect_uri=" + redirectUri);
             return sb.toString();
         }
-
-        public String getIconUrl() {
-            return themeUrl + "/icons/" + id + ".png";
-        }
-    }
-    
-    public class RequiredCredential {
-        private String type;
-        private boolean secret;
-
-        public RequiredCredential(String type, boolean secure) {
-            this.type = type;
-            this.secret = secure;
-        }
-
-        public String getType() {
-            return type;
-        }
-
-        public boolean isSecret() {
-            return secret;
-        }
     }
 
 }
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/login.xhtml b/sdk-html/src/main/resources/META-INF/resources/sdk/login.xhtml
index 317157d..c283e9a 100644
--- a/sdk-html/src/main/resources/META-INF/resources/sdk/login.xhtml
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/login.xhtml
@@ -1,13 +1 @@
-<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
-	xmlns:ui="http://java.sun.com/jsf/facelets">
-<h:head>
-	<meta charset="utf-8"></meta>
-	<title>Log in to #{login.name}</title>
-	<link href="#{login.stylesheet}" rel="stylesheet" />
-</h:head>
-
-<h:body class="rcue-login-register">
-	<ui:include src="#{login.loginTemplate}" />
-</h:body>
-
-</html>
\ No newline at end of file
+<ui:include xmlns:ui="http://java.sun.com/jsf/facelets" src="theme/#{login.theme}/login.xhtml" />
\ No newline at end of file
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/register.xhtml b/sdk-html/src/main/resources/META-INF/resources/sdk/register.xhtml
new file mode 100644
index 0000000..f25d7ea
--- /dev/null
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/register.xhtml
@@ -0,0 +1,13 @@
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
+	xmlns:ui="http://java.sun.com/jsf/facelets">
+<h:head>
+	<meta charset="utf-8"></meta>
+	<title>Register with #{register.name}</title>
+	<link href="#{register.themeUrl}/styles.css" rel="stylesheet" />
+</h:head>
+
+<h:body class="keycloak-register">
+	<ui:include src="theme/#{register.theme}/register.xhtml" />
+</h:body>
+
+</html>
\ No newline at end of file
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/forms.css b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/forms.css
index 052b5e1..a8a21b3 100644
--- a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/forms.css
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/forms.css
@@ -1,67 +1,56 @@
 fieldset {
   border: none;
 }
-
 input[type="text"],
-input[type="password"] {
-    font-size: 1.1em;
-    padding: 0 0.545454545454545em; /* 0 6px */
-    min-width: 18.1818181818182em; /* 200px */
-    height: 2.18181818181818em; /* 24px */
-    border: 1px #b6b6b6 solid;
-    border-radius: 2px;
-    box-shadow: inset 0px 2px 2px rgba(0,0,0,0.1);
-    color: #333;
+input[type="password"],
+input[type="email"] {
+  font-size: 1.1em;
+  padding: 0 0.545454545454545em;
+  min-width: 18.1818181818182em;
+  height: 2.18181818181818em;
+  border: 1px #b6b6b6 solid;
+  border-radius: 2px;
+  box-shadow: inset 0px 2px 2px rgba(0, 0, 0, 0.1);
+  color: #333;
 }
-
 input[type="text"]:hover,
-input[type="password"]:hover {
+input[type="password"]:hover,
+input[type="email"]:hover {
   border-color: #62afdb;
 }
-
 input[type="text"]:focus,
-input[type="password"]:focus {
+input[type="password"]:focus,
+input[type="email"]:focus {
   border-color: #62afdb;
   box-shadow: #62afdb 0 0 5px;
 }
-
 input[type="submit"] {
-    font-size: 1.3em;
-    padding: 0.30769230769231em 1.07692307692308em; /* 4px 14px */
-    border: 1px #21799e solid;
-    border-radius: 2px;
-    background-image: linear-gradient(top, #00A9EC 0%, #009BD3 100%);
-    background-image: -o-linear-gradient(top, #00A9EC 0%, #009BD3 100%);
-    background-image: -moz-linear-gradient(top, #00A9EC 0%, #009BD3 100%);
-    background-image: -webkit-linear-gradient(top, #00A9EC 0%, #009BD3 100%);
-    background-image: -ms-linear-gradient(top, #00A9EC 0%, #009BD3 100%);
-    background-image: -webkit-gradient(
-      linear,
-      left top,
-      left bottom,
-      color-stop(0.0, #00A9EC),
-      color-stop(1,0, #009BD3)
-    );
-    color: #fff;
-    font-weight: bold;
-    letter-spacing: 0.04em;
+  font-size: 1.3em;
+  padding: 0.30769230769231em 1.07692307692308em;
+  border: 1px #21799e solid;
+  border-radius: 2px;
+  background-image: linear-gradient(top, #00a9ec 0%, #009bd3 100%);
+  background-image: -o-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
+  background-image: -moz-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
+  background-image: -webkit-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
+  background-image: -ms-linear-gradient(top, #00a9ec 0%, #009bd3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #00a9ec), color-stop(1, 0, #009bd3));
+  color: #fff;
+  font-weight: bold;
+  letter-spacing: 0.04em;
 }
-
 input[type="submit"]:hover,
 input[type="submit"]:focus {
   background-color: #009BD3;
   background-image: none;
   cursor: pointer;
 }
-
 input[type="submit"]:active {
   background-color: #0099d4;
   background-image: none;
   cursor: pointer;
   box-shadow: inset 0 0 5px 3px #0074ae;
 }
-
 input[type="checkbox"] {
   margin-right: 0.5em;
 }
-
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/login-screen.css b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/login-screen.css
index 70e9cc3..7e33a6d 100644
--- a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/login-screen.css
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/css/login-screen.css
@@ -3,7 +3,6 @@ body {
 }
 .rcue-login-register {
   background-color: #1D2226;
-  background-image: url("img/login-screen-background.jpg");
   background-position: top left;
   background-size: auto;
   background-repeat: no-repeat;
@@ -22,14 +21,12 @@ body {
 }
 .rcue-login-register .content {
   position: absolute;
-  bottom: 15%;
+  bottom: 10%;
   width: 100%;
   min-width: 76em;
 }
 .rcue-login-register h2 {
   padding-left: 4.34782608695652em;
-  /* 100px */
-
   font-family: "Overpass", sans-serif;
   font-size: 2.3em;
   font-weight: 100;
@@ -255,14 +252,16 @@ a.zocial:before {
   line-height: 1.3em;
 }
 /* Customer login */
-.rcue-login-register.customer {
-  background-image: url("img/customer-login-screen-bg2.jpg");
+
+.rcue-login-register p.powered {
+  font-size: 1.1em;
+  margin-top: 1.27272727272727em;
+  text-align: right;
+  margin-right: 5.81818181818182em;
 }
-.rcue-login-register.customer h2 {
-  display: inline-block;
+.rcue-login-register p.powered a {
+  color: #666;
 }
-.rcue-login-register.customer p.powered {
-  display: inline-block;
-  font-size: 1.3em;
-  margin-left: 1.2em;
+.rcue-login-register p.powered a:hover {
+  color: #0099D3;
 }
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/login.xhtml b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/login.xhtml
index c1cc362..a56e9cf 100755
--- a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/login.xhtml
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/login.xhtml
@@ -1,65 +1,36 @@
-<ui:composition xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:c="http://java.sun.com/jstl/core">
-	<h1><a href="#" title="Go to the home page"><img src="#{login.themeUrl}/img/red-hat-logo.png" alt="Red Hat logo"/></a></h1>
-	<div class="content">
-		<h2>
-			Log in to <strong>#{login.name}</strong>
-		</h2>
-		<div class="background-area">
-			<div class="form-area social clearfix">
-				<section class="app-form">
-					<h3>Application login area</h3>
-					<form action="#{login.loginAction}" method="post">
-						<div>
-							<label for="username">Username</label>
-							<input id="username" name="username" value="#{login.username}" type="text" />
-						</div>
+<ui:composition xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"
+	xmlns:c="http://java.sun.com/jstl/core" template="template.xhtml">
 
-						<ui:repeat var="c" value="#{login.requiredCredentials}">
-							<div>
-								<label for="#{c.type}">#{c.type}</label>
-								<input id="#{c.type}" name="#{c.type}" type="#{c.secret ? 'password' : 'text'}" />
-							</div>
-						</ui:repeat>
+	<ui:define name="header">Log in to <strong>#{login.name}</strong></ui:define>
+	
+	<ui:define name="form">
+		<form action="#{login.loginAction}" method="post">
+			<div>
+				<label for="username">Username</label> <input id="username" name="username" value="#{login.username}" type="text" />
+			</div>
+
+			<ui:repeat var="c" value="#{login.requiredCredentials}">
+				<div>
+					<label for="#{c.name}">#{c.label}</label> <input id="#{c.name}" name="#{c.name}" type="#{c.inputType}" />
+				</div>
+			</ui:repeat>
 
-						<input name="client_id" value="#{login.clientId}" type="hidden" />
-						
-						<h:panelGroup rendered="#{not empty login.scope}">
-							<input name="scope" value="#{login.scope}" type="hidden" />
-						</h:panelGroup>
-						
-						<h:panelGroup rendered="#{not empty login.state}">
-							<input name="state" value="#{login.state}" type="hidden" />
-						</h:panelGroup>
-						
-						<h:panelGroup rendered="#{not empty login.redirectUri}">
-							<input name="redirect_uri" value="#{login.redirectUri}" type="hidden" />
-						</h:panelGroup>
+			<ui:repeat var="p" value="#{login.hiddenProperties}">
+				<input name="#{p.name}" value="#{p.value}" type="hidden" />
+			</ui:repeat>
 
-						<input type="submit" value="Log In" />
-					</form>
-				</section>
-				<section class="social-login">
-					<span>or</span>
-					<h3>Social login area</h3>
-					<p>Log In with</p>
-					<ul>
-						<ui:repeat var="p" value="#{login.providers}">
-							<li><a href="#{p.loginUrl}" class="zocial #{p.id}"> <span class="text">#{p.name}</span></a></li>
-						</ui:repeat>
-					</ul>
-				</section>
-				<section class="info-area">
-					<h3>Info area</h3>
-					<p>
-						No account? <a href="saas-register.html">Register</a>.
-					</p>
-					<ul>
-						<li><strong>Domain:</strong> 10.0.0.1</li>
-						<li><strong>Zone:</strong> Live</li>
-						<li><strong>Appliance:</strong> Yep</li>
-					</ul>
-				</section>
+			<div class="aside-btn">
+				<input type="checkbox" id="remember" /><label for="remember">Remember Username</label>
+				<p>Forgot <a href="#">Username</a> or <a href="#">Password</a>?</p>
 			</div>
-		</div>
-	</div>
+
+			<input type="submit" value="Log In" />
+		</form>
+	</ui:define>
+	
+	<ui:define name="info">
+		<h:panelGroup rendered="#{login.registrationAllowed}">
+			<p>No account? <a href="saas-register.html">Register</a>.</p>
+		</h:panelGroup>	
+	</ui:define>
 </ui:composition>
\ No newline at end of file
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/register.xhtml b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/register.xhtml
new file mode 100755
index 0000000..73b9ef2
--- /dev/null
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/register.xhtml
@@ -0,0 +1,40 @@
+<ui:composition xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"
+	xmlns:c="http://java.sun.com/jstl/core" template="template.xhtml">
+
+	<ui:define name="header">Register with <strong>#{login.name}</strong></ui:define>
+	
+	<ui:define name="form">
+		<form action="#{login.registerAction}" method="post">
+			<div>
+            	<label for="name">Full name</label>
+                <input type="text" id="name" />
+			</div>
+            <div>
+            	<label for="email">Email</label>
+				<input type="email" id="email" />
+			</div>
+			<div>
+				<label for="username">Username</label>
+				<input type="text" id="username" />
+			</div>
+            <div>
+            	<label for="password">Password</label>
+				<input type="password" id="password" />
+			</div>
+
+			<ui:repeat var="p" value="#{login.hiddenProperties}">
+				<input name="#{p.name}" value="#{p.value}" type="hidden" />
+			</ui:repeat>
+						
+			<div class="aside-btn">
+				<p>By registering you agree to the <a href="#">Terms of Service</a> and the <a href="#">Privacy Policy</a>.</p>
+			</div>						
+
+			<input type="submit" value="Register" />
+		</form>
+	</ui:define>
+	
+	<ui:define name="info">
+		<p>Already have an account? <a href="realm-login.html">Log in</a>.</p>
+	</ui:define>
+</ui:composition>
\ No newline at end of file
diff --git a/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/template.xhtml b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/template.xhtml
new file mode 100644
index 0000000..2511a41
--- /dev/null
+++ b/sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/template.xhtml
@@ -0,0 +1,65 @@
+<!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" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html">
+
+<h:head>
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<title>Log in to #{login.name}</title>
+	<link href="#{login.themeConfig['styles']}" rel="stylesheet" />
+	<style>
+		body {
+			background-image: url("#{login.themeConfig['background']}");
+		}
+	</style>
+</h:head>
+
+<h:body class="rcue-login-register">
+	<h:panelGroup rendered="#{not empty login.themeConfig['logo']}">
+		<h1><a href="#" title="Go to the home page"><img src="#{login.themeConfig['logo']}" alt="Logo" /></a></h1>
+	</h:panelGroup>
+
+	<div class="content">
+		<h2><ui:insert name="header" /></h2>
+
+		<div class="background-area">
+			<div class="form-area #{login.social ? 'social' : ''} clearfix">
+				<section class="app-form">
+					<h3>Application login area</h3>
+					<h:messages />
+					<ui:insert name="form" />
+				</section>
+				
+				<h:panelGroup rendered="#{login.social}">
+					<section class="social-login">
+						<span>or</span>
+						<h3>Social login area</h3>
+						<p>Log In with</p>
+						<ul>
+							<ui:repeat var="p" value="#{login.providers}">
+								<li><a href="#{p.loginUrl}" class="zocial #{p.id}"> <span class="text">#{p.name}</span></a></li>
+							</ui:repeat>
+						</ul>
+					</section>
+				</h:panelGroup>
+				
+				<section class="info-area">
+					<h3>Info area</h3>
+					<ui:insert name="info" />
+					<ul>
+						<li><strong>Domain:</strong> 10.0.0.1</li>
+						<li><strong>Zone:</strong> Live</li>
+						<li><strong>Appliance:</strong> Yep</li>
+					</ul>
+				</section>								
+			</div>
+		</div>
+			
+		<h:panelGroup rendered="#{login.themeConfig['displayPoweredBy']}">
+			<p class="powered"><a href="#">Powered by Keycloak</a></p>
+		</h:panelGroup>			
+	</div>
+
+	<ui:insert name="content" />
+
+</h:body>
+</html>
\ No newline at end of file