From 912946d92f432ac904b0a1a031c2bcfb75607834 Mon Sep 17 00:00:00 2001 From: jensp Date: Thu, 29 Aug 2019 10:00:32 +0000 Subject: [PATCH] SAML Login Form git-svn-id: https://svn.libreccm.org/ccm/trunk@6169 8810af33-2d31-482b-a856-94f89814c4df --- .../kernel/security/OneLoginUtil.java | 78 +++++++ .../kernel/security/SamlLoginModule.java | 23 +- .../kernel/security/SecurityConfig.java | 40 ++-- .../com/arsdigita/ui/login/LoginServlet.java | 206 +++++++++++------- .../com/arsdigita/ui/login/SamlLoginForm.java | 81 +++++++ 5 files changed, 321 insertions(+), 107 deletions(-) create mode 100644 ccm-core/src/com/arsdigita/kernel/security/OneLoginUtil.java create mode 100644 ccm-core/src/com/arsdigita/ui/login/SamlLoginForm.java diff --git a/ccm-core/src/com/arsdigita/kernel/security/OneLoginUtil.java b/ccm-core/src/com/arsdigita/kernel/security/OneLoginUtil.java new file mode 100644 index 000000000..438dc1648 --- /dev/null +++ b/ccm-core/src/com/arsdigita/kernel/security/OneLoginUtil.java @@ -0,0 +1,78 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.arsdigita.kernel.security; + +import com.arsdigita.ui.login.LoginServlet; +import com.arsdigita.web.URL; + +import com.onelogin.saml2.settings.Saml2Settings; +import com.onelogin.saml2.settings.SettingsBuilder; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +/** + * Utility functions for integrating the OneLogin SAML implementation into CCM. + * + * @see https://github.com/onelogin/java-saml + * + * @author Jens Pelzetter + */ +public final class OneLoginUtil { + + private OneLoginUtil() { + // Nothing + } + + public static Saml2Settings buildSettings( + final HttpServletRequest request) { + + final SecurityConfig securityConfig = SecurityConfig.getConfig(); + + final Map settings = new HashMap<>(); + settings.put("onelogin.saml2.strict", + securityConfig.getOneLoginSaml2Strict()); + settings.put("onelogin.saml2.debug", + securityConfig.getOneLoginSaml2Debug()); + settings.put("onelogin.saml2.sp.entityid", + securityConfig.getOneLoginSaml2SpEntityId()); + settings.put("onelogin.saml2.sp.assertation.consumer_service.url", + URL.there(request, LoginServlet.APPLICATION_NAME)); + settings.put( + "onelogin.saml2.sp.assertation_consumer_service.binding", + securityConfig.getOneLoginSaml2SpAssertationConsumerServiceBinding()); + settings.put("onelogin.saml2.sp.single_logout_service.url", + URL.there(request, LoginServlet.getLogoutPageURL())); + settings.put( + "onelogin.saml2.sp.single_logout_service.binding", + securityConfig.getOneLoginSaml2SpSingleLogoutServiceBinding()); + settings.put("onelogin.saml2.sp.nameidformat", + securityConfig.getOneLoginSaml2SpNameIdFormat()); + + settings.put("onelogin.saml2.idp.entityid", + securityConfig.getOneLoginSaml2IdpEntityId()); + settings.put("onelogin.saml2.idp.single_sign_on_service.url", + securityConfig.getOneLoginSaml2IdpSingleSignOnServiceUrl()); + settings.put("onelogin.saml2.idp.single_sign_on_service.binding", + securityConfig + .getOneLoginSaml2IdpSingleSignOnServiceBinding()); + settings.put("onelogin.saml2.ipd.single_logout_service.url", + securityConfig.getOneLoginSaml2IdpSingleLogoutServiceUrl()); + settings.put( + "onelogin.saml2.idp.single_logout_service.response.url", + securityConfig.getOneLoginSaml2IdpSingleLogoutServiceResponseUrl()); + settings.put( + "onelogin.saml2.idp.single_logout_service.binding", + securityConfig.getOneLoginSaml2IdpSingleLogoutServiceBinding()); + + final SettingsBuilder builder = new SettingsBuilder(); + + return builder.fromValues(settings).build(); + } + +} diff --git a/ccm-core/src/com/arsdigita/kernel/security/SamlLoginModule.java b/ccm-core/src/com/arsdigita/kernel/security/SamlLoginModule.java index 69ec6a2f7..bd0e12ca0 100644 --- a/ccm-core/src/com/arsdigita/kernel/security/SamlLoginModule.java +++ b/ccm-core/src/com/arsdigita/kernel/security/SamlLoginModule.java @@ -55,13 +55,15 @@ public class SamlLoginModule implements LoginModule { @Override public boolean login() throws LoginException { - final HttpServletRequest request = getRequest(); - final HttpServletResponse response = getResponse(); + final HttpServletRequest httpRequest = getRequest(); + final HttpServletResponse httpResponse = getResponse(); final Auth auth; try { - auth = new Auth(request, response); - } catch (IOException | SettingsException | Error ex) { + auth = new Auth(OneLoginUtil.buildSettings(httpRequest), + httpRequest, + httpResponse); + } catch (SettingsException ex) { LOGGER.error("SAML Login failed.", ex); throw new LoginException("SAML Login failed. Configuration error?"); } @@ -85,7 +87,7 @@ public class SamlLoginModule implements LoginModule { @Override public boolean commit() throws LoginException { - + if (userId != null) { subject.getPrincipals().add(new PartyPrincipal(userId)); } @@ -99,7 +101,7 @@ public class SamlLoginModule implements LoginModule { @Override public boolean logout() throws LoginException { - + getRequest().getSession().invalidate(); return true; } @@ -132,18 +134,19 @@ public class SamlLoginModule implements LoginModule { } } - protected BigDecimal getUserId(final String ssoLogin) + protected BigDecimal getUserId(final String ssoLogin) throws LoginException { - + try { final UserAuthentication userAuth = UserAuthentication .retrieveForSSOlogin(ssoLogin); - + return userAuth.getUser().getID(); - } catch(DataObjectNotFoundException ex) { + } catch (DataObjectNotFoundException ex) { throw new FailedLoginException( String.format("SSO login %s not found", ssoLogin) ); } } + } diff --git a/ccm-core/src/com/arsdigita/kernel/security/SecurityConfig.java b/ccm-core/src/com/arsdigita/kernel/security/SecurityConfig.java index 9de959e08..9a2dea80e 100755 --- a/ccm-core/src/com/arsdigita/kernel/security/SecurityConfig.java +++ b/ccm-core/src/com/arsdigita/kernel/security/SecurityConfig.java @@ -151,21 +151,21 @@ public class SecurityConfig extends AbstractConfig { "waf.onelogin.saml2.sp.entityid", Parameter.REQUIRED, "http://localhost:8080/ccm-saml/metadata"); - private final Parameter m_oneLoginSaml2SpAssertationConsumerServiceUrl - = new StringParameter( - "waf.onelogin.saml2.sp.assertion_consumer_service.url", - Parameter.REQUIRED, - "http://localhost:8080/ccm-saml/acs"); +// private final Parameter m_oneLoginSaml2SpAssertationConsumerServiceUrl +// = new StringParameter( +// "waf.onelogin.saml2.sp.assertion_consumer_service.url", +// Parameter.REQUIRED, +// "http://localhost:8080/ccm-saml/acs"); private final Parameter m_oneLoginSaml2SpAssertationConsumerServiceBinding = new StringParameter( "waf.onelogin.saml2.sp.assertion_consumer_service.binding", Parameter.REQUIRED, "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"); - private final Parameter m_oneLoginSaml2SpSingleLogoutServiceUrl - = new StringParameter( - "waf.onelogin.saml2.sp.single_logout_service.url", - Parameter.REQUIRED, - "http://localhost:8080/ccm-saml/sls"); +// private final Parameter m_oneLoginSaml2SpSingleLogoutServiceUrl +// = new StringParameter( +// "waf.onelogin.saml2.sp.single_logout_service.url", +// Parameter.REQUIRED, +// "http://localhost:8080/ccm-saml/sls"); private final Parameter m_oneLoginSaml2SpSingleLogoutServiceBinding = new StringParameter( "waf.onelogin.saml2.sp.single_logout_service.binding", @@ -232,11 +232,11 @@ public class SecurityConfig extends AbstractConfig { register(m_oneLoginSaml2IdpSingleSignOnServiceBinding); register(m_oneLoginSaml2IdpSingleSignOnServiceUrl); register(m_oneLoginSaml2SpAssertationConsumerServiceBinding); - register(m_oneLoginSaml2SpAssertationConsumerServiceUrl); +// register(m_oneLoginSaml2SpAssertationConsumerServiceUrl); register(m_oneLoginSaml2SpEntityId); register(m_oneLoginSaml2SpNameIdFormat); register(m_oneLoginSaml2SpSingleLogoutServiceBinding); - register(m_oneLoginSaml2SpSingleLogoutServiceUrl); +// register(m_oneLoginSaml2SpSingleLogoutServiceUrl); register(m_oneLoginSaml2Strict); loadInfo(); @@ -339,25 +339,25 @@ public class SecurityConfig extends AbstractConfig { return (Boolean) get(m_oneLoginSaml2Strict); } - public final Boolean getM_oneLoginSaml2Debug() { + public final Boolean getOneLoginSaml2Debug() { return (boolean) get(m_oneLoginSaml2Debug); } - public final String getM_oneLoginSaml2SpEntityId() { + public final String getOneLoginSaml2SpEntityId() { return (String) get(m_oneLoginSaml2SpEntityId); } - public final String getOneLoginSaml2SpAssertationConsumerServiceUrl() { - return (String) get(m_oneLoginSaml2SpAssertationConsumerServiceUrl); - } +// public final String getOneLoginSaml2SpAssertationConsumerServiceUrl() { +// return (String) get(m_oneLoginSaml2SpAssertationConsumerServiceUrl); +// } public final String getOneLoginSaml2SpAssertationConsumerServiceBinding() { return (String) get(m_oneLoginSaml2SpAssertationConsumerServiceBinding); } - public final String getOneLoginSaml2SpSingleLogoutServiceUrl() { - return (String) get(m_oneLoginSaml2SpSingleLogoutServiceUrl); - } +// public final String getOneLoginSaml2SpSingleLogoutServiceUrl() { +// return (String) get(m_oneLoginSaml2SpSingleLogoutServiceUrl); +// } public final String getOneLoginSaml2SpSingleLogoutServiceBinding() { return (String) get(m_oneLoginSaml2SpSingleLogoutServiceBinding); diff --git a/ccm-core/src/com/arsdigita/ui/login/LoginServlet.java b/ccm-core/src/com/arsdigita/ui/login/LoginServlet.java index 352bf7621..ed35fbb2b 100644 --- a/ccm-core/src/com/arsdigita/ui/login/LoginServlet.java +++ b/ccm-core/src/com/arsdigita/ui/login/LoginServlet.java @@ -18,6 +18,7 @@ */ package com.arsdigita.ui.login; +import com.arsdigita.bebop.BoxPanel; import com.arsdigita.bebop.Component; import com.arsdigita.bebop.ElementComponent; import com.arsdigita.bebop.Label; @@ -31,6 +32,7 @@ import com.arsdigita.bebop.page.BebopApplicationServlet; import com.arsdigita.dispatcher.DispatcherConfig; import com.arsdigita.dispatcher.DispatcherHelper; import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.security.SecurityConfig; import com.arsdigita.ui.UI; import com.arsdigita.web.ReturnSignal; import com.arsdigita.web.URL; @@ -41,15 +43,16 @@ import javax.servlet.http.HttpServletRequest; import org.apache.log4j.Logger; /** - * Login Application Servlet class, central entry point to create and process the Login application - * UI. + * Login Application Servlet class, central entry point to create and process + * the Login application UI. * - * It manages user registration page, new user page, user workspace, logout, and permissions admin - * pages. + * It manages user registration page, new user page, user workspace, logout, and + * permissions admin pages. * - * It just defines a mapping URL <-> various pages and uses the super class to actually server the - * pages. Additionally is provides service methods to expose various properties, especially the - * URL's of public subpages (e.g. logout) and initializes the creation of the UI. + * It just defines a mapping URL <-> various pages and uses the super class to + * actually server the pages. Additionally is provides service methods to expose + * various properties, especially the URL's of public subpages (e.g. logout) and + * initializes the creation of the UI. * * @author Peter Boy * @version $Id: LoginServlet.java 2161 2012-03-15 00:16:13Z pboy $ @@ -65,49 +68,53 @@ public class LoginServlet extends BebopApplicationServlet { // Define various URLs to subpages of Login to manage administrative tasks. // //////////////////////////////////////////////////////////////////////// /** - * PathInfo into the Login application to access the (optional) newUser * page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser * + * page. Ends with "/" because it is a servlet/directory */ public static final String EDIT_USER_PROFILE_PATH_INFO = "/edit-profile/"; /** - * PathInfo into the Login application to access the (optional) newUser * page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser * + * page. Ends with "/" because it is a servlet/directory */ public static final String NEW_USER_PATH_INFO = "/new-user/"; /** - * PathInfo into the Login application to access the (optional) newUser * page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser * + * page. Ends with "/" because it is a servlet/directory */ - public static final String CHANGE_USER_PASSWORD_PATH_INFO = "/change-password/"; + public static final String CHANGE_USER_PASSWORD_PATH_INFO + = "/change-password/"; /** - * PathInfo into the Login application to access the (optional) newUser page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser + * page. Ends with "/" because it is a servlet/directory */ - public static final String RECOVER_USER_PASSWORD_PATH_INFO = "/recover-password/"; + public static final String RECOVER_USER_PASSWORD_PATH_INFO + = "/recover-password/"; /** - * PathInfo into the Login application to access the (optional) newUser page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser + * page. Ends with "/" because it is a servlet/directory */ - public static final String EXPLAIN_PERSISTENT_COOKIES_PATH_INFO = "/explain-persistent-cookies/"; + public static final String EXPLAIN_PERSISTENT_COOKIES_PATH_INFO + = "/explain-persistent-cookies/"; /** - * PathInfo into the Login application to access the (optional) newUser page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser + * page. Ends with "/" because it is a servlet/directory */ public static final String LOGIN_EXPIRED_PATH_INFO = "/login-expired/"; /** - * PathInfo into the Login application to access the (optional) newUser page. Ends with "/" - * because it is a servlet/directory + * PathInfo into the Login application to access the (optional) newUser + * page. Ends with "/" because it is a servlet/directory */ public static final String LOGOUT_PATH_INFO = "/logout/"; /** - * Base URL of the Login application for internal use, fetched from Login domain class. + * Base URL of the Login application for internal use, fetched from Login + * domain class. */ private final static String s_loginURL = Login.LOGIN_PAGE_URL; @@ -117,7 +124,8 @@ public class LoginServlet extends BebopApplicationServlet { public static final String APPLICATION_NAME = "login"; /** - * User extension point used to create the pages to server and setup a URL - page mapping. + * User extension point used to create the pages to server and setup a URL - + * page mapping. * * @throws ServletException */ @@ -135,8 +143,7 @@ public class LoginServlet extends BebopApplicationServlet { * to a NewUserRegistrationForm or to skip. */ put("/", buildSimplePage("login.userRegistrationForm.title", - new UserLoginForm(Kernel.getSecurityConfig() - .isAutoRegistrationOn()), + buildLogin(), "login")); disableClientCaching("/"); @@ -159,8 +166,9 @@ public class LoginServlet extends BebopApplicationServlet { /* Create ExplainPersistentCookiesPage and add to the page map */ put(EXPLAIN_PERSISTENT_COOKIES_PATH_INFO, buildSimplePage("login.explainCookiesPage.title", - new ElementComponent("subsite:explainPersistentCookies", - SUBSITE_NS_URI), + new ElementComponent( + "subsite:explainPersistentCookies", + SUBSITE_NS_URI), "cookies")); /* Create ChangeUserPasswordPage and add to the page map */ @@ -205,12 +213,12 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Check wether a custom base Page class (top-level container for all Bebop components and - * containersPages) is configured and return the appropriate Page. Here used (only) for - * UserInfo() workspace. + * Check wether a custom base Page class (top-level container for all Bebop + * components and containersPages) is configured and return the appropriate + * Page. Here used (only) for UserInfo() workspace. * - * @return Page to use for top-level container for all Bebop components and containersPage, null - * to use default class + * @return Page to use for top-level container for all Bebop components and + * containersPage, null to use default class */ private static Page checkForPageSubClass() { //check to see if there is subclass of Page defined in Config @@ -223,7 +231,8 @@ public class LoginServlet extends BebopApplicationServlet { Class c = Class.forName(pageClass); p = (Page) c.newInstance(); } catch (Exception e) { - s_log.error("Unable to instantiate waf.dispatcher.default_page_class", e); + s_log.error( + "Unable to instantiate waf.dispatcher.default_page_class", e); } } return p; @@ -238,7 +247,8 @@ public class LoginServlet extends BebopApplicationServlet { private static Page buildSimplePage(String title, Component body, String id) { Page page = PageFactory.buildPage(APPLICATION_NAME, - new Label(LoginHelper.getMessage(title)), + new Label(LoginHelper + .getMessage(title)), id); page.add(body); page.lock(); @@ -246,7 +256,8 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Creates a page informing the user the login has expired. Provides links to login again, etc. + * Creates a page informing the user the login has expired. Provides links + * to login again, etc. * * @return Page (login expired info) */ @@ -256,11 +267,14 @@ public class LoginServlet extends BebopApplicationServlet { new Label(LoginHelper.getMessage("login.loginExpiredPage.title")) ); page.add(new SimpleContainer() { + { // constructor - add(new Label(LoginHelper.getMessage("login.loginExpiredPage.before"))); + add(new Label(LoginHelper.getMessage( + "login.loginExpiredPage.before"))); add(new DynamicLink("login.loginExpiredPage.link", Login.getLoginPageURL())); - add(new Label(LoginHelper.getMessage("login.loginExpiredPage.after"))); + add(new Label(LoginHelper.getMessage( + "login.loginExpiredPage.after"))); add(new ElementComponent("subsite:explainLoginExpired", SUBSITE_NS_URI)); } @@ -281,6 +295,7 @@ public class LoginServlet extends BebopApplicationServlet { ); page.addActionListener(new UserLogoutListener()); page.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent event) { final PageState state = event.getPageState(); @@ -297,14 +312,37 @@ public class LoginServlet extends BebopApplicationServlet { return page; } + private Component buildLogin() { + + final SecurityConfig securityConfig = SecurityConfig.getConfig(); + + if (SecurityConfig.getConfig().getEnableSaml()) { + + final UserLoginForm userLoginForm = new UserLoginForm( + securityConfig.isAutoRegistrationOn()); + + final SamlLoginForm samlLoginForm = new SamlLoginForm(); + + final BoxPanel panel = new BoxPanel(BoxPanel.HORIZONTAL); + panel.add(samlLoginForm); + panel.add(userLoginForm); + + return panel; + } else { + return new UserLoginForm(securityConfig.isAutoRegistrationOn()); + } + } + /** - * Provides an (absolute) URL to a user profile editig page. It is relative to document root - * without any constant prefix if there is one configured. + * Provides an (absolute) URL to a user profile editig page. It is relative + * to document root without any constant prefix if there is one configured. * - * XXX This implementation starts with a leading slash and ends with a slash. In previous - * configurations String urls began without a slash in order to be able to provide a full URL - * which also contains the context part. Since version 5.2 the context part is handled by (new) - * dispatcher. The leading slash it API change! It's impacts have to be checked. (2011-02) + * XXX This implementation starts with a leading slash and ends with a + * slash. In previous configurations String urls began without a slash in + * order to be able to provide a full URL which also contains the context + * part. Since version 5.2 the context part is handled by (new) dispatcher. + * The leading slash it API change! It's impacts have to be checked. + * (2011-02) * * @return url to EditUserProfile page as String */ @@ -317,14 +355,16 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Provides an (absolute URL) to an optional new user registration page (accessible only if - * activated). It is relative to document root without any constant prefix if there is one - * configured. + * Provides an (absolute URL) to an optional new user registration page + * (accessible only if activated). It is relative to document root without + * any constant prefix if there is one configured. * - * XXX This implementation starts with a leading slash and ends with a slash. In previous - * configurations String urls began without a slash in order to be able to provide a full URL - * which also contains the context part. Since version 5.2 the context part is handled by (new) - * dispatcher. The leading slash it API change! It's impacts have to be checked. (2011-02) + * XXX This implementation starts with a leading slash and ends with a + * slash. In previous configurations String urls began without a slash in + * order to be able to provide a full URL which also contains the context + * part. Since version 5.2 the context part is handled by (new) dispatcher. + * The leading slash it API change! It's impacts have to be checked. + * (2011-02) * * @return url to new user registration page as String */ @@ -333,13 +373,16 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Provides an absolute URL (leading slash) for a password recovery page. It is relative to - * document root without any constant prefix if there is one configured. + * Provides an absolute URL (leading slash) for a password recovery page. It + * is relative to document root without any constant prefix if there is one + * configured. * - * XXX This implementation starts with a leading slash and ends with a slash. In previous - * configurations String urls began without a slash in order to be able to provide a full URL - * which also contains the context part. Since version 5.2 the context part is handled by (new) - * dispatcher. The leading slash it API change! It's impacts have tp be checked. (2011-02) + * XXX This implementation starts with a leading slash and ends with a + * slash. In previous configurations String urls began without a slash in + * order to be able to provide a full URL which also contains the context + * part. Since version 5.2 the context part is handled by (new) dispatcher. + * The leading slash it API change! It's impacts have tp be checked. + * (2011-02) * * @return url String for new user registration page as String */ @@ -348,13 +391,16 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Provides an absolute URL (leading slash) for a cookie explanation page. It is relative to - * document root without any constant prefix if there is one configured. + * Provides an absolute URL (leading slash) for a cookie explanation page. + * It is relative to document root without any constant prefix if there is + * one configured. * - * XXX This implementation starts with a leading slash and ends with a slash. In previous - * configurations String urls began without a slash in order to be able to provide a full URL - * which also contains the context part. Since version 5.2 the context part is handled by (new) - * dispatcher. The leading slash it API change! It's impacts have tp be checked. (2011-02) + * XXX This implementation starts with a leading slash and ends with a + * slash. In previous configurations String urls began without a slash in + * order to be able to provide a full URL which also contains the context + * part. Since version 5.2 the context part is handled by (new) dispatcher. + * The leading slash it API change! It's impacts have tp be checked. + * (2011-02) * * @return url String for new user registration page as String */ @@ -363,13 +409,16 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Provides an absolute URL (leading slash) for a login expired info page. It is relative to - * document root without any constant prefix if there is one configured. + * Provides an absolute URL (leading slash) for a login expired info page. + * It is relative to document root without any constant prefix if there is + * one configured. * - * XXX This implementation starts with a leading slash and ends with a slash. In previous - * configurations String urls began without a slash in order to be able to provide a full URL - * which also contains the context part. Since version 5.2 the context part is handled by (new) - * dispatcher. The leading slash it API change! It's impacts have tp be checked. (2011-02) + * XXX This implementation starts with a leading slash and ends with a + * slash. In previous configurations String urls began without a slash in + * order to be able to provide a full URL which also contains the context + * part. Since version 5.2 the context part is handled by (new) dispatcher. + * The leading slash it API change! It's impacts have tp be checked. + * (2011-02) * * @return url String for new user registration page as String */ @@ -378,13 +427,16 @@ public class LoginServlet extends BebopApplicationServlet { } /** - * Provides an absolute URL (leading slash) for the system logout page. It is relative to - * document root without any constant prefix if there is one configured. + * Provides an absolute URL (leading slash) for the system logout page. It + * is relative to document root without any constant prefix if there is one + * configured. * - * XXX This implementation starts with a leading slash and ends with a slash. In previous - * configurations String urls began without a slash in order to be able to provide a full URL - * which also contains the context part. Since version 5.2 the context part is handled by (new) - * dispatcher. The leading slash it API change! It's impacts have tp be checked. (2011-02) + * XXX This implementation starts with a leading slash and ends with a + * slash. In previous configurations String urls began without a slash in + * order to be able to provide a full URL which also contains the context + * part. Since version 5.2 the context part is handled by (new) dispatcher. + * The leading slash it API change! It's impacts have tp be checked. + * (2011-02) * * @return URL for logout page as String */ diff --git a/ccm-core/src/com/arsdigita/ui/login/SamlLoginForm.java b/ccm-core/src/com/arsdigita/ui/login/SamlLoginForm.java new file mode 100644 index 000000000..9f95dff16 --- /dev/null +++ b/ccm-core/src/com/arsdigita/ui/login/SamlLoginForm.java @@ -0,0 +1,81 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package com.arsdigita.ui.login; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.kernel.security.OneLoginUtil; + +import com.onelogin.saml2.Auth; +import com.onelogin.saml2.exception.SettingsException; + +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + * @author Jens Pelzetter + */ +public class SamlLoginForm + extends Form + implements LoginConstants, FormProcessListener { + + final static String FORM_NAME = "saml-login"; + + private Submit submitLogin; + + public SamlLoginForm() { + + this(new BoxPanel()); + } + + public SamlLoginForm(final Container panel) { + + super(FORM_NAME, panel); + setMethod(Form.POST); + addProcessListener(this); + + submitLogin = new Submit( + LoginGlobalizationUtil.globalize("login.saml.submit") + ); + add(submitLogin); + } + + @Override + public void process(final FormSectionEvent event) + throws FormProcessException { + + final PageState state = event.getPageState(); + + if (submitLogin.isSelected(state)) { + final HttpServletRequest request = state.getRequest(); + final HttpServletResponse response = state.getResponse(); + + try { + final Auth auth = new Auth(OneLoginUtil.buildSettings(request), + request, + response); + auth.login(); + } catch (IOException | SettingsException ex) { + throw new FormProcessException(ex); + } + } + } + +}