Renamed sdk-html for forms and added registration form
This commit is contained in:
1 parent
8876484a87
commit
0ffe1cb354
44 files changed
+277
-181
No files matched your search
@@ -52,7 +52,7 @@
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-sdk-html</artifactId>
|
||||
<artifactId>keycloak-forms</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
<!-- <select class="nav pull-left" ng-options="r.name for r in current.realms"></select> -->
|
||||
</div>
|
||||
<ul class="nav pull-right" data-ng-hide="auth.loggedIn">
|
||||
<li><a href="/auth-server/rest/saas/loginPage.html">Login</a></li>
|
||||
<li><a href="/auth-server/saas/saas-register.jsp">Register</a></li>
|
||||
<li><a href="/auth-server/rest/saas/login">Login</a></li>
|
||||
<li><a href="/auth-server/rest/saas/registrations">Register</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right" data-ng-show="auth.loggedIn">
|
||||
<li class="divider-vertical-left dropdown"><a data-toggle="dropdown" class="dropdown-toggle" href="#"><i
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1"%><!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Register with Keycloak</title>
|
||||
<link rel="stylesheet" href="<%=application.getContextPath()%>/saas/css/reset.css">
|
||||
<link rel="stylesheet" type="text/css" href="<%=application.getContextPath()%>/saas/css/base.css">
|
||||
<link rel="stylesheet" type="text/css" href="<%=application.getContextPath()%>/saas/css/forms.css">
|
||||
<link rel="stylesheet" type="text/css" href="<%=application.getContextPath()%>/saas/css/zocial/zocial.css">
|
||||
<link rel="stylesheet" type="text/css" href="<%=application.getContextPath()%>/saas/css/login-screen.css">
|
||||
<link rel="stylesheet" type="text/css" href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic'>
|
||||
</head>
|
||||
<body class="rcue-login-register register">
|
||||
<h1><a href="#" title="Go to the home page"><img src="<%=application.getContextPath()%>/saas/img/red-hat-logo.png" alt="Red Hat logo"></a></h1>
|
||||
<div class="content">
|
||||
<h2>Register with <strong>Keycloak</strong></h2>
|
||||
<div class="background-area">
|
||||
<div class="form-area social clearfix">
|
||||
<section class="app-form">
|
||||
<h3>Application login area</h3>
|
||||
<form action="<%=application.getContextPath()%>/rest/saas/registrations" method="POST">
|
||||
<%
|
||||
String errorMessage = (String)request.getAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE");
|
||||
if (errorMessage != null) { %>
|
||||
<div class="feedback feedback-error">
|
||||
<p><font color="red"><%=errorMessage%></font></p>
|
||||
</div>
|
||||
<% } %>
|
||||
<p class="subtitle">All fields required</p>
|
||||
<div>
|
||||
<label for="name">Full name</label><input type="text" id="name" name="name" autofocus>
|
||||
</div>
|
||||
<div>
|
||||
<label for="email">Email</label><input type="email" id="email" name="email">
|
||||
</div>
|
||||
<div>
|
||||
<label for="username">Username</label><input type="text" id="username" name="username">
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Password</label><input type="password" id="password" placeholder="At least 6 characters" name="password">
|
||||
</div>
|
||||
<div>
|
||||
<label for="password-confirm" class="two-lines">Password confirmation</label><input type="password" id="password-confirm" name="password-confirm">
|
||||
</div>
|
||||
<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>
|
||||
</section>
|
||||
<section class="social-login">
|
||||
<span>or</span>
|
||||
<h3>Social login area</h3>
|
||||
<p>Log In with</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="#" class="zocial facebook">
|
||||
<span class="text">Facebook</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="zocial googleplus">
|
||||
<span class="text">Google</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="zocial twitter">
|
||||
<span class="text">Twitter</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section class="info-area">
|
||||
<h3>Info area</h3>
|
||||
<p>Already have an account? <a href="<%=application.getContextPath()%>/rest/saas/loginPage.html">Log in</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>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-sdk-html</artifactId>
|
||||
<name>Keycloak HTML SDK</name>
|
||||
<artifactId>keycloak-forms</artifactId>
|
||||
<name>Keycloak Forms</name>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
+61
-9
@@ -8,31 +8,33 @@ 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;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.ws.rs.core.MultivaluedMap;
|
||||
|
||||
import org.keycloak.services.models.RealmModel;
|
||||
import org.keycloak.services.models.RequiredCredentialModel;
|
||||
|
||||
@ManagedBean(name = "login")
|
||||
@ManagedBean(name = "forms")
|
||||
@RequestScoped
|
||||
public class LoginBean {
|
||||
public class FormsBean {
|
||||
|
||||
private RealmModel realm;
|
||||
|
||||
private String name;
|
||||
|
||||
private String loginUrl;
|
||||
|
||||
private String loginAction;
|
||||
|
||||
private String socialLoginUrl;
|
||||
|
||||
private String registrationUrl;
|
||||
|
||||
private String username;
|
||||
private String registrationAction;
|
||||
|
||||
private List<RequiredCredential> requiredCredentials;
|
||||
|
||||
@@ -48,6 +50,12 @@ public class LoginBean {
|
||||
|
||||
private String error;
|
||||
|
||||
private String errorDetails;
|
||||
|
||||
private String view;
|
||||
|
||||
private Map<String, String> formData;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
@@ -55,20 +63,26 @@ public class LoginBean {
|
||||
HttpServletRequest request = (HttpServletRequest) ctx.getExternalContext().getRequest();
|
||||
|
||||
realm = (RealmModel) request.getAttribute(RealmModel.class.getName());
|
||||
|
||||
|
||||
if (RealmModel.DEFAULT_REALM.equals(realm.getName())) {
|
||||
name = "Keycloak";
|
||||
} else {
|
||||
name = realm.getName();
|
||||
}
|
||||
|
||||
view = ctx.getViewRoot().getViewId();
|
||||
view = view.substring(view.lastIndexOf('/') + 1, view.lastIndexOf('.'));
|
||||
|
||||
loginUrl = ((URI) request.getAttribute("KEYCLOAK_LOGIN_PAGE")).toString();
|
||||
loginAction = ((URI) request.getAttribute("KEYCLOAK_LOGIN_ACTION")).toString();
|
||||
|
||||
registrationUrl = ((URI) request.getAttribute("KEYCLOAK_REGISTRATION_PAGE")).toString();
|
||||
registrationAction = ((URI) request.getAttribute("KEYCLOAK_REGISTRATION_ACTION")).toString();
|
||||
|
||||
socialLoginUrl = ((URI) request.getAttribute("KEYCLOAK_SOCIAL_LOGIN")).toString();
|
||||
|
||||
username = (String) request.getAttribute("username");
|
||||
|
||||
addRequiredCredentials();
|
||||
addFormData(request);
|
||||
addHiddenProperties(request, "client_id", "scope", "state", "redirect_uri");
|
||||
addSocialProviders();
|
||||
addErrors(request);
|
||||
@@ -98,6 +112,10 @@ public class LoginBean {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getLoginUrl() {
|
||||
return loginUrl;
|
||||
}
|
||||
|
||||
public String getLoginAction() {
|
||||
return loginAction;
|
||||
}
|
||||
@@ -106,6 +124,14 @@ public class LoginBean {
|
||||
return error;
|
||||
}
|
||||
|
||||
public String getErrorDetails() {
|
||||
return errorDetails;
|
||||
}
|
||||
|
||||
public Map<String, String> getFormData() {
|
||||
return formData;
|
||||
}
|
||||
|
||||
public List<Property> getHiddenProperties() {
|
||||
return hiddenProperties;
|
||||
}
|
||||
@@ -114,6 +140,10 @@ public class LoginBean {
|
||||
return requiredCredentials;
|
||||
}
|
||||
|
||||
public String getView() {
|
||||
return view;
|
||||
}
|
||||
|
||||
public String getTheme() {
|
||||
return theme;
|
||||
}
|
||||
@@ -126,8 +156,8 @@ public class LoginBean {
|
||||
return registrationUrl;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
public String getRegistrationAction() {
|
||||
return registrationAction;
|
||||
}
|
||||
|
||||
public boolean isSocial() {
|
||||
@@ -139,6 +169,18 @@ public class LoginBean {
|
||||
return realm.isRegistrationAllowed();
|
||||
}
|
||||
|
||||
private void addFormData(HttpServletRequest request) {
|
||||
formData = new HashMap<String, String>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
MultivaluedMap<String, String> t = (MultivaluedMap<String, String>) request.getAttribute("KEYCLOAK_FORM_DATA");
|
||||
if (t != null) {
|
||||
for (String k : t.keySet()) {
|
||||
formData.put(k, t.getFirst(k));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addHiddenProperties(HttpServletRequest request, String... names) {
|
||||
hiddenProperties = new LinkedList<Property>();
|
||||
for (String name : names) {
|
||||
@@ -170,6 +212,16 @@ public class LoginBean {
|
||||
|
||||
private void addErrors(HttpServletRequest request) {
|
||||
error = (String) request.getAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE");
|
||||
|
||||
if (error != null) {
|
||||
if (view.equals("login")) {
|
||||
errorDetails = error;
|
||||
error = "Login failed";
|
||||
} else if (view.equals("register")) {
|
||||
errorDetails = error;
|
||||
error = "Registration failed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Property {
|
||||
File renamed without changes.
+1
-1
@@ -1,2 +1,2 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<ui:include xmlns:ui="http://java.sun.com/jsf/facelets" src="theme/#{login.theme}/login.xhtml" />
|
||||
<ui:include xmlns:ui="http://java.sun.com/jsf/facelets" src="theme/#{forms.theme}/login.xhtml" />
|
||||
+1
-1
@@ -1,2 +1,2 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<ui:include xmlns:ui="http://java.sun.com/jsf/facelets" src="theme/#{login.theme}/register.xhtml" />
|
||||
<ui:include xmlns:ui="http://java.sun.com/jsf/facelets" src="theme/#{forms.theme}/register.xhtml" />
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
+10
-9
@@ -2,27 +2,28 @@
|
||||
<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">Log in to <strong>#{login.name}</strong></ui:define>
|
||||
<ui:define name="header">Log in to <strong>#{forms.name}</strong></ui:define>
|
||||
|
||||
<ui:define name="form">
|
||||
<form action="#{login.loginAction}" method="post">
|
||||
<form action="#{forms.loginAction}" method="post">
|
||||
<div>
|
||||
<label for="username">Username</label> <input id="username" name="username" value="#{login.username}" type="text" />
|
||||
<label for="username">Username</label>
|
||||
<input id="username" name="username" value="#{forms.formData['username']}" type="text" />
|
||||
</div>
|
||||
|
||||
<ui:repeat var="c" value="#{login.requiredCredentials}">
|
||||
<ui:repeat var="c" value="#{forms.requiredCredentials}">
|
||||
<div>
|
||||
<label for="#{c.name}">#{c.label}</label> <input id="#{c.name}" name="#{c.name}" type="#{c.inputType}" />
|
||||
</div>
|
||||
</ui:repeat>
|
||||
|
||||
<ui:repeat var="p" value="#{login.hiddenProperties}">
|
||||
<ui:repeat var="p" value="#{forms.hiddenProperties}">
|
||||
<input name="#{p.name}" value="#{p.value}" type="hidden" />
|
||||
</ui:repeat>
|
||||
|
||||
<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>
|
||||
<!-- <input type="checkbox" id="remember" /><label for="remember">Remember Username</label> -->
|
||||
<!-- <p>Forgot <a href="#">Username</a> or <a href="#">Password</a>?</p> -->
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Log In" />
|
||||
@@ -30,8 +31,8 @@
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="info">
|
||||
<h:panelGroup rendered="#{login.registrationAllowed}">
|
||||
<p>No account? <a href="#{login.registrationUrl}">Register</a>.</p>
|
||||
<h:panelGroup rendered="#{forms.registrationAllowed}">
|
||||
<p>No account? <a href="#{forms.registrationUrl}">Register</a>.</p>
|
||||
</h:panelGroup>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
+14
-9
@@ -4,31 +4,36 @@
|
||||
|
||||
<ui:param name="bodyClass" value="register" />
|
||||
|
||||
<ui:define name="header">Register with <strong>#{login.name}</strong></ui:define>
|
||||
<ui:define name="header">Register with <strong>#{forms.name}</strong></ui:define>
|
||||
|
||||
<ui:define name="form">
|
||||
<form action="#{login.registerAction}" method="post">
|
||||
<form action="#{forms.registrationAction}" method="post">
|
||||
<p class="subtitle">All fields are required</p>
|
||||
<div>
|
||||
<label for="name">Full name</label>
|
||||
<input type="text" id="name" />
|
||||
<input type="text" id="name" name="name" value="#{forms.formData['name']}" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="email">Email</label>
|
||||
<input type="email" id="email" />
|
||||
<input type="text" id="email" name="email" value="#{forms.formData['email']}" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="username">Username</label>
|
||||
<input type="text" id="username" />
|
||||
<input type="text" id="username" name="username" value="#{forms.formData['username']}" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Password</label>
|
||||
<input type="password" id="password" />
|
||||
<input type="password" id="password" name="password" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="password-confirm">Password confirmation</label>
|
||||
<input type="password" id="password-confirm" name="password-confirm" />
|
||||
</div>
|
||||
|
||||
<ui:repeat var="p" value="#{login.hiddenProperties}">
|
||||
<ui:repeat var="p" value="#{forms.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>
|
||||
@@ -38,6 +43,6 @@
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="info">
|
||||
<p>Already have an account? <a href="realm-login.html">Log in</a>.</p>
|
||||
<p>Already have an account? <a href="#{forms.loginUrl}">Log in</a>.</p>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
File renamed without changes.
+21
-16
@@ -3,42 +3,47 @@
|
||||
|
||||
<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" />
|
||||
<title>Log in to #{forms.name}</title>
|
||||
<link href="#{forms.themeConfig['styles']}" rel="stylesheet" />
|
||||
<style>
|
||||
body {
|
||||
background-image: url("#{login.themeConfig['background']}");
|
||||
background-image: url("#{forms.themeConfig['background']}");
|
||||
}
|
||||
</style>
|
||||
</h:head>
|
||||
|
||||
<h:body class="rcue-login-register #{bodyClass}">
|
||||
<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 rendered="#{not empty forms.themeConfig['logo']}">
|
||||
<h1><a href="#" title="Go to the home page"><img src="#{forms.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">
|
||||
<div class="form-area #{forms.social ? 'social' : ''} clearfix">
|
||||
<section class="app-form">
|
||||
<h3>Application login area</h3>
|
||||
|
||||
<h:panelGroup rendered="#{not empty login.error}">
|
||||
<div class="feedback error bottom-left show"><p><strong>#{login.error}</strong></p></div>
|
||||
<h:panelGroup rendered="#{not empty forms.error}">
|
||||
<div class="feedback error bottom-left show">
|
||||
<p>
|
||||
<strong>#{forms.error}</strong><br/>
|
||||
#{forms.errorDetails}
|
||||
</p>
|
||||
</div>
|
||||
</h:panelGroup>
|
||||
|
||||
<ui:insert name="form" />
|
||||
</section>
|
||||
|
||||
<h:panelGroup rendered="#{login.social}">
|
||||
<h:panelGroup rendered="#{forms.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}">
|
||||
<ui:repeat var="p" value="#{forms.providers}">
|
||||
<li><a href="#{p.loginUrl}" class="zocial #{p.id}"> <span class="text">#{p.name}</span></a></li>
|
||||
</ui:repeat>
|
||||
</ul>
|
||||
@@ -48,16 +53,16 @@
|
||||
<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>
|
||||
<!-- <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']}">
|
||||
<h:panelGroup rendered="#{forms.themeConfig['displayPoweredBy']}">
|
||||
<p class="powered"><a href="#">Powered by Keycloak</a></p>
|
||||
</h:panelGroup>
|
||||
</div>
|
||||
File renamed without changes.
@@ -58,7 +58,7 @@
|
||||
<module>integration</module>
|
||||
<module>examples</module>
|
||||
<module>social</module>
|
||||
<module>sdk-html</module>
|
||||
<module>forms</module>
|
||||
<!--<module>ui</module> -->
|
||||
</modules>
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package org.keycloak.services.resources;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
@@ -22,7 +20,6 @@ public class OAuthUtil {
|
||||
private static final Logger log = Logger.getLogger(OAuthUtil.class);
|
||||
|
||||
public final static String securityFailurePath = "/saas/securityFailure.jsp";
|
||||
public final static String loginFormPath = "/sdk/login.xhtml";
|
||||
public final static String oauthFormPath = "/saas/oauthGrantForm.jsp";
|
||||
|
||||
public static Response processAccessCode(RealmModel realm, TokenManager tokenManager, AuthenticationManager authManager,
|
||||
@@ -75,16 +72,22 @@ public class OAuthUtil {
|
||||
public static void forwardToLoginForm(RealmModel realm, HttpRequest request, UriInfo uriInfo, String redirect,
|
||||
String clientId, String scopeParam, String state) {
|
||||
request.setAttribute(RealmModel.class.getName(), realm);
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ACTION", TokenService.processLoginUrl(uriInfo).build(realm.getId()));
|
||||
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", SocialResource.redirectToProviderAuthUrl(uriInfo).build(realm.getId()));
|
||||
request.setAttribute("KEYCLOAK_REGISTRATION_PAGE", URI.create("not-implemented-yet"));
|
||||
|
||||
request.setAttribute("KEYCLOAK_LOGIN_PAGE", Urls.realmLoginPage(uriInfo, realm.getId()));
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ACTION", Urls.realmLoginAction(uriInfo, realm.getId()));
|
||||
|
||||
request.setAttribute("KEYCLOAK_REGISTRATION_PAGE", Urls.realmRegisterPage(uriInfo, realm.getId()));
|
||||
request.setAttribute("KEYCLOAK_REGISTRATION_ACTION", Urls.realmRegisterAction(uriInfo, realm.getId()));
|
||||
|
||||
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", Urls.socialRedirectToProviderAuth(uriInfo, realm.getId()));
|
||||
|
||||
// RESTEASY eats the form data, so we send via an attribute
|
||||
request.setAttribute("redirect_uri", redirect);
|
||||
request.setAttribute("client_id", clientId);
|
||||
request.setAttribute("scope", scopeParam);
|
||||
request.setAttribute("state", state);
|
||||
request.forward(loginFormPath);
|
||||
|
||||
request.forward(Pages.loginForm);
|
||||
}
|
||||
|
||||
public static void oauthGrantPage(RealmModel realm, HttpRequest request, UriInfo uriInfo, AccessCodeEntry accessCode,
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.keycloak.services.resources;
|
||||
|
||||
public class Pages {
|
||||
|
||||
public final static String loginForm = "/sdk/login.xhtml";
|
||||
public final static String registerForm = "/sdk/register.xhtml";
|
||||
|
||||
}
|
||||
@@ -39,8 +39,6 @@ public class SaasService {
|
||||
@Context
|
||||
HttpResponse response;
|
||||
|
||||
protected String saasLoginPath = "/saas/saas-login.jsp";
|
||||
protected String saasRegisterPath = "/saas/saas-register.jsp";
|
||||
protected String adminPath = "/saas/admin/index.html";
|
||||
protected AuthenticationManager authManager = new AuthenticationManager();
|
||||
|
||||
@@ -170,7 +168,7 @@ public class SaasService {
|
||||
}.call();
|
||||
}
|
||||
|
||||
@Path("loginPage.html")
|
||||
@Path("login")
|
||||
@GET
|
||||
@NoCache
|
||||
public void loginPage() {
|
||||
@@ -180,7 +178,22 @@ public class SaasService {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.defaultRealm();
|
||||
authManager.expireSaasIdentityCookie(uriInfo);
|
||||
forwardToLoginForm(realm);
|
||||
forwardToLoginForm(realm, null, null);
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
|
||||
@Path("registrations")
|
||||
@GET
|
||||
@NoCache
|
||||
public void registerPage() {
|
||||
new Transaction() {
|
||||
@Override
|
||||
protected void runImpl() {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.defaultRealm();
|
||||
authManager.expireSaasIdentityCookie(uriInfo);
|
||||
forwardToRegisterForm(realm, null, null);
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
@@ -195,7 +208,7 @@ public class SaasService {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel realm = realmManager.defaultRealm();
|
||||
authManager.expireSaasIdentityCookie(uriInfo);
|
||||
forwardToLoginForm(realm);
|
||||
forwardToLoginForm(realm, null, null);
|
||||
}
|
||||
}.run();
|
||||
}
|
||||
@@ -214,16 +227,42 @@ public class SaasService {
|
||||
}.run();
|
||||
}
|
||||
|
||||
public final static String loginFormPath = "/sdk/login.xhtml";
|
||||
protected void forwardToLoginForm(RealmModel realm, String error, MultivaluedMap<String, String> formData) {
|
||||
if (error != null) {
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", error);
|
||||
}
|
||||
|
||||
protected void forwardToLoginForm(RealmModel realm) {
|
||||
if (formData != null) {
|
||||
request.setAttribute("KEYCLOAK_FORM_DATA", formData);
|
||||
}
|
||||
|
||||
forwardToForm(realm, Pages.loginForm);
|
||||
}
|
||||
|
||||
protected void forwardToRegisterForm(RealmModel realm, String error, MultivaluedMap<String, String> formData) {
|
||||
if (error != null) {
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", error);
|
||||
}
|
||||
|
||||
if (formData != null) {
|
||||
request.setAttribute("KEYCLOAK_FORM_DATA", formData);
|
||||
}
|
||||
|
||||
forwardToForm(realm, Pages.registerForm);
|
||||
}
|
||||
|
||||
protected void forwardToForm(RealmModel realm, String form) {
|
||||
request.setAttribute(RealmModel.class.getName(), realm);
|
||||
URI action = uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "processLogin").build();
|
||||
URI register = contextRoot(uriInfo).path(saasRegisterPath).build();
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ACTION", action);
|
||||
request.setAttribute("KEYCLOAK_REGISTRATION_PAGE", register);
|
||||
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", SocialResource.redirectToProviderAuthUrl(uriInfo).build(realm.getId()));
|
||||
request.forward(loginFormPath);
|
||||
|
||||
request.setAttribute("KEYCLOAK_LOGIN_PAGE", Urls.saasLoginPage(uriInfo));
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ACTION", Urls.saasLoginAction(uriInfo));
|
||||
|
||||
request.setAttribute("KEYCLOAK_REGISTRATION_PAGE", Urls.saasRegisterPage(uriInfo));
|
||||
request.setAttribute("KEYCLOAK_REGISTRATION_ACTION", Urls.saasRegisterAction(uriInfo));
|
||||
|
||||
request.setAttribute("KEYCLOAK_SOCIAL_LOGIN", Urls.socialRedirectToProviderAuth(uriInfo, realm.getId()));
|
||||
|
||||
request.forward(form);
|
||||
}
|
||||
|
||||
|
||||
@@ -246,22 +285,19 @@ public class SaasService {
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
logger.info("Not Authenticated! Incorrect user name");
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Incorrect user name.");
|
||||
forwardToLoginForm(realm);
|
||||
forwardToLoginForm(realm, "Invalid username or password", formData);
|
||||
return null;
|
||||
}
|
||||
if (!user.isEnabled()) {
|
||||
logger.info("NAccount is disabled, contact admin.");
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Account is disabled, contact admin.");
|
||||
forwardToLoginForm(realm);
|
||||
forwardToLoginForm(realm, "Account is disabled, contact admin.", formData);
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
||||
if (!authenticated) {
|
||||
logger.info("Not Authenticated! Invalid credentials");
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid credentials.");
|
||||
forwardToLoginForm(realm);
|
||||
forwardToLoginForm(realm, "Invalid username or password", formData);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -295,24 +331,24 @@ public class SaasService {
|
||||
@Path("registrations")
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response processRegister(final @FormParam("name") String fullname,
|
||||
final @FormParam("email") String email,
|
||||
final @FormParam("username") String username,
|
||||
final @FormParam("password") String password,
|
||||
final @FormParam("password-confirm") String confirm) {
|
||||
if (!password.equals(confirm)) {
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Password confirmation doesn't match.");
|
||||
request.forward(saasRegisterPath);
|
||||
return null;
|
||||
}
|
||||
public Response processRegister(final MultivaluedMap<String, String> formData) {
|
||||
return new Transaction() {
|
||||
@Override
|
||||
protected Response callImpl() {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
RealmModel defaultRealm = realmManager.defaultRealm();
|
||||
|
||||
String error = validateRegistrationForm(formData);
|
||||
if (error != null) {
|
||||
forwardToRegisterForm(defaultRealm, error, formData);
|
||||
return null;
|
||||
}
|
||||
|
||||
UserRepresentation newUser = new UserRepresentation();
|
||||
newUser.setUsername(username);
|
||||
newUser.setEmail(email);
|
||||
newUser.setUsername(formData.getFirst("username"));
|
||||
newUser.setEmail(formData.getFirst("email"));
|
||||
|
||||
String fullname = formData.getFirst("name");
|
||||
if (fullname != null) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(fullname, " ");
|
||||
StringBuffer first = null;
|
||||
@@ -334,11 +370,11 @@ public class SaasService {
|
||||
newUser.setFirstName(first.toString());
|
||||
newUser.setLastName(last);
|
||||
}
|
||||
newUser.credential(CredentialRepresentation.PASSWORD, password);
|
||||
newUser.credential(CredentialRepresentation.PASSWORD, formData.getFirst("password"));
|
||||
UserModel user = registerMe(defaultRealm, newUser);
|
||||
if (user == null) {
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Username already exists.");
|
||||
request.forward(saasRegisterPath);
|
||||
forwardToRegisterForm(defaultRealm, "Username already exists.", formData);
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -376,5 +412,32 @@ public class SaasService {
|
||||
return user;
|
||||
}
|
||||
|
||||
private String validateRegistrationForm(MultivaluedMap<String, String> formData) {
|
||||
if (isEmpty(formData.getFirst("name"))) {
|
||||
return "Please specify full name";
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst("email"))) {
|
||||
return "Please specify email";
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst("username"))) {
|
||||
return "Please specify username";
|
||||
}
|
||||
|
||||
if (isEmpty(formData.getFirst("password"))) {
|
||||
return "Please specify password";
|
||||
}
|
||||
|
||||
if (!formData.getFirst("password").equals(formData.getFirst("password-confirm"))) {
|
||||
return "Password confirmation doesn't match.";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -199,7 +199,8 @@ public class TokenService {
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
logger.error("Incorrect user name.");
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Incorrect user name.");
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid username or password");
|
||||
request.setAttribute("KEYCLOAK_FORM_DATA", formData);
|
||||
OAuthUtil.forwardToLoginForm(realm, request, uriInfo, redirect, clientId, scopeParam, state);
|
||||
return null;
|
||||
}
|
||||
@@ -211,7 +212,8 @@ public class TokenService {
|
||||
if (!authenticated) {
|
||||
logger.error("Authentication failed");
|
||||
request.setAttribute("username", username);
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid credentials.");
|
||||
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid username or password");
|
||||
request.setAttribute("KEYCLOAK_FORM_DATA", formData);
|
||||
OAuthUtil.forwardToLoginForm(realm, request, uriInfo, redirect, clientId, scopeParam, state);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.keycloak.services.resources;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
public class Urls {
|
||||
|
||||
public static URI realmLoginAction(UriInfo uriInfo, String realmId) {
|
||||
return TokenService.processLoginUrl(uriInfo).build(realmId);
|
||||
}
|
||||
|
||||
public static URI realmLoginPage(UriInfo uriInfo, String realmId) {
|
||||
return uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "processLogin").build();
|
||||
}
|
||||
|
||||
public static URI realmRegisterAction(UriInfo uriInfo, String realmId) {
|
||||
return URI.create("not-implemented-yet");
|
||||
}
|
||||
|
||||
public static URI realmRegisterPage(UriInfo uriInfo, String realmId) {
|
||||
return URI.create("not-implemented-yet");
|
||||
}
|
||||
|
||||
public static URI saasLoginAction(UriInfo uriInfo) {
|
||||
return uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "processLogin").build();
|
||||
}
|
||||
|
||||
public static URI saasLoginPage(UriInfo uriInfo) {
|
||||
return uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "loginPage").build();
|
||||
}
|
||||
|
||||
public static URI saasRegisterAction(UriInfo uriInfo) {
|
||||
return uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "processRegister").build();
|
||||
}
|
||||
|
||||
public static URI saasRegisterPage(UriInfo uriInfo) {
|
||||
return uriInfo.getBaseUriBuilder().path(SaasService.class).path(SaasService.class, "registerPage").build();
|
||||
}
|
||||
|
||||
public static URI socialRedirectToProviderAuth(UriInfo uriInfo, String realmId) {
|
||||
return SocialResource.redirectToProviderAuthUrl(uriInfo).build(realmId);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user