diff --git a/README.md b/README.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..def2025270e701f38d7f91262972806b583a18d0 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,164 @@ +Shibboleth Authentication Plugin for Liferay +============================================ + +* This plugin is derived from an initial version of rsheshi@gmail.com. See: http://code.google.com/p/liferay-shibboleth-plugin/ +* The first major extension was done by Ivan Novakov. https://github.com/ivan-novakov +* Further upgrades were made by Mihály Héder. https://github.com/mheder +* The latest extensions were made by Szabolcs Tenczer https://github.com/burgosz + +Additional features has been added: + +* auto create users using Shibboleth attributes (email, first name, last name) +* auto update user information upon login +* added options to specify the headers (Shibboleth attributes) to be used for extracting email, first name and last name +* basic attribute to role mapping + +Requirements +------------ + +* Apache 2.x with mod_ssl and mod_proxy_ajp +* Shibboleth SP 2.x + +Introduction +------------ + +Currently, there is no native Java Shibboleth service provider. If you need to protect your Java web +with Shibboleth, you have to run Apache with mod_shib in front of your servlet container (Tomcat, JBoss, ...). +The protected application must not be accessible directly, it must be run on a private address. Apache will intercept +requests, and after performing all authentication related tasks, it will pass the request to the backend servlet +container using AJP (Apache JServ Protocol). + +Shibboleth Service Provider +--------------------------- + +A standard Shibboleth Service Provider instance may be used with one difference - the attribute preffix must bes +set to "AJP_", otherwise user attributes from Shibboleh will not be accessible in the application. + + <ApplicationDefaults entityID="https://liferay-test/shibboleth" + REMOTE_USER="uid eppn persistent-id targeted-id" + attributePrefix="AJP_"> + + +Apache configuration +-------------------- + +First, we need to set the AJP communication with the backend in our virtual host configuration: + + ProxyPass / ajp://localhost:8009/ + ProxyPassReverse / ajp://localhost:8009/ + +Then we'll configure Shibboleth to be "activated" for the whole site: + + <Location /> + AuthType shibboleth + require shibboleth + </Location> + +And require a Shibboleth session at the "login" location: + + <Location /c/portal/login> + AuthType shibboleth + ShibRequireSession On + require valid-user + </Location> + + +Container's AJP connector +--------------------- + +Make sure, the backend servlet container has properly configured AJP connector. For example, in JBoss it is not enabled by default and you have to explicitly enable it: + + # cd $JBOSS_HOME/bin + # ./jboss-cli.sh + You are disconnected at the moment. Type 'connect' to connect to the server or 'help' for the list of supported commands. + [disconnected /] connect + [standalone@localhost:9999 /] /subsystem=web:read-children-names(child-type=connector) + { + "outcome" => "success", + "result" => ["http"] + } + [standalone@localhost:9999 /] /subsystem=web/connector=ajp:add(socket-binding=ajp, protocol="AJP/1.3", enabled=true, scheme=ajp) + {"outcome" => "success"} + [standalone@localhost:9999 /] /subsystem=web:read-children-names(child-type=connector) + { + "outcome" => "success", + "result" => [ + "ajp", + "http" + ] + } + + +Plugin installation and configuration +------------------------------------- + +Clone the repository and run the Maven install script: + + # git clone https://github.com/mheder/liferay-shibboleth-plugin + # cd liferay-shibboleth-plugin + # mvn install + +Then deploy the WAR file to your servlet container. +After a successful installation a new "Shibboleth" section appears in the Liferay's Control panel at "Portal Settings / Authentication". You can adjust Shibboleth authentication there. The most important setting is the name of the attribute from with the user identity is taken. +At the same time, in "Portal Settings --> Authentication --> General", disable all "Allow..." options. + +Further steps +------------- + +If you plan to use Shibboleth autehtnication only, it will be a good idea to prevent your users from changing their personal info (especially the screen name which holds the identity). + +If you choose to auto-create users, you need to disable the "terms of use" page and the "security question", which appear to the new users. Add these directives to your portal-ext.properties: + + # + # Set this to true to enable reminder queries that are used to help reset a + # user's password. + # + users.reminder.queries.enabled=false + users.reminder.queries.custom.question.enabled=false + + # + # Set this to true if all users are required to agree to the terms of use. + # + terms.of.use.required=false + +Logging can be enabled at "Control panel --> Server Administration --> Log Levels" by adding these categories: + + com.liferay.portal.security.auth.ShibbolethAutoLogin + com.liferay.portal.servlet.filters.sso.shibboleth.ShibbolethFilter + +These settings will work untill server reboot only. To make them permanent you need to create a special configuration file placed at `$JBOSS_HOME/standalone/deployments/ROOT.war/WEB-INF/classes/META-INF/portal-log4j-ext.xml`: + + <?xml version="1.0"?> + <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> + + <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"> + + <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender"> + <layout class="org.apache.log4j.PatternLayout"> + <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}:%L] %m%n" /> + </layout> + </appender> + + <category name="com.liferay.portal.security.auth.ShibbolethAutoLogin"> + <priority value="INFO" /> + </category> + + <category name="com.liferay.portal.servlet.filters.sso.shibboleth.ShibbolethFilter"> + <priority value="INFO" /> + </category> + + </log4j:configuration> + + + +Licence +------- + +[MIT Licence](http://opensource.org/licenses/mit-license.php) + + +Contact +------- + +* homepage: https://github.com/ivan-novakov/liferay-shibboleth-plugin + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000000000000000000000000000000000000..0fdd6ea216538bed633da2931647fb64b3ca1a4e --- /dev/null +++ b/pom.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>com.github.ivan-novakov.liferay-shibboleth-plugin</groupId> + <artifactId>liferay-shibboleth-plugin</artifactId> + <packaging>war</packaging> + <name>liferay-shibboleth-plugin</name> + <url>https://github.com/ivan-novakov/liferay-shibboleth-plugin</url> + <version>1.2</version> + <properties> + <liferay.auto.deploy.dir>/opt/lr/deploy</liferay.auto.deploy.dir> + <liferay.version>6.2.0-RC5</liferay.version> + </properties> + <build> + <finalName>shibboleth-plugin-hook</finalName> + <plugins> + <plugin> + <groupId>com.liferay.maven.plugins</groupId> + <artifactId>liferay-maven-plugin</artifactId> + <version>${liferay.version}</version> + <configuration> + <autoDeployDir>${liferay.auto.deploy.dir}</autoDeployDir> + <liferayVersion>${liferay.version}</liferayVersion> + <pluginType>hook</pluginType> + </configuration> + </plugin> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <encoding>UTF-8</encoding> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> + <plugin> + <artifactId>maven-resources-plugin</artifactId> + <configuration> + <encoding>UTF-8</encoding> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-war-plugin</artifactId> + <version>2.4</version> + <configuration> + <webResources> + <resource> + <filtering>true</filtering> + <directory>src/main/webapp</directory> + <includes> + <include>**/liferay-plugin-package.xml</include> + <include>**/web.xml</include> + </includes> + </resource> + </webResources> + <warSourceDirectory>src/main/webapp</warSourceDirectory> + <webXml>src/main/webapp/WEB-INF/web.xml</webXml> + </configuration> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>com.liferay.portal</groupId> + <artifactId>portal-service</artifactId> + <version>${liferay.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>com.liferay.portal</groupId> + <artifactId>util-java</artifactId> + <version>${liferay.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.portlet</groupId> + <artifactId>portlet-api</artifactId> + <version>2.0</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.4</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>javax.servlet.jsp</groupId> + <artifactId>jsp-api</artifactId> + <version>2.0</version> + <scope>provided</scope> + </dependency> + </dependencies> +</project> diff --git a/src/main/java/com/liferay/portal/security/auth/ShibbolethAutoLogin.java b/src/main/java/com/liferay/portal/security/auth/ShibbolethAutoLogin.java new file mode 100644 index 0000000000000000000000000000000000000000..7fea4902378521a3715bec20311fbc0a8e7abb64 --- /dev/null +++ b/src/main/java/com/liferay/portal/security/auth/ShibbolethAutoLogin.java @@ -0,0 +1,340 @@ +package com.liferay.portal.security.auth; + +import com.liferay.portal.NoSuchUserException; +import com.liferay.portal.kernel.exception.PortalException; +import com.liferay.portal.kernel.exception.SystemException; +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; +import com.liferay.portal.kernel.util.StringPool; +import com.liferay.portal.kernel.util.Validator; +import com.liferay.portal.model.CompanyConstants; +import com.liferay.portal.model.Role; +import com.liferay.portal.model.User; +import com.liferay.portal.security.ldap.PortalLDAPImporterUtil; +import com.liferay.portal.service.RoleLocalServiceUtil; +import com.liferay.portal.service.ServiceContext; +import com.liferay.portal.service.UserLocalServiceUtil; +import com.liferay.portal.shibboleth.util.ShibbolethPropsKeys; +import com.liferay.portal.shibboleth.util.Util; +import com.liferay.portal.util.PortalUtil; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.util.*; + +/** + * Performs autologin based on the header values passed by Shibboleth. + * + * The Shibboleth user ID header set in the configuration must contain the user + * ID, if users are authenticated by screen name or the user email, if the users + * are authenticated by email (Portal settings --> Authentication --> General). + * + * @author Romeo Sheshi + * @author Ivan Novakov <ivan.novakov@debug.cz> + */ +public class ShibbolethAutoLogin implements AutoLogin { + + private static Log _log = LogFactoryUtil.getLog(ShibbolethAutoLogin.class); + + @Override + public String[] handleException(HttpServletRequest request, HttpServletResponse response, Exception e) throws AutoLoginException { + // taken from BaseAutoLogin + if (Validator.isNull(request.getAttribute(AutoLogin.AUTO_LOGIN_REDIRECT))) { + throw new AutoLoginException(e); + } + _log.error(e, e); + return null; + } + + @Override + public String[] login(HttpServletRequest req, HttpServletResponse res) throws AutoLoginException { + + User user; + String[] credentials = null; + HttpSession session = req.getSession(false); + long companyId = PortalUtil.getCompanyId(req); + + + try { + _log.info("Shibboleth Autologin [modified 2]"); + + if (!Util.isEnabled(companyId)) { + return credentials; + } + + user = loginFromSession(companyId, session); + if (Validator.isNull(user)) { + return credentials; + } + + credentials = new String[3]; + credentials[0] = String.valueOf(user.getUserId()); + credentials[1] = user.getPassword(); + credentials[2] = Boolean.TRUE.toString(); + return credentials; + + } catch (NoSuchUserException e) { + logError(e); + } catch (Exception e) { + logError(e); + throw new AutoLoginException(e); + } + + return credentials; + } + + private User loginFromSession(long companyId, HttpSession session) throws Exception { + String login; + User user = null; + + login = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_LOGIN); + if (Validator.isNull(login)) { + return null; + } + + String authType = Util.getAuthType(companyId); + + try { + if (authType.equals(CompanyConstants.AUTH_TYPE_SN)) { + _log.info("Trying to find user with screen name: " + login); + user = UserLocalServiceUtil.getUserByScreenName(companyId, login); + } else if (authType.equals(CompanyConstants.AUTH_TYPE_EA)) { + + String emailAddress = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_EMAIL); + if (Validator.isNull(emailAddress)) { + return null; + } + + _log.info("Trying to find user with email: " + emailAddress); + user = UserLocalServiceUtil.getUserByEmailAddress(companyId, emailAddress); + } else { + throw new NoSuchUserException(); + } + + _log.info("User found: " + user.getScreenName() + " (" + user.getEmailAddress() + ")"); + + if (Util.autoUpdateUser(companyId)) { + _log.info("Auto-updating user..."); + updateUserFromSession(user, session); + } + + } catch (NoSuchUserException e) { + _log.error("User " + login + " not found"); + + if (Util.autoCreateUser(companyId)) { + _log.info("Importing user from session..."); + user = createUserFromSession(companyId, session); + _log.info("Created user with ID: " + user.getUserId()); + } else if (Util.importUser(companyId)) { + _log.info("Importing user from LDAP..."); + user = PortalLDAPImporterUtil.importLDAPUser(companyId, StringPool.BLANK, login); + } + } + + try { + updateUserRolesFromSession(companyId, user, session); + } catch (Exception e) { + _log.error("Exception while updating user roles from session: " + e.getMessage()); + } + + return user; + } + + /** + * Create user from session + */ + protected User createUserFromSession(long companyId, HttpSession session) throws Exception { + User user = null; + + String screenName = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_LOGIN); + if (Validator.isNull(screenName)) { + _log.error("Cannot create user - missing screen name"); + return user; + } + + String emailAddress = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_EMAIL); + if (Validator.isNull(emailAddress)) { + _log.error("Cannot create user - missing email"); + return user; + } + + String firstname = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_FIRSTNAME); + if (Validator.isNull(firstname)) { + _log.error("Cannot create user - missing firstname"); + return user; + } + + String surname = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_SURNAME); + if (Validator.isNull(surname)) { + _log.error("Cannot create user - missing surname"); + return user; + } + + _log.info("Creating user: screen name = [" + screenName + "], emailAddress = [" + emailAddress + + "], first name = [" + firstname + "], surname = [" + surname + "]"); + + return addUser(companyId, screenName, emailAddress, firstname, surname); + } + + /** + * Store user + */ + private User addUser(long companyId, String screenName, String emailAddress, String firstName, String lastName) + throws Exception { + + long creatorUserId = 0; + boolean autoPassword = true; + String password1 = null; + String password2 = null; + boolean autoScreenName = false; + long facebookId = 0; + String openId = StringPool.BLANK; + Locale locale = Locale.US; + String middleName = StringPool.BLANK; + int prefixId = 0; + int suffixId = 0; + boolean male = true; + int birthdayMonth = Calendar.JANUARY; + int birthdayDay = 1; + int birthdayYear = 1970; + String jobTitle = StringPool.BLANK; + + long[] groupIds = null; + long[] organizationIds = null; + long[] roleIds = null; + long[] userGroupIds = null; + + boolean sendEmail = false; + ServiceContext serviceContext = null; + + return UserLocalServiceUtil.addUser(creatorUserId, companyId, autoPassword, password1, password2, + autoScreenName, screenName, emailAddress, facebookId, openId, locale, firstName, middleName, lastName, + prefixId, suffixId, male, birthdayMonth, birthdayDay, birthdayYear, jobTitle, groupIds, + organizationIds, roleIds, userGroupIds, sendEmail, serviceContext); + } + + protected void updateUserFromSession(User user, HttpSession session) throws Exception { + boolean modified = false; + + String emailAddress = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_EMAIL); + if (Validator.isNotNull(emailAddress) && !user.getEmailAddress().equals(emailAddress)) { + _log.info("User [" + user.getScreenName() + "]: update email address [" + user.getEmailAddress() + + "] --> [" + emailAddress + "]"); + user.setEmailAddress(emailAddress); + modified = true; + } + + String firstname = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_FIRSTNAME); + if (Validator.isNotNull(firstname) && !user.getFirstName().equals(firstname)) { + _log.info("User [" + user.getScreenName() + "]: update first name [" + user.getFirstName() + "] --> [" + + firstname + "]"); + user.setFirstName(firstname); + modified = true; + } + + String surname = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_SURNAME); + if (Validator.isNotNull(surname) && !user.getLastName().equals(surname)) { + _log.info("User [" + user.getScreenName() + "]: update last name [" + user.getLastName() + "] --> [" + + surname + "]"); + user.setLastName(surname); + modified = true; + } + + if (modified) { + UserLocalServiceUtil.updateUser(user); + } + } + + private void updateUserRolesFromSession(long companyId, User user, HttpSession session) throws Exception { + if (!Util.autoAssignUserRole(companyId)) { + return; + } + + List<Role> currentFelRoles = getRolesFromSession(companyId, session); + long[] currentFelRoleIds = roleListToLongArray(currentFelRoles); + + List<Role> felRoles = getAllRolesWithConfiguredSubtype(companyId); + long[] felRoleIds = roleListToLongArray(felRoles); + + RoleLocalServiceUtil.unsetUserRoles(user.getUserId(), felRoleIds); + RoleLocalServiceUtil.addUserRoles(user.getUserId(), currentFelRoleIds); + + _log.info("User '" + user.getScreenName() + "' has been assigned " + currentFelRoleIds.length + " role(s): " + + Arrays.toString(currentFelRoleIds)); + } + + private long[] roleListToLongArray(List<Role> roles) { + long[] roleIds = new long[roles.size()]; + + for (int i = 0; i < roles.size(); i++) { + roleIds[i] = roles.get(i).getRoleId(); + } + + return roleIds; + } + + private List<Role> getAllRolesWithConfiguredSubtype(long companyId) throws Exception { + String roleSubtype = Util.autoAssignUserRoleSubtype(companyId); + return RoleLocalServiceUtil.getSubtypeRoles(roleSubtype); + } + + private List<Role> getRolesFromSession(long companyId, HttpSession session) throws SystemException { + List<Role> currentFelRoles = new ArrayList<Role>(); + String affiliation = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_AFFILIATION); + + if (Validator.isNull(affiliation)) { + return currentFelRoles; + } + + String[] affiliationList = affiliation.split(";"); + for (String roleName : affiliationList) { + Role role; + try { + role = RoleLocalServiceUtil.getRole(companyId, roleName); + } catch (PortalException e) { + _log.info("Exception while getting role with name '" + roleName + "': " + e.getMessage()); + try{ + if(Util.isCreateRoleEnabled(companyId)){ + List<Role> roleList = RoleLocalServiceUtil.getRoles(companyId); + long [] roleIds = roleListToLongArray(roleList); + Arrays.sort(roleIds); + long newId = roleIds[roleIds.length-1]; + newId = newId+1; + role = RoleLocalServiceUtil.createRole(newId); + + long classNameId = 0; + try{ + classNameId = RoleLocalServiceUtil.getRole(roleIds[roleIds.length-1]).getClassNameId(); + }catch (PortalException ex){ + _log.info("classname error"); + } + role.setClassNameId(classNameId); + role.setCompanyId(companyId); + role.setClassPK(newId); + role.setDescription(null); + role.setTitleMap(null); + role.setName(roleName); + role.setType(1); + RoleLocalServiceUtil.addRole(role); + }else continue; + }catch (Exception exc){ + continue; + } + } + + currentFelRoles.add(role); + } + + return currentFelRoles; + } + + private void logError(Exception e) { + _log.error("Exception message = " + e.getMessage() + " cause = " + e.getCause()); + if (_log.isDebugEnabled()) { + _log.error(e); + } + + } + +} \ No newline at end of file diff --git a/src/main/java/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.java b/src/main/java/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.java new file mode 100644 index 0000000000000000000000000000000000000000..2b00b16df1101fef9743b003b529fbf40b211418 --- /dev/null +++ b/src/main/java/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.java @@ -0,0 +1,218 @@ +package com.liferay.portal.servlet.filters.sso.shibboleth; + +import com.liferay.portal.kernel.log.Log; +import com.liferay.portal.kernel.log.LogFactoryUtil; +import com.liferay.portal.kernel.servlet.BaseFilter; +import com.liferay.portal.kernel.util.Validator; +import com.liferay.portal.shibboleth.util.ShibbolethPropsKeys; +import com.liferay.portal.shibboleth.util.Util; +import com.liferay.portal.util.PortalUtil; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +/** + * @author Romeo Sheshi + * @author Ivan Novakov <ivan.novakov@debug.cz> + */ +public class ShibbolethFilter extends BaseFilter { + + @Override + public boolean isFilterEnabled(HttpServletRequest request, HttpServletResponse response) { + try { + long companyId = PortalUtil.getCompanyId(request); + if (Util.isEnabled(companyId)) { + return true; + } + } catch (Exception e) { + _log.error(e, e); + } + return false; + } + + @Override + protected Log getLog() { + return _log; + } + + @Override + protected void processFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) + throws Exception { + + _log.info("Shibboleth filter"); + + String pathInfo = request.getPathInfo(); + HttpSession session = request.getSession(); + long companyId = PortalUtil.getCompanyId(request); + + if (pathInfo.contains("/portal/logout")) { + if (Util.isLogoutEnabled(companyId)) { + session.invalidate(); + String logoutUrl = Util.getLogoutUrl(companyId); + response.sendRedirect(logoutUrl); + return; + } + } else { + extractData(session, companyId, request); + } + processFilter(ShibbolethFilter.class, request, response, filterChain); + } + + /** + * Extracts user data from AJP or HTTP header + * + * @return true if any data is present + */ + protected boolean extractData(HttpSession session, long companyId, HttpServletRequest request) throws Exception { + String login = (String) session.getAttribute(ShibbolethPropsKeys.SHIBBOLETH_LOGIN); + if (Validator.isNull(login)) { + + boolean headersEnabled = Util.isHeadersEnabled(companyId); + + if (headersEnabled) { + _log.info("Using HTTP headers as source for attribute values"); + } else { + _log.info("Using Environment variables as source for attribute values"); + } + + //String aaiProvidedLoginName = getHeader(Util.getHeaderName(companyId), request, headersEnabled); + + //MODIFIED FV + String aaiProvidedLoginName = getHeader(Util.getHeaderName(companyId), request, headersEnabled); + + System.out.println ("ORIGINAL: "+aaiProvidedLoginName); + aaiProvidedLoginName=aaiProvidedLoginName.split("@")[0]; + System.out.println ("SPLITTED: "+aaiProvidedLoginName); + + String aaiProvidedEmail = getHeader(Util.getEmailHeaderName(companyId), request, headersEnabled); + + String aaiProvidedFirstname = getHeader(Util.getFirstnameHeaderName(companyId), request, headersEnabled); + + String aaiProvidedSurname = getHeader(Util.getSurnameHeaderName(companyId), request, headersEnabled); + + String aaiProvidedAffiliation = getHeader(Util.getAffiliationHeaderName(companyId), request, headersEnabled); + + + if (Validator.isNull(aaiProvidedLoginName)) { + _log.error("Required header [" + Util.getHeaderName(companyId) + "] not found"); + _log.error("AAI authentication failed as login name header is empty."); + return false; + } + if (Util.isScreenNameTransformEnabled(companyId)) { + _log.info("ScreenName transform is enabled."); + //check validity of screen name + + // most probably it is an eduPersonPrincipalName. Make transformations + if(aaiProvidedLoginName.contains("@")){ + _log.info("The login name provided by AAI looks like an " + + "email (or eduPersonPrincipalName): " + + aaiProvidedLoginName + + " It needs to be converted to be a Liferay screen name."); + aaiProvidedLoginName = aaiProvidedLoginName.replaceAll("@", ".at."); + _log.info("Login name is converted to:" + aaiProvidedLoginName); + } else _log.info("error"); + //Liferay does not like underscores + if (aaiProvidedLoginName.contains("_")) { + _log.info("The login name provided by AAI contains underscores:" + + aaiProvidedLoginName + + "It needs to be converted to be a Liferay screen name."); + aaiProvidedLoginName = aaiProvidedLoginName.replaceAll("_", "-"); + _log.info("Login name is converted to:" + aaiProvidedLoginName); + } + } + else { + _log.info("ScreenName transform is disabled."); + } + + _log.info("AAI-provided screen name is:" + aaiProvidedLoginName); + session.setAttribute(ShibbolethPropsKeys.SHIBBOLETH_LOGIN, aaiProvidedLoginName); + + //get the first of multi-valued email address + if (aaiProvidedEmail.contains(";")) { + _log.info("The email address string provided by AAI is multi-valued:" + + aaiProvidedEmail + + " Using the first value."); + String[] emails = aaiProvidedEmail.split(";"); + aaiProvidedEmail = emails[0]; + } + _log.info("AAI-provided email is:" + aaiProvidedEmail); + session.setAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_EMAIL, aaiProvidedEmail); + + if (Validator.isNull(aaiProvidedFirstname)) { + _log.error("No First name provided in: " + + Util.getFirstnameHeaderName(companyId) + + " using a default value instead."); + aaiProvidedFirstname = "MissingFirstName"; + } + _log.info("AAI-provided first name is:" + aaiProvidedFirstname); + session.setAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_FIRSTNAME, aaiProvidedFirstname); + + if (Validator.isNull(aaiProvidedSurname)) { + _log.error("No Surname provided in: " + + Util.getSurnameHeaderName(companyId) + + " using a default value instead."); + aaiProvidedSurname = "MissingSurname"; + } + _log.info("AAI-provided Surname is:" + aaiProvidedSurname); + session.setAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_SURNAME, aaiProvidedSurname); + + if (Validator.isNull(aaiProvidedAffiliation)) { + _log.debug("No affiliation provided"); + aaiProvidedAffiliation = ""; + } + if (Util.isAffiliationTruncateEnabled(companyId) && aaiProvidedAffiliation.contains(":")) { + _log.info("affiliation contains ':' characters: " + + aaiProvidedAffiliation + + " assuming eduPersonEntitlement format"); + // AAI-provided affiliation is multi-valued + if (aaiProvidedAffiliation.contains(";")) { + _log.info("AAI-provided affiliation is multi-valued:" + + aaiProvidedAffiliation + + " Processing each vale"); + String[] affiliations = aaiProvidedAffiliation.split(";"); + aaiProvidedAffiliation = ""; + + for (int i = 0; i < affiliations.length; i++) { + String[] parts = affiliations[i].split(":"); + aaiProvidedAffiliation += parts[parts.length - 1]; + if (i < affiliations.length - 1) { + aaiProvidedAffiliation += ";"; + } + } + + } else { + String[] parts = aaiProvidedAffiliation.split(":"); + aaiProvidedAffiliation = parts[parts.length - 1]; + } + } + _log.info("AAI-provided affiliation is:" + aaiProvidedAffiliation); + session.setAttribute(ShibbolethPropsKeys.SHIBBOLETH_HEADER_AFFILIATION, aaiProvidedAffiliation); + + return true; + } else { + return false; + } + } + + protected String getHeader(String headerName, HttpServletRequest request, boolean headersEnabled) { + if (Validator.isNull(headerName)) { + return null; + } + String headerValue; + + if (headersEnabled) { + headerValue = request.getHeader(headerName); + } else { + headerValue = (String) request.getAttribute(headerName); + } + + _log.info("Header [" + headerName + "]: " + headerValue); + + return headerValue; + } + + private static final Log _log = LogFactoryUtil.getLog(ShibbolethFilter.class); + +} diff --git a/src/main/java/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.java b/src/main/java/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.java new file mode 100644 index 0000000000000000000000000000000000000000..d77ef5f3a3057f095fbf964c07d72b13a953de9b --- /dev/null +++ b/src/main/java/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.java @@ -0,0 +1,48 @@ +package com.liferay.portal.shibboleth.util; + +/** + * @author Romeo Sheshi + * @author Ivan Novakov <ivan.novakov@debug.cz> + */ +public class ShibbolethPropsKeys { + + public static final String SHIBBOLETH_ENABLED = "shibboleth.enabled"; + + public static final String SHIBBOLETH_HEADER = "shibboleth.header"; + + public static final String SHIBBOLETH_HEADER_EMAIL = "shibboleth.header.email"; + + public static final String SHIBBOLETH_HEADER_FIRSTNAME = "shibboleth.header.firstname"; + + public static final String SHIBBOLETH_HEADER_SURNAME = "shibboleth.header.surname"; + + public static final String SHIBBOLETH_HEADER_AFFILIATION = "shibboleth.header.affiliation"; + + public static final String SHIBBOLETH_USER_AUTO_CREATE = "shibboleth.user.auto.create"; + + public static final String SHIBBOLETH_USER_AUTO_UPDATE = "shibboleth.user.auto.update"; + + public static final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN = "shibboleth.user.role.auto.assign"; + + public static final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE = "shibboleth.user.role.auto.assign.subtype"; + + public static final String SHIBBOLETH_LOGIN = "shibboleth.login"; + + public static final String SHIBBOLETH_USER_LDAP_IMPORT = "shibboleth.user.ldap.import"; + + public static final String SHIBBOLETH_LOGIN_URL = "shibboleth.login.url"; + + public static final String SHIBBOLETH_LOGOUT_ENABLE = "shibboleth.logout.enabled"; + + public static final String SHIBBOLETH_LOGOUT_URL = "shibboleth.logout.url"; + + public static final String SHIBBOLETH_HEADERS_ENABLE = "shibboleth.headers.enabled"; + + public static final String SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE = "shibboleth.affiliation.truncate.enabled"; + + public static final String SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE = "shibboleth.screenname.transform.enabled"; + + public static final String SHIBBOLETH_HEADER_AFFILIATION_PREFIX = "shibboleth.header.affiliation.prefix"; + + public static final String SHIBBOLETH_USER_ROLE_AUTO_CREATE = "shibboleth.user.role.auto.create"; +} diff --git a/src/main/java/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.java b/src/main/java/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.java new file mode 100644 index 0000000000000000000000000000000000000000..e7b06840776fa6533a50e185d589b89d309aa2c7 --- /dev/null +++ b/src/main/java/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.java @@ -0,0 +1,48 @@ +package com.liferay.portal.shibboleth.util; + +import com.liferay.portal.kernel.util.GetterUtil; +import com.liferay.portal.kernel.util.PropsUtil; + +/** + * @author Romeo Sheshi + * @author Ivan Novakov <ivan.novakov@debug.cz> + */ +public class ShibbolethPropsValues { + public static final boolean SHIBBOLETH_ENABLED = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_ENABLED)); + + public static final String SHIBBOLETH_HEADER = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADER); + + public static final String SHIBBOLETH_HEADER_EMAIL = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADER_EMAIL); + + public static final String SHIBBOLETH_HEADER_FIRSTNAME = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADER_FIRSTNAME); + + public static final String SHIBBOLETH_HEADER_SURNAME = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADER_SURNAME); + + public static final String SHIBBOLETH_HEADER_AFFILIATION = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADER_AFFILIATION); + + public static final boolean SHIBBOLETH_USER_AUTO_CREATE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_USER_AUTO_CREATE)); + + public static final boolean SHIBBOLETH_USER_AUTO_UPDATE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_USER_AUTO_UPDATE)); + + public static final boolean SHIBBOLETH_USER_LDAP_IMPORT = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_USER_LDAP_IMPORT)); + + public static final boolean SHIBBOLETH_USER_ROLE_AUTO_ASSIGN = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_USER_ROLE_AUTO_ASSIGN)); + + public static final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE); + + public static final boolean SHIBBOLETH_LOGOUT_ENABLE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_LOGOUT_ENABLE)); + + public static final boolean SHIBBOLETH_HEADERS_ENABLE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADERS_ENABLE)); + + public static final boolean SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE)); + + public static final boolean SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE)); + + public static final String SHIBBOLETH_LOGIN_URL = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_LOGIN_URL); + + public static final String SHIBBOLETH_LOGOUT_URL = PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_LOGOUT_URL); + + public static final String SHIBBOLETH_HEADER_AFFILIATION_PREFIX= PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_HEADER_AFFILIATION_PREFIX); + + public static final boolean SHIBBOLETH_USER_ROLE_AUTO_CREATE = GetterUtil.getBoolean(PropsUtil.get(ShibbolethPropsKeys.SHIBBOLETH_USER_ROLE_AUTO_CREATE)); +} diff --git a/src/main/java/com/liferay/portal/shibboleth/util/Util.java b/src/main/java/com/liferay/portal/shibboleth/util/Util.java new file mode 100644 index 0000000000000000000000000000000000000000..bd99320ab7f5f08eca0f01748f0af553caa07603 --- /dev/null +++ b/src/main/java/com/liferay/portal/shibboleth/util/Util.java @@ -0,0 +1,120 @@ +package com.liferay.portal.shibboleth.util; + +import com.liferay.portal.kernel.util.GetterUtil; +import com.liferay.portal.kernel.util.PrefsPropsUtil; +import com.liferay.portal.kernel.util.PropsKeys; +import com.liferay.portal.model.CompanyConstants; + +/** + * + * @author Romeo Sheshi + * @author Ivan Novakov <ivan.novakov@debug.cz> + */ +public final class Util { + private Util() { + } + + public static boolean isEnabled(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_ENABLED), + ShibbolethPropsValues.SHIBBOLETH_ENABLED); + } + + public static boolean isLogoutEnabled(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_LOGOUT_ENABLE), + ShibbolethPropsValues.SHIBBOLETH_LOGOUT_ENABLE); + } + + public static boolean isHeadersEnabled(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADERS_ENABLE), + ShibbolethPropsValues.SHIBBOLETH_HEADERS_ENABLE); + } + + public static boolean isAffiliationTruncateEnabled(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE), + ShibbolethPropsValues.SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE); + } + + public static boolean isScreenNameTransformEnabled(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE), + ShibbolethPropsValues.SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE); + } + + public static boolean importUser(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_USER_LDAP_IMPORT), + ShibbolethPropsValues.SHIBBOLETH_USER_LDAP_IMPORT); + } + + public static String getLoginUrl(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_LOGIN_URL), + ShibbolethPropsValues.SHIBBOLETH_LOGIN_URL); + } + + public static String getLogoutUrl(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_LOGOUT_URL), + ShibbolethPropsValues.SHIBBOLETH_LOGOUT_URL); + } + + public static String getHeaderName(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADER), + ShibbolethPropsValues.SHIBBOLETH_HEADER); + } + + public static String getEmailHeaderName(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADER_EMAIL), + ShibbolethPropsValues.SHIBBOLETH_HEADER_EMAIL); + } + + public static String getFirstnameHeaderName(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADER_FIRSTNAME), + ShibbolethPropsValues.SHIBBOLETH_HEADER_FIRSTNAME); + } + + public static String getSurnameHeaderName(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADER_SURNAME), + ShibbolethPropsValues.SHIBBOLETH_HEADER_SURNAME); + } + + public static String getAffiliationHeaderName(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADER_AFFILIATION), + ShibbolethPropsValues.SHIBBOLETH_HEADER_AFFILIATION); + } + + public static boolean autoCreateUser(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_USER_AUTO_CREATE), + ShibbolethPropsValues.SHIBBOLETH_USER_AUTO_CREATE); + } + + public static boolean autoUpdateUser(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_USER_AUTO_UPDATE), + ShibbolethPropsValues.SHIBBOLETH_USER_AUTO_UPDATE); + } + + public static boolean autoAssignUserRole(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_USER_ROLE_AUTO_ASSIGN), + ShibbolethPropsValues.SHIBBOLETH_USER_ROLE_AUTO_ASSIGN); + } + + public static String autoAssignUserRoleSubtype(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE), + ShibbolethPropsValues.SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE); + } + + public static String getAuthType(long companyId) throws Exception { + return GetterUtil.getString(getValue(companyId, PropsKeys.COMPANY_SECURITY_AUTH_TYPE), + CompanyConstants.AUTH_TYPE_EA); + } + + private static String getValue(long companyId, String key) throws Exception { + return PrefsPropsUtil.getString(companyId, key); + } + + public static String getAffiliationHeaderPrefix(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_HEADER_AFFILIATION_PREFIX), + ShibbolethPropsValues.SHIBBOLETH_HEADER_AFFILIATION_PREFIX); + } + + public static boolean isCreateRoleEnabled(long companyId) throws Exception { + return GetterUtil.get(getValue(companyId, ShibbolethPropsKeys.SHIBBOLETH_USER_ROLE_AUTO_CREATE), + ShibbolethPropsValues.SHIBBOLETH_USER_ROLE_AUTO_CREATE); + } +} diff --git a/src/main/resources/language.properties b/src/main/resources/language.properties new file mode 100644 index 0000000000000000000000000000000000000000..f4af834454d78886f270c87c065f428be26a9b73 --- /dev/null +++ b/src/main/resources/language.properties @@ -0,0 +1,17 @@ +shibboleth-logout-enable=Logout enable +shibboleth-headers-enable=Extract attributes from HTTP Headers instead of environment variables (see: https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPJavaInstall , the "AJP_" prefix part) +shibboleth-affiliation-truncate-enable=Truncate affiliation values and keep only the last segment after ':'. Useful for standard eduPersonEntilement values. ('foo:bar:baz:qux:RoleName' becomes 'RoleName') +shibboleth-screenname-transform-enable=Transform login ID to make it valid screen name. Replace '@' to '.at.' and '_' to '-'. ('foo_bar@baz.org' becomes 'foo-bar.at.baz.org') +import-shibboleth-users-from-ldap=Import from LDAP +shibboleth-user-header=Shibboleth header name +shibboleth-user-id-header=Shibboleth user ID header +shibboleth-user-header-email=Shibboleth user email header +shibboleth-user-header-firstname=Shibboleth user first name header +shibboleth-user-header-surname=Shibboleth user surname header +shibboleth-user-header-affiliation=Shibboleth user affiliation header +auto-create-users=Auto-create users +auto-update-users=Auto-update users +auto-assign-user-role=Auto-assign roles to users (based on the affiliation) +auto-assign-user-role-subtype=Role subtype for auto-assign roles +shibboleth=Shibboleth +shibboleth-user-header-affiliation-prefix=Shibboleth user affiliation header prefix diff --git a/src/main/resources/portal.properties b/src/main/resources/portal.properties new file mode 100644 index 0000000000000000000000000000000000000000..8059041ab2e81cc92f9b0f9fb4126d4a745018f7 --- /dev/null +++ b/src/main/resources/portal.properties @@ -0,0 +1,19 @@ +auto.login.hooks=com.liferay.portal.security.auth.ShibbolethAutoLogin + +shibboleth.enabled=true +shibboleth.header=eppn +shibboleth.header.email=eppn +shibboleth.header.firstname=givenName +shibboleth.header.surname=sn +shibboleth.user.auto.create=true +shibboleth.user.auto.update=true +shibboleth.user.ldap.import=false +shibboleth.logout.enabled=true +shibboleth.headers.enabled=false +shibboleth.affiliation.truncate.enabled=false +shibboleth.screenname.transform.enabled=true +shibboleth.login.url=/c/portal/login/shibboleth +shibboleth.logout.url=/Shibboleth.sso/Logout?return=/ +company.settings.form.authentication=shibboleth + +login.form.navigation.pre=shibboleth \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsps/html/portlet/login/navigation/shibboleth.jsp b/src/main/webapp/WEB-INF/jsps/html/portlet/login/navigation/shibboleth.jsp new file mode 100644 index 0000000000000000000000000000000000000000..48fa3ba38bbd2005a8fd9db5abfc164f8079f170 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsps/html/portlet/login/navigation/shibboleth.jsp @@ -0,0 +1,18 @@ +<%@ include file="/html/portlet/login/init.jsp"%> + +<% + + final String SHIBBOLETH_ENABLED = "shibboleth.enabled"; + final String SHIBBOLETH_LOGIN_URL = "shibboleth.login.url"; + + boolean shibbolethEnabled = GetterUtil.getBoolean(PrefsPropsUtil.getString(PortalUtil.getCompanyId(renderRequest), SHIBBOLETH_ENABLED)); + String shibbolethLoginUrl = PrefsPropsUtil.getString(company.getCompanyId(), "shibboleth.login.url", ""); +%> + +<c:if test="<%=shibbolethEnabled%>"> + + <liferay-ui:icon + src="/liferay-shibboleth-plugin-hook/images/shibboleth.png" + url="<%= shibbolethLoginUrl %>" message="shibboleth" /> + +</c:if> diff --git a/src/main/webapp/WEB-INF/jsps/html/portlet/portal_settings/authentication/shibboleth.jsp b/src/main/webapp/WEB-INF/jsps/html/portlet/portal_settings/authentication/shibboleth.jsp new file mode 100644 index 0000000000000000000000000000000000000000..10cea50f8207f5e494e122b6de6a040e34d2799b --- /dev/null +++ b/src/main/webapp/WEB-INF/jsps/html/portlet/portal_settings/authentication/shibboleth.jsp @@ -0,0 +1,96 @@ +<%@ include file="/html/portlet/portal_settings/init.jsp" %> +<% + final String SHIBBOLETH_ENABLED = "shibboleth.enabled"; + final String SHIBBOLETH_HEADER = "shibboleth.header"; + final String SHIBBOLETH_USER_LDAP_IMPORT = "shibboleth.user.ldap.import"; + final String SHIBBOLETH_LOGOUT_ENABLE = "shibboleth.logout.enabled"; + final String SHIBBOLETH_LOGOUT_URL = "shibboleth.logout.url"; + final String SHIBBOLETH_LOGIN_URL = "shibboleth.login.url"; + final String SHIBBOLETH_HEADERS_ENABLE = "shibboleth.headers.enabled"; + final String SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE = "shibboleth.affiliation.truncate.enabled"; + final String SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE = "shibboleth.screenname.transform.enabled"; + + final String SHIBBOLETH_HEADER_EMAIL = "shibboleth.header.email"; + final String SHIBBOLETH_HEADER_FIRSTNAME = "shibboleth.header.firstname"; + final String SHIBBOLETH_HEADER_SURNAME = "shibboleth.header.surname"; + final String SHIBBOLETH_HEADER_AFFILIATION = "shibboleth.header.affiliation"; + final String SHIBBOLETH_USER_AUTO_CREATE = "shibboleth.user.auto.create"; + final String SHIBBOLETH_USER_AUTO_UPDATE = "shibboleth.user.auto.update"; + final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN = "shibboleth.user.role.auto.assign"; + final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE = "shibboleth.user.role.auto.assign.subtype"; + final String SHIBBOLETH_HEADER_AFFILIATION_PREFIX = "shibboleth.header.affiliation.prefix"; + final String SHIBBOLETH_USER_ROLE_AUTO_CREATE = "shibboleth.user.role.auto.create"; + + String shibbolethEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_ENABLED, "false"); + String shibbolethHeader = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER, ""); + String shibbolethUserLdapImport = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_LDAP_IMPORT, "false"); + String shibbolethLogoutEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_LOGOUT_ENABLE, "false"); + String shibbolethLogoutUrl = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_LOGOUT_URL, ""); + String shibbolethLoginUrl = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_LOGIN_URL, ""); + String shibbolethHeadersEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADERS_ENABLE, "false"); + String shibbolethAffiliationTruncateEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE, "false"); + String shibbolethScreenNameTransformEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE, "false"); + + String shibbolethHeaderEmail = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_EMAIL, "mail"); + String shibbolethHeaderFirtsname = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_FIRSTNAME, "givenname"); + String shibbolethHeaderSurname = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_SURNAME, "sn"); + String shibbolethHeaderAffiliation = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_AFFILIATION, "affiliation"); + String shibbolethUserAutoCreate = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_AUTO_CREATE, "false"); + String shibbolethUserAutoUpdate = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_AUTO_UPDATE, "false"); + String shibbolethUserRoleAutoAssign = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_ROLE_AUTO_ASSIGN, "false"); + String shibbolethUserRoleAutoAssignSubtype = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE, ""); + String shibbolethHeaderAffiliationPrefix = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_AFFILIATION_PREFIX, ""); + String shibbolethUserRoleAutoCreate = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_ROLE_AUTO_CREATE, "false"); +%> +<aui:fieldset> + <aui:input label="enabled" name='<%="settings--" + SHIBBOLETH_ENABLED + "--" %>' type="checkbox" + value="<%= shibbolethEnabled %>"/> + <aui:input cssCLass="lfr-input-text-container" label="login-url" + name='<%= "settings--" + SHIBBOLETH_LOGIN_URL + "--" %>' type="text" + value="<%= shibbolethLoginUrl %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-id-header" + name='<%= "settings--" + SHIBBOLETH_HEADER + "--" %>' type="text" value="<%= shibbolethHeader %>"/> + <aui:input label="shibboleth-screenname-transform-enable" name='<%= "settings--" + SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethScreenNameTransformEnabled %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-email" + name='<%= "settings--" + SHIBBOLETH_HEADER_EMAIL + "--" %>' type="text" value="<%= shibbolethHeaderEmail %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-firstname" + name='<%= "settings--" + SHIBBOLETH_HEADER_FIRSTNAME + "--" %>' type="text" value="<%= shibbolethHeaderFirtsname %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-surname" + name='<%= "settings--" + SHIBBOLETH_HEADER_SURNAME + "--" %>' type="text" value="<%= shibbolethHeaderSurname %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-affiliation" + name='<%= "settings--" + SHIBBOLETH_HEADER_AFFILIATION + "--" %>' type="text" value="<%= shibbolethHeaderAffiliation %>"/> + <aui:input label="shibboleth-affiliation-truncate-enable" name='<%= "settings--" + SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethAffiliationTruncateEnabled %>"/> + <aui:input label="auto-create-users" + name='<%= "settings--" + SHIBBOLETH_USER_AUTO_CREATE + "--" %>' type="checkbox" + value="<%= shibbolethUserAutoCreate %>"/> + <aui:input label="auto-update-users" + name='<%= "settings--" + SHIBBOLETH_USER_AUTO_UPDATE + "--" %>' type="checkbox" + value="<%= shibbolethUserAutoUpdate %>"/> + <aui:input label="import-shibboleth-users-from-ldap" + name='<%= "settings--" + SHIBBOLETH_USER_LDAP_IMPORT + "--" %>' type="checkbox" + value="<%= shibbolethUserLdapImport %>"/> + <aui:input label="auto-create-user-role" + name='<%= "settings--" + SHIBBOLETH_USER_ROLE_AUTO_CREATE + "--" %>' type="checkbox" + value="<%= shibbolethUserRoleAutoCreate %>"/> + <aui:input label="auto-assign-user-role" + name='<%= "settings--" + SHIBBOLETH_USER_ROLE_AUTO_ASSIGN + "--" %>' type="checkbox" + value="<%= shibbolethUserRoleAutoAssign %>"/> + <aui:input cssClass="lfr-input-text-container" label="auto-assign-user-role-subtype" + name='<%= "settings--" + SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE + "--" %>' type="text" + value="<%= shibbolethUserRoleAutoAssignSubtype %>"/> + <aui:input label="shibboleth-logout-enable" name='<%= "settings--" + SHIBBOLETH_LOGOUT_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethLogoutEnabled %>"/> + <aui:input cssClass="lfr-input-text-container" label="logout-url" + name='<%= "settings--" + SHIBBOLETH_LOGOUT_URL + "--" %>' type="text" + value="<%= shibbolethLogoutUrl %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-affiliation-prefix" + name='<%= "settings--" + SHIBBOLETH_HEADER_AFFILIATION_PREFIX + "--" %>' type="text" + value="<%= shibbolethHeaderAffiliationPrefix %>"/> + <aui:input label="shibboleth-headers-enable" name='<%= "settings--" + SHIBBOLETH_HEADERS_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethHeadersEnabled %>"/> +</aui:fieldset> + + + diff --git a/src/main/webapp/WEB-INF/liferay-hook.xml b/src/main/webapp/WEB-INF/liferay-hook.xml new file mode 100644 index 0000000000000000000000000000000000000000..d230f19f6590c8eb3b5f9415bcd64579a3422ec9 --- /dev/null +++ b/src/main/webapp/WEB-INF/liferay-hook.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd"> + +<hook> + <portal-properties>portal.properties</portal-properties> + <language-properties>language.properties</language-properties> + <custom-jsp-dir>/WEB-INF/jsps</custom-jsp-dir> + <servlet-filter> + <servlet-filter-name>shibboleth</servlet-filter-name> + <servlet-filter-impl>com.liferay.portal.servlet.filters.sso.shibboleth.ShibbolethFilter</servlet-filter-impl> + </servlet-filter> + <servlet-filter-mapping> + <servlet-filter-name>shibboleth</servlet-filter-name> + <after-filter>Auto Login Filter</after-filter> + <url-pattern>/c/portal/login</url-pattern> + <url-pattern>/c/portal/logout</url-pattern> + <dispatcher>FORWARD</dispatcher> + <dispatcher>REQUEST</dispatcher> + </servlet-filter-mapping> +</hook> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/liferay-plugin-package.properties b/src/main/webapp/WEB-INF/liferay-plugin-package.properties new file mode 100644 index 0000000000000000000000000000000000000000..86d6fe22320409a1e654329163293c99d3a6bf6e --- /dev/null +++ b/src/main/webapp/WEB-INF/liferay-plugin-package.properties @@ -0,0 +1,10 @@ +name=Shibboleth Plugin +module-group-id=liferay 7.1.1 +module-incremental-version=1 +tags= +short-description= +change-log= +page-url=https://github.com/ivan-novakov/liferay-shibboleth-plugin +author=Ivan Novakov ivan.novakov@debug.cz +page-url=http://code.google.com/p/liferay-shibboleth-plugin/ +author=Romeo Sheshi rsheshi@gmail.com diff --git a/src/main/webapp/WEB-INF/liferay-plugin-package.xml b/src/main/webapp/WEB-INF/liferay-plugin-package.xml new file mode 100644 index 0000000000000000000000000000000000000000..80a18d1fd55e530478ec7d4a3eb912c84d62723e --- /dev/null +++ b/src/main/webapp/WEB-INF/liferay-plugin-package.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plugin-package PUBLIC "-//Liferay//DTD Plugin Package 6.2.0//EN" + "http://www.liferay.com/dtd/liferay-plugin-package_6_2_0.dtd"> +<plugin-package> + <name>Shibboleth Plugin</name> + <module-id>${project.groupId}/${project.artifactId}/${project.version}/${project.packaging}</module-id> + <types> + <type>portlets</type> + </types> + <tags> + <tag>shibboleth</tag> + </tags> + <short-description/> + <change-log/> + <page-url>https://github.com/ivan-novakov/liferay-shibboleth-plugin</page-url> + <author>Ivan Novakov ivan.novakov@debug.cz</author> + <licenses> + <license osi-approved="true">LGPL</license> + </licenses> + <liferay-versions> + <liferay-version>6.2.0+</liferay-version> + </liferay-versions> +</plugin-package> \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000000000000000000000000000000000..e067cae3a8db64f6119dd5338aea97484fc75950 --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,5 @@ +<?xml version="1.0"?> + +<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> +</web-app> \ No newline at end of file diff --git a/src/main/webapp/images/shibboleth.png b/src/main/webapp/images/shibboleth.png new file mode 100644 index 0000000000000000000000000000000000000000..b706062e24071a25c7f70ec9770fe7191b7d4768 Binary files /dev/null and b/src/main/webapp/images/shibboleth.png differ diff --git a/target/classes/com/liferay/portal/security/auth/ShibbolethAutoLogin.class b/target/classes/com/liferay/portal/security/auth/ShibbolethAutoLogin.class new file mode 100644 index 0000000000000000000000000000000000000000..64c7e80bd14ece4dd68368dddcbfc5947d0f8ebf Binary files /dev/null and b/target/classes/com/liferay/portal/security/auth/ShibbolethAutoLogin.class differ diff --git a/target/classes/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.class b/target/classes/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.class new file mode 100644 index 0000000000000000000000000000000000000000..fcf3394bd41b00be8bb984e100a6e6a9441779b6 Binary files /dev/null and b/target/classes/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.class differ diff --git a/target/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.class b/target/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.class new file mode 100644 index 0000000000000000000000000000000000000000..1c81cd108a748ee4c78dca59f68f355c9afedc29 Binary files /dev/null and b/target/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.class differ diff --git a/target/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.class b/target/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.class new file mode 100644 index 0000000000000000000000000000000000000000..0c55c04ba3d01f9eb49f94125ea3925b030560f1 Binary files /dev/null and b/target/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.class differ diff --git a/target/classes/com/liferay/portal/shibboleth/util/Util.class b/target/classes/com/liferay/portal/shibboleth/util/Util.class new file mode 100644 index 0000000000000000000000000000000000000000..d6baffff35d7f4c16c6575b228cf40a43e1a7629 Binary files /dev/null and b/target/classes/com/liferay/portal/shibboleth/util/Util.class differ diff --git a/target/classes/language.properties b/target/classes/language.properties new file mode 100644 index 0000000000000000000000000000000000000000..f4af834454d78886f270c87c065f428be26a9b73 --- /dev/null +++ b/target/classes/language.properties @@ -0,0 +1,17 @@ +shibboleth-logout-enable=Logout enable +shibboleth-headers-enable=Extract attributes from HTTP Headers instead of environment variables (see: https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPJavaInstall , the "AJP_" prefix part) +shibboleth-affiliation-truncate-enable=Truncate affiliation values and keep only the last segment after ':'. Useful for standard eduPersonEntilement values. ('foo:bar:baz:qux:RoleName' becomes 'RoleName') +shibboleth-screenname-transform-enable=Transform login ID to make it valid screen name. Replace '@' to '.at.' and '_' to '-'. ('foo_bar@baz.org' becomes 'foo-bar.at.baz.org') +import-shibboleth-users-from-ldap=Import from LDAP +shibboleth-user-header=Shibboleth header name +shibboleth-user-id-header=Shibboleth user ID header +shibboleth-user-header-email=Shibboleth user email header +shibboleth-user-header-firstname=Shibboleth user first name header +shibboleth-user-header-surname=Shibboleth user surname header +shibboleth-user-header-affiliation=Shibboleth user affiliation header +auto-create-users=Auto-create users +auto-update-users=Auto-update users +auto-assign-user-role=Auto-assign roles to users (based on the affiliation) +auto-assign-user-role-subtype=Role subtype for auto-assign roles +shibboleth=Shibboleth +shibboleth-user-header-affiliation-prefix=Shibboleth user affiliation header prefix diff --git a/target/classes/portal.properties b/target/classes/portal.properties new file mode 100644 index 0000000000000000000000000000000000000000..8059041ab2e81cc92f9b0f9fb4126d4a745018f7 --- /dev/null +++ b/target/classes/portal.properties @@ -0,0 +1,19 @@ +auto.login.hooks=com.liferay.portal.security.auth.ShibbolethAutoLogin + +shibboleth.enabled=true +shibboleth.header=eppn +shibboleth.header.email=eppn +shibboleth.header.firstname=givenName +shibboleth.header.surname=sn +shibboleth.user.auto.create=true +shibboleth.user.auto.update=true +shibboleth.user.ldap.import=false +shibboleth.logout.enabled=true +shibboleth.headers.enabled=false +shibboleth.affiliation.truncate.enabled=false +shibboleth.screenname.transform.enabled=true +shibboleth.login.url=/c/portal/login/shibboleth +shibboleth.logout.url=/Shibboleth.sso/Logout?return=/ +company.settings.form.authentication=shibboleth + +login.form.navigation.pre=shibboleth \ No newline at end of file diff --git a/target/maven-archiver/pom.properties b/target/maven-archiver/pom.properties new file mode 100644 index 0000000000000000000000000000000000000000..908d59d39380b78742de95dfe5ebeccf05ff0011 --- /dev/null +++ b/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Tue Jul 05 11:42:51 CEST 2016 +version=1.2 +groupId=com.github.ivan-novakov.liferay-shibboleth-plugin +artifactId=liferay-shibboleth-plugin diff --git a/target/shibboleth-plugin-hook.war b/target/shibboleth-plugin-hook.war new file mode 100644 index 0000000000000000000000000000000000000000..332fa5e5f67614f68ce8e9a71567d35edf1ddcab Binary files /dev/null and b/target/shibboleth-plugin-hook.war differ diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/security/auth/ShibbolethAutoLogin.class b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/security/auth/ShibbolethAutoLogin.class new file mode 100644 index 0000000000000000000000000000000000000000..64c7e80bd14ece4dd68368dddcbfc5947d0f8ebf Binary files /dev/null and b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/security/auth/ShibbolethAutoLogin.class differ diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.class b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.class new file mode 100644 index 0000000000000000000000000000000000000000..fcf3394bd41b00be8bb984e100a6e6a9441779b6 Binary files /dev/null and b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/servlet/filters/sso/shibboleth/ShibbolethFilter.class differ diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.class b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.class new file mode 100644 index 0000000000000000000000000000000000000000..1c81cd108a748ee4c78dca59f68f355c9afedc29 Binary files /dev/null and b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsKeys.class differ diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.class b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.class new file mode 100644 index 0000000000000000000000000000000000000000..0c55c04ba3d01f9eb49f94125ea3925b030560f1 Binary files /dev/null and b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/ShibbolethPropsValues.class differ diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/Util.class b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/Util.class new file mode 100644 index 0000000000000000000000000000000000000000..d6baffff35d7f4c16c6575b228cf40a43e1a7629 Binary files /dev/null and b/target/shibboleth-plugin-hook/WEB-INF/classes/com/liferay/portal/shibboleth/util/Util.class differ diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/language.properties b/target/shibboleth-plugin-hook/WEB-INF/classes/language.properties new file mode 100644 index 0000000000000000000000000000000000000000..f4af834454d78886f270c87c065f428be26a9b73 --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/classes/language.properties @@ -0,0 +1,17 @@ +shibboleth-logout-enable=Logout enable +shibboleth-headers-enable=Extract attributes from HTTP Headers instead of environment variables (see: https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPJavaInstall , the "AJP_" prefix part) +shibboleth-affiliation-truncate-enable=Truncate affiliation values and keep only the last segment after ':'. Useful for standard eduPersonEntilement values. ('foo:bar:baz:qux:RoleName' becomes 'RoleName') +shibboleth-screenname-transform-enable=Transform login ID to make it valid screen name. Replace '@' to '.at.' and '_' to '-'. ('foo_bar@baz.org' becomes 'foo-bar.at.baz.org') +import-shibboleth-users-from-ldap=Import from LDAP +shibboleth-user-header=Shibboleth header name +shibboleth-user-id-header=Shibboleth user ID header +shibboleth-user-header-email=Shibboleth user email header +shibboleth-user-header-firstname=Shibboleth user first name header +shibboleth-user-header-surname=Shibboleth user surname header +shibboleth-user-header-affiliation=Shibboleth user affiliation header +auto-create-users=Auto-create users +auto-update-users=Auto-update users +auto-assign-user-role=Auto-assign roles to users (based on the affiliation) +auto-assign-user-role-subtype=Role subtype for auto-assign roles +shibboleth=Shibboleth +shibboleth-user-header-affiliation-prefix=Shibboleth user affiliation header prefix diff --git a/target/shibboleth-plugin-hook/WEB-INF/classes/portal.properties b/target/shibboleth-plugin-hook/WEB-INF/classes/portal.properties new file mode 100644 index 0000000000000000000000000000000000000000..8059041ab2e81cc92f9b0f9fb4126d4a745018f7 --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/classes/portal.properties @@ -0,0 +1,19 @@ +auto.login.hooks=com.liferay.portal.security.auth.ShibbolethAutoLogin + +shibboleth.enabled=true +shibboleth.header=eppn +shibboleth.header.email=eppn +shibboleth.header.firstname=givenName +shibboleth.header.surname=sn +shibboleth.user.auto.create=true +shibboleth.user.auto.update=true +shibboleth.user.ldap.import=false +shibboleth.logout.enabled=true +shibboleth.headers.enabled=false +shibboleth.affiliation.truncate.enabled=false +shibboleth.screenname.transform.enabled=true +shibboleth.login.url=/c/portal/login/shibboleth +shibboleth.logout.url=/Shibboleth.sso/Logout?return=/ +company.settings.form.authentication=shibboleth + +login.form.navigation.pre=shibboleth \ No newline at end of file diff --git a/target/shibboleth-plugin-hook/WEB-INF/jsps/html/portlet/login/navigation/shibboleth.jsp b/target/shibboleth-plugin-hook/WEB-INF/jsps/html/portlet/login/navigation/shibboleth.jsp new file mode 100644 index 0000000000000000000000000000000000000000..48fa3ba38bbd2005a8fd9db5abfc164f8079f170 --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/jsps/html/portlet/login/navigation/shibboleth.jsp @@ -0,0 +1,18 @@ +<%@ include file="/html/portlet/login/init.jsp"%> + +<% + + final String SHIBBOLETH_ENABLED = "shibboleth.enabled"; + final String SHIBBOLETH_LOGIN_URL = "shibboleth.login.url"; + + boolean shibbolethEnabled = GetterUtil.getBoolean(PrefsPropsUtil.getString(PortalUtil.getCompanyId(renderRequest), SHIBBOLETH_ENABLED)); + String shibbolethLoginUrl = PrefsPropsUtil.getString(company.getCompanyId(), "shibboleth.login.url", ""); +%> + +<c:if test="<%=shibbolethEnabled%>"> + + <liferay-ui:icon + src="/liferay-shibboleth-plugin-hook/images/shibboleth.png" + url="<%= shibbolethLoginUrl %>" message="shibboleth" /> + +</c:if> diff --git a/target/shibboleth-plugin-hook/WEB-INF/jsps/html/portlet/portal_settings/authentication/shibboleth.jsp b/target/shibboleth-plugin-hook/WEB-INF/jsps/html/portlet/portal_settings/authentication/shibboleth.jsp new file mode 100644 index 0000000000000000000000000000000000000000..10cea50f8207f5e494e122b6de6a040e34d2799b --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/jsps/html/portlet/portal_settings/authentication/shibboleth.jsp @@ -0,0 +1,96 @@ +<%@ include file="/html/portlet/portal_settings/init.jsp" %> +<% + final String SHIBBOLETH_ENABLED = "shibboleth.enabled"; + final String SHIBBOLETH_HEADER = "shibboleth.header"; + final String SHIBBOLETH_USER_LDAP_IMPORT = "shibboleth.user.ldap.import"; + final String SHIBBOLETH_LOGOUT_ENABLE = "shibboleth.logout.enabled"; + final String SHIBBOLETH_LOGOUT_URL = "shibboleth.logout.url"; + final String SHIBBOLETH_LOGIN_URL = "shibboleth.login.url"; + final String SHIBBOLETH_HEADERS_ENABLE = "shibboleth.headers.enabled"; + final String SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE = "shibboleth.affiliation.truncate.enabled"; + final String SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE = "shibboleth.screenname.transform.enabled"; + + final String SHIBBOLETH_HEADER_EMAIL = "shibboleth.header.email"; + final String SHIBBOLETH_HEADER_FIRSTNAME = "shibboleth.header.firstname"; + final String SHIBBOLETH_HEADER_SURNAME = "shibboleth.header.surname"; + final String SHIBBOLETH_HEADER_AFFILIATION = "shibboleth.header.affiliation"; + final String SHIBBOLETH_USER_AUTO_CREATE = "shibboleth.user.auto.create"; + final String SHIBBOLETH_USER_AUTO_UPDATE = "shibboleth.user.auto.update"; + final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN = "shibboleth.user.role.auto.assign"; + final String SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE = "shibboleth.user.role.auto.assign.subtype"; + final String SHIBBOLETH_HEADER_AFFILIATION_PREFIX = "shibboleth.header.affiliation.prefix"; + final String SHIBBOLETH_USER_ROLE_AUTO_CREATE = "shibboleth.user.role.auto.create"; + + String shibbolethEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_ENABLED, "false"); + String shibbolethHeader = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER, ""); + String shibbolethUserLdapImport = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_LDAP_IMPORT, "false"); + String shibbolethLogoutEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_LOGOUT_ENABLE, "false"); + String shibbolethLogoutUrl = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_LOGOUT_URL, ""); + String shibbolethLoginUrl = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_LOGIN_URL, ""); + String shibbolethHeadersEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADERS_ENABLE, "false"); + String shibbolethAffiliationTruncateEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE, "false"); + String shibbolethScreenNameTransformEnabled = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE, "false"); + + String shibbolethHeaderEmail = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_EMAIL, "mail"); + String shibbolethHeaderFirtsname = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_FIRSTNAME, "givenname"); + String shibbolethHeaderSurname = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_SURNAME, "sn"); + String shibbolethHeaderAffiliation = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_AFFILIATION, "affiliation"); + String shibbolethUserAutoCreate = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_AUTO_CREATE, "false"); + String shibbolethUserAutoUpdate = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_AUTO_UPDATE, "false"); + String shibbolethUserRoleAutoAssign = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_ROLE_AUTO_ASSIGN, "false"); + String shibbolethUserRoleAutoAssignSubtype = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE, ""); + String shibbolethHeaderAffiliationPrefix = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_HEADER_AFFILIATION_PREFIX, ""); + String shibbolethUserRoleAutoCreate = PrefsPropsUtil.getString(company.getCompanyId(), SHIBBOLETH_USER_ROLE_AUTO_CREATE, "false"); +%> +<aui:fieldset> + <aui:input label="enabled" name='<%="settings--" + SHIBBOLETH_ENABLED + "--" %>' type="checkbox" + value="<%= shibbolethEnabled %>"/> + <aui:input cssCLass="lfr-input-text-container" label="login-url" + name='<%= "settings--" + SHIBBOLETH_LOGIN_URL + "--" %>' type="text" + value="<%= shibbolethLoginUrl %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-id-header" + name='<%= "settings--" + SHIBBOLETH_HEADER + "--" %>' type="text" value="<%= shibbolethHeader %>"/> + <aui:input label="shibboleth-screenname-transform-enable" name='<%= "settings--" + SHIBBOLETH_SCREENNAME_TRANSFORM_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethScreenNameTransformEnabled %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-email" + name='<%= "settings--" + SHIBBOLETH_HEADER_EMAIL + "--" %>' type="text" value="<%= shibbolethHeaderEmail %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-firstname" + name='<%= "settings--" + SHIBBOLETH_HEADER_FIRSTNAME + "--" %>' type="text" value="<%= shibbolethHeaderFirtsname %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-surname" + name='<%= "settings--" + SHIBBOLETH_HEADER_SURNAME + "--" %>' type="text" value="<%= shibbolethHeaderSurname %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-affiliation" + name='<%= "settings--" + SHIBBOLETH_HEADER_AFFILIATION + "--" %>' type="text" value="<%= shibbolethHeaderAffiliation %>"/> + <aui:input label="shibboleth-affiliation-truncate-enable" name='<%= "settings--" + SHIBBOLETH_AFFILIATION_TRUNCATE_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethAffiliationTruncateEnabled %>"/> + <aui:input label="auto-create-users" + name='<%= "settings--" + SHIBBOLETH_USER_AUTO_CREATE + "--" %>' type="checkbox" + value="<%= shibbolethUserAutoCreate %>"/> + <aui:input label="auto-update-users" + name='<%= "settings--" + SHIBBOLETH_USER_AUTO_UPDATE + "--" %>' type="checkbox" + value="<%= shibbolethUserAutoUpdate %>"/> + <aui:input label="import-shibboleth-users-from-ldap" + name='<%= "settings--" + SHIBBOLETH_USER_LDAP_IMPORT + "--" %>' type="checkbox" + value="<%= shibbolethUserLdapImport %>"/> + <aui:input label="auto-create-user-role" + name='<%= "settings--" + SHIBBOLETH_USER_ROLE_AUTO_CREATE + "--" %>' type="checkbox" + value="<%= shibbolethUserRoleAutoCreate %>"/> + <aui:input label="auto-assign-user-role" + name='<%= "settings--" + SHIBBOLETH_USER_ROLE_AUTO_ASSIGN + "--" %>' type="checkbox" + value="<%= shibbolethUserRoleAutoAssign %>"/> + <aui:input cssClass="lfr-input-text-container" label="auto-assign-user-role-subtype" + name='<%= "settings--" + SHIBBOLETH_USER_ROLE_AUTO_ASSIGN_SUBTYPE + "--" %>' type="text" + value="<%= shibbolethUserRoleAutoAssignSubtype %>"/> + <aui:input label="shibboleth-logout-enable" name='<%= "settings--" + SHIBBOLETH_LOGOUT_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethLogoutEnabled %>"/> + <aui:input cssClass="lfr-input-text-container" label="logout-url" + name='<%= "settings--" + SHIBBOLETH_LOGOUT_URL + "--" %>' type="text" + value="<%= shibbolethLogoutUrl %>"/> + <aui:input cssClass="lfr-input-text-container" label="shibboleth-user-header-affiliation-prefix" + name='<%= "settings--" + SHIBBOLETH_HEADER_AFFILIATION_PREFIX + "--" %>' type="text" + value="<%= shibbolethHeaderAffiliationPrefix %>"/> + <aui:input label="shibboleth-headers-enable" name='<%= "settings--" + SHIBBOLETH_HEADERS_ENABLE + "--" %>' + type="checkbox" value="<%= shibbolethHeadersEnabled %>"/> +</aui:fieldset> + + + diff --git a/target/shibboleth-plugin-hook/WEB-INF/liferay-hook.xml b/target/shibboleth-plugin-hook/WEB-INF/liferay-hook.xml new file mode 100644 index 0000000000000000000000000000000000000000..d230f19f6590c8eb3b5f9415bcd64579a3422ec9 --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/liferay-hook.xml @@ -0,0 +1,20 @@ +<?xml version="1.0"?> +<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd"> + +<hook> + <portal-properties>portal.properties</portal-properties> + <language-properties>language.properties</language-properties> + <custom-jsp-dir>/WEB-INF/jsps</custom-jsp-dir> + <servlet-filter> + <servlet-filter-name>shibboleth</servlet-filter-name> + <servlet-filter-impl>com.liferay.portal.servlet.filters.sso.shibboleth.ShibbolethFilter</servlet-filter-impl> + </servlet-filter> + <servlet-filter-mapping> + <servlet-filter-name>shibboleth</servlet-filter-name> + <after-filter>Auto Login Filter</after-filter> + <url-pattern>/c/portal/login</url-pattern> + <url-pattern>/c/portal/logout</url-pattern> + <dispatcher>FORWARD</dispatcher> + <dispatcher>REQUEST</dispatcher> + </servlet-filter-mapping> +</hook> \ No newline at end of file diff --git a/target/shibboleth-plugin-hook/WEB-INF/liferay-plugin-package.properties b/target/shibboleth-plugin-hook/WEB-INF/liferay-plugin-package.properties new file mode 100644 index 0000000000000000000000000000000000000000..86d6fe22320409a1e654329163293c99d3a6bf6e --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/liferay-plugin-package.properties @@ -0,0 +1,10 @@ +name=Shibboleth Plugin +module-group-id=liferay 7.1.1 +module-incremental-version=1 +tags= +short-description= +change-log= +page-url=https://github.com/ivan-novakov/liferay-shibboleth-plugin +author=Ivan Novakov ivan.novakov@debug.cz +page-url=http://code.google.com/p/liferay-shibboleth-plugin/ +author=Romeo Sheshi rsheshi@gmail.com diff --git a/target/shibboleth-plugin-hook/WEB-INF/liferay-plugin-package.xml b/target/shibboleth-plugin-hook/WEB-INF/liferay-plugin-package.xml new file mode 100644 index 0000000000000000000000000000000000000000..dbf08c86f7474d44709241cc763ff631d21f4e40 --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/liferay-plugin-package.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plugin-package PUBLIC "-//Liferay//DTD Plugin Package 6.2.0//EN" + "http://www.liferay.com/dtd/liferay-plugin-package_6_2_0.dtd"> +<plugin-package> + <name>Shibboleth Plugin</name> + <module-id>com.github.ivan-novakov.liferay-shibboleth-plugin/liferay-shibboleth-plugin/1.2/war</module-id> + <types> + <type>portlets</type> + </types> + <tags> + <tag>shibboleth</tag> + </tags> + <short-description/> + <change-log/> + <page-url>https://github.com/ivan-novakov/liferay-shibboleth-plugin</page-url> + <author>Ivan Novakov ivan.novakov@debug.cz</author> + <licenses> + <license osi-approved="true">LGPL</license> + </licenses> + <liferay-versions> + <liferay-version>6.2.0+</liferay-version> + </liferay-versions> +</plugin-package> \ No newline at end of file diff --git a/target/shibboleth-plugin-hook/WEB-INF/web.xml b/target/shibboleth-plugin-hook/WEB-INF/web.xml new file mode 100644 index 0000000000000000000000000000000000000000..e067cae3a8db64f6119dd5338aea97484fc75950 --- /dev/null +++ b/target/shibboleth-plugin-hook/WEB-INF/web.xml @@ -0,0 +1,5 @@ +<?xml version="1.0"?> + +<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> +</web-app> \ No newline at end of file diff --git a/target/shibboleth-plugin-hook/images/shibboleth.png b/target/shibboleth-plugin-hook/images/shibboleth.png new file mode 100644 index 0000000000000000000000000000000000000000..b706062e24071a25c7f70ec9770fe7191b7d4768 Binary files /dev/null and b/target/shibboleth-plugin-hook/images/shibboleth.png differ