keycloak-memoizeit
Changes
sdk-html/src/main/java/org/keycloak/sdk/LoginBean.java 217(+119 -98)
sdk-html/src/main/resources/META-INF/resources/sdk/theme/saas/img/customer-login-screen-bg2.jpg 0(+0 -0)
Details
sdk-html/src/main/java/org/keycloak/sdk/LoginBean.java 217(+119 -98)
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