Difference between revisions of "D4Science Portal HTTPS x509 Certificate Authentication"
(→Liferay Portal Properties) |
|||
(20 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | This is a custom Auto login hook that provides customised authentication for X509 certificate users. | + | == How to configure Apache HTTP server and Apache Tomcat to handle X.509 certificates (full HTTPS) == |
+ | |||
+ | The following setup shows how to configure Apache HTTP server in HTTPS so that X.509 client credentials can be forwarded to an internal Apache Tomcat instance. | ||
+ | |||
+ | === Apache HTTP server === | ||
+ | Two VirtualHost should be configured. The first one to handle HTTP requests on standard port 80, and redirect all of them to port 443 (HTTPS). | ||
+ | |||
+ | <pre> | ||
+ | <VirtualHost *:80> | ||
+ | ServerAdmin webmaster@localhost | ||
+ | ServerName myportal.mydomain.com | ||
+ | |||
+ | DocumentRoot /var/www/ | ||
+ | |||
+ | ErrorLog /var/log/apache2/error.log | ||
+ | CustomLog /var/log/apache2/access.log combined | ||
+ | |||
+ | |||
+ | ProxyPreserveHost on | ||
+ | RewriteEngine on | ||
+ | |||
+ | Redirect permanent / https://myportal.mydomain.com/ | ||
+ | </VirtualHost> | ||
+ | </pre> | ||
+ | |||
+ | The second virtual host is meant to handle HTTPS requests, asking clients to optionally authenticate with an X.509 certificates. | ||
+ | |||
+ | <pre> | ||
+ | <VirtualHost *:443> | ||
+ | ServerAdmin webmaster@localhost | ||
+ | ServerName myportal.mydomain.com | ||
+ | |||
+ | DocumentRoot /var/www/ | ||
+ | <Directory /> | ||
+ | Options FollowSymLinks | ||
+ | AllowOverride None | ||
+ | </Directory> | ||
+ | <Directory /var/www/> | ||
+ | Options Indexes FollowSymLinks MultiViews | ||
+ | AllowOverride None | ||
+ | Order allow,deny | ||
+ | allow from all | ||
+ | </Directory> | ||
+ | |||
+ | ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ | ||
+ | <Directory "/usr/lib/cgi-bin"> | ||
+ | AllowOverride None | ||
+ | Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch | ||
+ | Order allow,deny | ||
+ | Allow from all | ||
+ | </Directory> | ||
+ | |||
+ | ErrorLog /var/log/apache2/error.log | ||
+ | |||
+ | # Possible values include: debug, info, notice, warn, error, crit, | ||
+ | # alert, emerg. | ||
+ | LogLevel warn | ||
+ | |||
+ | CustomLog /var/log/apache2/access.log combined | ||
+ | ServerSignature On | ||
+ | |||
+ | Alias /doc/ "/usr/share/doc/" | ||
+ | <Directory "/usr/share/doc/"> | ||
+ | Options Indexes MultiViews FollowSymLinks | ||
+ | AllowOverride None | ||
+ | Order deny,allow | ||
+ | Deny from all | ||
+ | Allow from 127.0.0.0/255.0.0.0 ::1/128 | ||
+ | </Directory> | ||
+ | |||
+ | SSLEngine on | ||
+ | SSLCertificateFile /etc/apache2/ssl/containercert.pem | ||
+ | SSLCertificateKeyFile /etc/apache2/ssl/containerkey.pem | ||
+ | |||
+ | SSLProxyEngine on | ||
+ | |||
+ | SSLCACertificatePath /etc/grid-security/certificates/ | ||
+ | SSLVerifyClient optional | ||
+ | SSLVerifyDepth 2 | ||
+ | |||
+ | # this option is mandatory to force apache to forward the client cert data to tomcat | ||
+ | SSLOptions +ExportCertData | ||
+ | |||
+ | <Proxy *> | ||
+ | AddDefaultCharset Off | ||
+ | Order deny,allow | ||
+ | Allow from all | ||
+ | </Proxy> | ||
+ | |||
+ | ProxyPass / ajp://localhost:8020/ | ||
+ | ProxyPassReverse / ajp://localhost:8020/ | ||
+ | |||
+ | </VirtualHost> | ||
+ | </pre> | ||
+ | |||
+ | The connection between Apache HTTP Server and Apache Tomcat is done via an AJP connector and Reverse Proxy directive. This means that the following modules need to be installed and loaded into Apache HTTP Server: | ||
+ | * proxy | ||
+ | * proxy_http | ||
+ | * proxy_ajp | ||
+ | |||
+ | to install a new module into apache2 use the following command: | ||
+ | |||
+ | <pre> | ||
+ | a2enmod <module_name> | ||
+ | </pre> | ||
+ | |||
+ | === Apache Tomcat === | ||
+ | |||
+ | An AJP connector needs to be declared in order to enable communication between Apache HTTP Server and Apache Tomcat, with a redirect to port 8443 to handle the HTTPS connection inside Tomcat. | ||
+ | |||
+ | <pre> | ||
+ | <!-- Define an AJP 1.3 Connector on port 8020 --> | ||
+ | <Connector port="8020" | ||
+ | enableLookups="false" redirectPort="8443" protocol="AJP/1.3" URIEncoding="UTF-8" /> | ||
+ | </pre> | ||
+ | |||
+ | Eventually, a Connector needs to declared for port 8443 to handle the HTTPS connection in Tomcat. | ||
+ | |||
+ | <pre> | ||
+ | <Connector port="8443" maxHttpHeaderSize="8192" | ||
+ | maxThreads="150" minSpareThreads="25" maxSpareThreads="75" | ||
+ | enableLookups="false" disableUploadTimeout="true" | ||
+ | acceptCount="100" scheme="https" secure="true" | ||
+ | clientAuth="want" sslProtocol="TLS" emptySessionPath="true" /> | ||
+ | </pre> | ||
+ | |||
+ | == How to configure Apache HTTP server and Apache Tomcat to handle X.509 certificates (HTTPS only for login) == | ||
+ | |||
+ | === Apache HTTP server === | ||
+ | <pre> | ||
+ | NameVirtualHost *:80 | ||
+ | NameVirtualHost *:443 | ||
+ | |||
+ | <VirtualHost *:80> | ||
+ | ServerAdmin webmaster@localhost | ||
+ | ServerName myportal.mydomain.com | ||
+ | |||
+ | DocumentRoot /var/www/ | ||
+ | |||
+ | ErrorLog /var/log/apache2/error.log | ||
+ | CustomLog /var/log/apache2/access.log combined | ||
+ | |||
+ | |||
+ | ProxyPreserveHost on | ||
+ | |||
+ | <Location /> | ||
+ | Allow From All | ||
+ | ProxyPass http://myportal.mydomain.com:9090/ | ||
+ | ProxyPassReverse http://myportal.mydomain.com:9090/ | ||
+ | </Location> | ||
+ | |||
+ | RewriteEngine on | ||
+ | |||
+ | #forces everything under /web/guest/signup to secure if non-secure (https) | ||
+ | RewriteRule ^(/web/guest.*)$ https://myportal.mydomain.com$1 [R,L] | ||
+ | |||
+ | </VirtualHost> | ||
+ | |||
+ | <VirtualHost *:443> | ||
+ | ServerAdmin webmaster@localhost | ||
+ | ServerName myportal.mydomain.com | ||
+ | |||
+ | DocumentRoot /var/www/ | ||
+ | <Directory /> | ||
+ | Options FollowSymLinks | ||
+ | AllowOverride None | ||
+ | </Directory> | ||
+ | <Directory /var/www/> | ||
+ | Options Indexes FollowSymLinks MultiViews | ||
+ | AllowOverride None | ||
+ | Order allow,deny | ||
+ | allow from all | ||
+ | </Directory> | ||
+ | |||
+ | ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ | ||
+ | <Directory "/usr/lib/cgi-bin"> | ||
+ | AllowOverride None | ||
+ | Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch | ||
+ | Order allow,deny | ||
+ | Allow from all | ||
+ | </Directory> | ||
+ | |||
+ | ErrorLog /var/log/apache2/error.log | ||
+ | |||
+ | # Possible values include: debug, info, notice, warn, error, crit, | ||
+ | # alert, emerg. | ||
+ | LogLevel warn | ||
+ | |||
+ | CustomLog /var/log/apache2/access.log combined | ||
+ | ServerSignature On | ||
+ | |||
+ | Alias /doc/ "/usr/share/doc/" | ||
+ | <Directory "/usr/share/doc/"> | ||
+ | Options Indexes MultiViews FollowSymLinks | ||
+ | AllowOverride None | ||
+ | Order deny,allow | ||
+ | Deny from all | ||
+ | Allow from 127.0.0.0/255.0.0.0 ::1/128 | ||
+ | </Directory> | ||
+ | |||
+ | SSLEngine on | ||
+ | SSLCertificateFile /etc/apache2/ssl/containercert.pem | ||
+ | SSLCertificateKeyFile /etc/apache2/ssl/containerkey.pem | ||
+ | |||
+ | SSLProxyEngine on | ||
+ | |||
+ | SSLCACertificatePath /etc/grid-security/certificates/ | ||
+ | SSLVerifyClient optional | ||
+ | SSLVerifyDepth 2 | ||
+ | |||
+ | # this option is mandatory to force apache to forward the client cert data to tomcat | ||
+ | SSLOptions +ExportCertData | ||
+ | |||
+ | RewriteEngine on | ||
+ | |||
+ | #forces everything not under /web/guest/signup to non-secure if secure (http) | ||
+ | RewriteCond %{REQUEST_URI} !^/(web/guest.*)$ | ||
+ | RewriteCond %{REQUEST_URI} !^/(web/guest/change-of-details.*)$ | ||
+ | RewriteCond %{REQUEST_URI} !^/(c/portal/login.*)$ | ||
+ | RewriteCond %{REQUEST_URI} !^/(c/.*)$ | ||
+ | RewriteCond %{REQUEST_URI} !^/(html/.*)$ | ||
+ | RewriteRule ^(.*)$ http://%{SERVER_NAME}$1 [R,L] | ||
+ | |||
+ | <Proxy *> | ||
+ | AddDefaultCharset Off | ||
+ | Order deny,allow | ||
+ | Allow from all | ||
+ | </Proxy> | ||
+ | |||
+ | ProxyPass / ajp://myportal.mydomain.com:8020/ | ||
+ | ProxyPassReverse / ajp://myportal.mydomain.com:8020/ | ||
+ | |||
+ | </VirtualHost> | ||
+ | </pre> | ||
+ | === Apache Tomcat === | ||
+ | Refer to the configuration described in the full HTTPS section | ||
+ | |||
+ | === Liferay Portal Properties === | ||
+ | Make sure that the following lines are appended to the portal-ext.properties file | ||
+ | <pre> | ||
+ | company.security.auth.requires.https=true | ||
+ | session.enable.phishing.protection=false | ||
+ | </pre> | ||
+ | |||
+ | == D4Science Portal HTTPS x509 Certificate Authentication == | ||
+ | |||
+ | This is a custom Auto login hook that provides customised authentication for X509 certificate users.<br/> | ||
'''Set the dev/deploy environment''' | '''Set the dev/deploy environment''' | ||
# Unzip the file [http://inikah2.googlecode.com/files/skeleton-hook.zip] onto your "plugin-sdk/hooks" folder. | # Unzip the file [http://inikah2.googlecode.com/files/skeleton-hook.zip] onto your "plugin-sdk/hooks" folder. | ||
# Copy the AutoLoginCustom.java(please find below) source to the src folder | # Copy the AutoLoginCustom.java(please find below) source to the src folder | ||
− | # Add the following line to portal.properties file: | + | # Add the following line to portal.properties file which is present in the /skeleton-hook/docroot/WEB-INF/src/ folder : |
− | auto.login.hooks=com.liferay.portal.security.auth.BasicAuthHeaderAutoLogin,com.liferay.portal.security.auth.AutoLoginCustom | + | #:auto.login.hooks=com.liferay.portal.security.auth.BasicAuthHeaderAutoLogin,com.liferay.portal.security.auth.AutoLoginCustom |
+ | # Edit the plugins-sdk/build.properties so that app.server.dir=/path/to/your/liferay/tomcat | ||
# Run "ant war" - The war file will be created in the plugins-sdk/dist folder. | # Run "ant war" - The war file will be created in the plugins-sdk/dist folder. | ||
− | # Copy the war file to Liferay_home/deploy | + | # Copy the war file to Liferay_home/deploy |
+ | # Copy portal-impl.jar in webapps/skeleton-hook/WEB-INF/lib/ (if not already there) | ||
# Restart liferay instance | # Restart liferay instance | ||
Line 12: | Line 260: | ||
<br/><br/> | <br/><br/> | ||
'''Configuration needed at liferay Web UI:'''<br/> | '''Configuration needed at liferay Web UI:'''<br/> | ||
− | # The X509 User should have | + | # Create a custom attribute for users with key "dn" and type java.lang.String |
+ | # Make sure that in the Custom Attribute Permissions, Guest has View permission checked | ||
+ | # The X509 User should have the custom attribute "dn" configured to the X509 certificate DN | ||
− | + | <br/> | |
− | < | + | '''The code for AutoLoginCustom.java''':<br/> |
− | The code for AutoLoginCustom.java: | + | <pre> |
package com.liferay.portal.security.auth; | package com.liferay.portal.security.auth; | ||
+ | import com.liferay.portal.SystemException; | ||
+ | import com.liferay.portal.model.User; | ||
+ | import com.liferay.portal.service.UserLocalServiceUtil; | ||
+ | |||
+ | import java.io.Serializable; | ||
import java.security.cert.X509Certificate; | import java.security.cert.X509Certificate; | ||
+ | |||
import java.util.Iterator; | import java.util.Iterator; | ||
import java.util.List; | import java.util.List; | ||
Line 26: | Line 282: | ||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
import org.apache.commons.logging.Log; | import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | import org.apache.commons.logging.LogFactory; | ||
− | |||
public class AutoLoginCustom implements AutoLogin{ | public class AutoLoginCustom implements AutoLogin{ | ||
− | + | ||
− | private static Log logger = LogFactory.getLog(AutoLoginCustom.class); | + | private static Log logger = LogFactory.getLog(AutoLoginCustom.class); |
− | + | ||
public String[] login(HttpServletRequest req, HttpServletResponse resp) | public String[] login(HttpServletRequest req, HttpServletResponse resp) | ||
throws AutoLoginException { | throws AutoLoginException { | ||
Line 48: | Line 297: | ||
User loginUser = null; | User loginUser = null; | ||
long userId = 0; | long userId = 0; | ||
+ | String userDN; | ||
+ | String userDNreverse; | ||
+ | String[] credentials = new String[3];; | ||
String requestDN = this.getUserDN(req); | String requestDN = this.getUserDN(req); | ||
− | if(requestDN != null){ | + | if (requestDN != null){ |
try { | try { | ||
− | + | ||
users = UserLocalServiceUtil.getUsers(0, UserLocalServiceUtil.getUsersCount()); | users = UserLocalServiceUtil.getUsers(0, UserLocalServiceUtil.getUsersCount()); | ||
} catch (SystemException e) { | } catch (SystemException e) { | ||
Line 58: | Line 310: | ||
} | } | ||
Iterator<User> userIter = users.iterator(); | Iterator<User> userIter = users.iterator(); | ||
− | |||
− | |||
+ | while (userIter.hasNext()){ | ||
+ | credentials = new String[3]; | ||
User user = (User)userIter.next(); | User user = (User)userIter.next(); | ||
− | if(user. | + | if(user.getExpandoBridge().hasAttribute("dn")){ |
− | + | Serializable dn = user.getExpandoBridge().getAttribute("dn"); | |
− | + | if(dn!=null){ | |
− | + | if(dn.toString().length()!=0){ | |
+ | // check the slash format for dn | ||
+ | userDN = dn.toString(); | ||
+ | if(userDN.contains("/")){ | ||
+ | userDN = userDN.substring(1); | ||
+ | } | ||
+ | userDN = userDN.replaceAll("/", ","); | ||
+ | |||
+ | userDNreverse=""; | ||
+ | String[] dnParts = userDN.split(","); | ||
+ | |||
+ | int dnPartsNo = dnParts.length; | ||
+ | while(dnPartsNo>0){ | ||
+ | dnPartsNo--; | ||
+ | userDNreverse += dnParts[dnPartsNo]; | ||
+ | if(dnPartsNo!=0){ | ||
+ | userDNreverse += ","; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | if (userDN.equals(requestDN) || userDNreverse.equals(requestDN)){ | ||
+ | loginUser = user; | ||
+ | logger.info("X509 certificate user logs in: " + loginUser.getFirstName()); | ||
+ | System.out.println("X509 certificate user logs in: " + loginUser.getFirstName()); | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | } | ||
} | } | ||
+ | |||
} | } | ||
− | |||
} | } | ||
− | if(loginUser!=null){ | + | if (loginUser!=null){ |
userId = loginUser.getUserId(); | userId = loginUser.getUserId(); | ||
− | |||
credentials[0]=String.valueOf(userId); | credentials[0]=String.valueOf(userId); | ||
credentials[1] = loginUser.getPassword(); | credentials[1] = loginUser.getPassword(); | ||
credentials[2] = Boolean.FALSE.toString(); | credentials[2] = Boolean.FALSE.toString(); | ||
+ | loginUser=null; | ||
} | } | ||
Line 98: | Line 377: | ||
} | } | ||
} | } | ||
− | </ | + | </pre> |
+ | <br/> | ||
+ | '''Reference''' <br/> | ||
+ | # http://www.liferay.com/community/wiki/-/wiki/Main/Hook+Plugin+Template |
Latest revision as of 16:03, 20 October 2010
Contents
How to configure Apache HTTP server and Apache Tomcat to handle X.509 certificates (full HTTPS)
The following setup shows how to configure Apache HTTP server in HTTPS so that X.509 client credentials can be forwarded to an internal Apache Tomcat instance.
Apache HTTP server
Two VirtualHost should be configured. The first one to handle HTTP requests on standard port 80, and redirect all of them to port 443 (HTTPS).
<VirtualHost *:80> ServerAdmin webmaster@localhost ServerName myportal.mydomain.com DocumentRoot /var/www/ ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combined ProxyPreserveHost on RewriteEngine on Redirect permanent / https://myportal.mydomain.com/ </VirtualHost>
The second virtual host is meant to handle HTTPS requests, asking clients to optionally authenticate with an X.509 certificates.
<VirtualHost *:443> ServerAdmin webmaster@localhost ServerName myportal.mydomain.com DocumentRoot /var/www/ <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog /var/log/apache2/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/log/apache2/access.log combined ServerSignature On Alias /doc/ "/usr/share/doc/" <Directory "/usr/share/doc/"> Options Indexes MultiViews FollowSymLinks AllowOverride None Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 </Directory> SSLEngine on SSLCertificateFile /etc/apache2/ssl/containercert.pem SSLCertificateKeyFile /etc/apache2/ssl/containerkey.pem SSLProxyEngine on SSLCACertificatePath /etc/grid-security/certificates/ SSLVerifyClient optional SSLVerifyDepth 2 # this option is mandatory to force apache to forward the client cert data to tomcat SSLOptions +ExportCertData <Proxy *> AddDefaultCharset Off Order deny,allow Allow from all </Proxy> ProxyPass / ajp://localhost:8020/ ProxyPassReverse / ajp://localhost:8020/ </VirtualHost>
The connection between Apache HTTP Server and Apache Tomcat is done via an AJP connector and Reverse Proxy directive. This means that the following modules need to be installed and loaded into Apache HTTP Server:
* proxy * proxy_http * proxy_ajp
to install a new module into apache2 use the following command:
a2enmod <module_name>
Apache Tomcat
An AJP connector needs to be declared in order to enable communication between Apache HTTP Server and Apache Tomcat, with a redirect to port 8443 to handle the HTTPS connection inside Tomcat.
<!-- Define an AJP 1.3 Connector on port 8020 --> <Connector port="8020" enableLookups="false" redirectPort="8443" protocol="AJP/1.3" URIEncoding="UTF-8" />
Eventually, a Connector needs to declared for port 8443 to handle the HTTPS connection in Tomcat.
<Connector port="8443" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" disableUploadTimeout="true" acceptCount="100" scheme="https" secure="true" clientAuth="want" sslProtocol="TLS" emptySessionPath="true" />
How to configure Apache HTTP server and Apache Tomcat to handle X.509 certificates (HTTPS only for login)
Apache HTTP server
NameVirtualHost *:80 NameVirtualHost *:443 <VirtualHost *:80> ServerAdmin webmaster@localhost ServerName myportal.mydomain.com DocumentRoot /var/www/ ErrorLog /var/log/apache2/error.log CustomLog /var/log/apache2/access.log combined ProxyPreserveHost on <Location /> Allow From All ProxyPass http://myportal.mydomain.com:9090/ ProxyPassReverse http://myportal.mydomain.com:9090/ </Location> RewriteEngine on #forces everything under /web/guest/signup to secure if non-secure (https) RewriteRule ^(/web/guest.*)$ https://myportal.mydomain.com$1 [R,L] </VirtualHost> <VirtualHost *:443> ServerAdmin webmaster@localhost ServerName myportal.mydomain.com DocumentRoot /var/www/ <Directory /> Options FollowSymLinks AllowOverride None </Directory> <Directory /var/www/> Options Indexes FollowSymLinks MultiViews AllowOverride None Order allow,deny allow from all </Directory> ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/ <Directory "/usr/lib/cgi-bin"> AllowOverride None Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch Order allow,deny Allow from all </Directory> ErrorLog /var/log/apache2/error.log # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. LogLevel warn CustomLog /var/log/apache2/access.log combined ServerSignature On Alias /doc/ "/usr/share/doc/" <Directory "/usr/share/doc/"> Options Indexes MultiViews FollowSymLinks AllowOverride None Order deny,allow Deny from all Allow from 127.0.0.0/255.0.0.0 ::1/128 </Directory> SSLEngine on SSLCertificateFile /etc/apache2/ssl/containercert.pem SSLCertificateKeyFile /etc/apache2/ssl/containerkey.pem SSLProxyEngine on SSLCACertificatePath /etc/grid-security/certificates/ SSLVerifyClient optional SSLVerifyDepth 2 # this option is mandatory to force apache to forward the client cert data to tomcat SSLOptions +ExportCertData RewriteEngine on #forces everything not under /web/guest/signup to non-secure if secure (http) RewriteCond %{REQUEST_URI} !^/(web/guest.*)$ RewriteCond %{REQUEST_URI} !^/(web/guest/change-of-details.*)$ RewriteCond %{REQUEST_URI} !^/(c/portal/login.*)$ RewriteCond %{REQUEST_URI} !^/(c/.*)$ RewriteCond %{REQUEST_URI} !^/(html/.*)$ RewriteRule ^(.*)$ http://%{SERVER_NAME}$1 [R,L] <Proxy *> AddDefaultCharset Off Order deny,allow Allow from all </Proxy> ProxyPass / ajp://myportal.mydomain.com:8020/ ProxyPassReverse / ajp://myportal.mydomain.com:8020/ </VirtualHost>
Apache Tomcat
Refer to the configuration described in the full HTTPS section
Liferay Portal Properties
Make sure that the following lines are appended to the portal-ext.properties file
company.security.auth.requires.https=true session.enable.phishing.protection=false
D4Science Portal HTTPS x509 Certificate Authentication
This is a custom Auto login hook that provides customised authentication for X509 certificate users.
Set the dev/deploy environment
- Unzip the file [1] onto your "plugin-sdk/hooks" folder.
- Copy the AutoLoginCustom.java(please find below) source to the src folder
- Add the following line to portal.properties file which is present in the /skeleton-hook/docroot/WEB-INF/src/ folder :
- auto.login.hooks=com.liferay.portal.security.auth.BasicAuthHeaderAutoLogin,com.liferay.portal.security.auth.AutoLoginCustom
- Edit the plugins-sdk/build.properties so that app.server.dir=/path/to/your/liferay/tomcat
- Run "ant war" - The war file will be created in the plugins-sdk/dist folder.
- Copy the war file to Liferay_home/deploy
- Copy portal-impl.jar in webapps/skeleton-hook/WEB-INF/lib/ (if not already there)
- Restart liferay instance
Auto Login hook is now ready to be tested and used.
Configuration needed at liferay Web UI:
- Create a custom attribute for users with key "dn" and type java.lang.String
- Make sure that in the Custom Attribute Permissions, Guest has View permission checked
- The X509 User should have the custom attribute "dn" configured to the X509 certificate DN
The code for AutoLoginCustom.java:
package com.liferay.portal.security.auth; import com.liferay.portal.SystemException; import com.liferay.portal.model.User; import com.liferay.portal.service.UserLocalServiceUtil; import java.io.Serializable; import java.security.cert.X509Certificate; import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; public class AutoLoginCustom implements AutoLogin{ private static Log logger = LogFactory.getLog(AutoLoginCustom.class); public String[] login(HttpServletRequest req, HttpServletResponse resp) throws AutoLoginException { // TODO Auto-generated method stub List<User> users = null; User loginUser = null; long userId = 0; String userDN; String userDNreverse; String[] credentials = new String[3];; String requestDN = this.getUserDN(req); if (requestDN != null){ try { users = UserLocalServiceUtil.getUsers(0, UserLocalServiceUtil.getUsersCount()); } catch (SystemException e) { // TODO Auto-generated catch block e.printStackTrace(); } Iterator<User> userIter = users.iterator(); while (userIter.hasNext()){ credentials = new String[3]; User user = (User)userIter.next(); if(user.getExpandoBridge().hasAttribute("dn")){ Serializable dn = user.getExpandoBridge().getAttribute("dn"); if(dn!=null){ if(dn.toString().length()!=0){ // check the slash format for dn userDN = dn.toString(); if(userDN.contains("/")){ userDN = userDN.substring(1); } userDN = userDN.replaceAll("/", ","); userDNreverse=""; String[] dnParts = userDN.split(","); int dnPartsNo = dnParts.length; while(dnPartsNo>0){ dnPartsNo--; userDNreverse += dnParts[dnPartsNo]; if(dnPartsNo!=0){ userDNreverse += ","; } } if (userDN.equals(requestDN) || userDNreverse.equals(requestDN)){ loginUser = user; logger.info("X509 certificate user logs in: " + loginUser.getFirstName()); System.out.println("X509 certificate user logs in: " + loginUser.getFirstName()); break; } } } } } } if (loginUser!=null){ userId = loginUser.getUserId(); credentials[0]=String.valueOf(userId); credentials[1] = loginUser.getPassword(); credentials[2] = Boolean.FALSE.toString(); loginUser=null; } return credentials; } private X509Certificate[] getCerts(HttpServletRequest req) { return (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate"); } private String getUserDN(HttpServletRequest req) { X509Certificate certs[] = this.getCerts(req); if (certs != null && certs.length > 0) { String DN = certs[0].getSubjectDN().getName(); String parsedDN = DN.replace(", ", ","); return parsedDN; } else { return null; } } }
Reference