WARNING: This is an article in progress. Do not attempt in production.
Acknowledgements
This feature is Bill Burke's idea. All glory to him.
Steps to Follow:
- Assume you have a JBoss Application Server v5 and beyond.
- Pick the two jars from PicketBox release (after 3.0.0.CR2) ( jboss-security-spi.jar [https://repository.jboss.org/nexus/content/groups/public-jboss/org/picketbox/jboss-security-spi/] and jbosssx.jar [ https://repository.jboss.org/nexus/content/groups/public-jboss/org/picketbox/jbosssx/ ]
- Rename the jboss-security-spi.jar and jbosssx.jar in JBAS5+ to *.bak (Just add a .bak prefix)
- Move the two downloaded jars from step 2 into where these .bak files are.
- Follow the Web Application Authentication Set up below.
- Follow the TOTP mobile app Set up below.
- Try logging in to your web application at http://localhost:8080/webapp (Eg: http://localhost:8080/jmx-console/)
- Now enter both your password and your TOTP token (generated by the mobile app) in the respective boxes.
- You should be logged in.
Web Application Set up
You will need FORM based authentication. (Strongly recommend using https)
I am going to take the example of jmx-console.war
The web.xml will look as follows:
<?xml version="1.0"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <description>The standard web descriptor for the html adaptor</description> <!-- <filter> <filter-name>JmxOpsAccessControlFilter</filter-name> <filter-class>org.jboss.jmx.adaptor.html.JMXOpsAccessControlFilter</filter-class> <init-param> <param-name>updateAttributes</param-name> <param-value>UpdateAttributeRole</param-value> <description>Comma-delimited Roles that define the JMX Operation denoting updation of Attributes</description> </init-param> <init-param> <param-name>invokeOp</param-name> <param-value>InvokeOpRole</param-value> <description>Comma-delimited Roles that define the JMX Operation denoting Invocation of Operations</description> </init-param> </filter> <filter-mapping> <filter-name>JmxOpsAccessControlFilter</filter-name> <servlet-name>HtmlAdaptor</servlet-name> </filter-mapping> --> <servlet> <servlet-name>HtmlAdaptor</servlet-name> <servlet-class>org.jboss.jmx.adaptor.html.HtmlAdaptorServlet</servlet-class> </servlet> <servlet> <servlet-name>ClusteredConsoleServlet</servlet-name> <servlet-class>org.jboss.jmx.adaptor.html.ClusteredConsoleServlet</servlet-class> <init-param> <description>The JGroups protocol stack config</description> <param-name>jgProps</param-name> <param-value>UDP(ip_mcast=true;ip_ttl=16;loopback=false;mcast_addr=${jboss.partition.udpGroup:228.1.2.3};mcast_port=${jboss.jmxconsolepartition.mcast_port:46666}): org.jboss.jmx.adaptor.control.FindView </param-value> </init-param> </servlet> <servlet> <servlet-name>DisplayMBeans</servlet-name> <jsp-file>/displayMBeans.jsp</jsp-file> </servlet> <servlet> <servlet-name>InspectMBean</servlet-name> <jsp-file>/inspectMBean.jsp</jsp-file> </servlet> <servlet> <servlet-name>DisplayOpResult</servlet-name> <jsp-file>/displayOpResult.jsp</jsp-file> </servlet> <servlet> <servlet-name>ClusterView</servlet-name> <jsp-file>/cluster/clusterView.jsp</jsp-file> </servlet> <servlet> <servlet-name>ProfileServiceDebugServlet</servlet-name> <servlet-class>org.jboss.profileservice.web.DebugServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>HtmlAdaptor</servlet-name> <url-pattern>/HtmlAdaptor</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ClusteredConsoleServlet</servlet-name> <url-pattern>/cluster/ClusteredConsole</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>DisplayMBeans</servlet-name> <url-pattern>/DisplayMBeans</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>InspectMBean</servlet-name> <url-pattern>/InspectMBean</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>DisplayOpResult</servlet-name> <url-pattern>/DisplayOpResult</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>ProfileServiceDebugServlet</servlet-name> <url-pattern>/ProfileServiceDebugServlet</url-pattern> </servlet-mapping> <!-- Display a generic error page when HTTP Status 500 exceptions occur. --> <error-page> <error-code>500</error-code> <location>/genericError.jsp</location> </error-page> <!-- A security constraint that restricts access to the HTML JMX console to users with the role JBossAdmin. Edit the roles to what you want and uncomment the WEB-INF/jboss-web.xml/security-domain element to enable secured access to the HTML JMX console. --> <security-constraint> <web-resource-collection> <web-resource-name>HtmlAdaptor</web-resource-name> <description>An example security config that only allows users with the role JBossAdmin to access the HTML JMX console web application </description> <url-pattern>/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>JBossAdmin</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <realm-name>JBoss JMX Console</realm-name> <form-login-config> <!-- only useful for FORM --> <form-login-page>/login-page.html</form-login-page> <form-error-page>/error-page.html</form-error-page> </form-login-config> </login-config> <security-role> <role-name>JBossAdmin</role-name> </security-role> </web-app>
Your WEB-INF/jboss-web.xml should look:
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN" "http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd"> <jboss-web> <!-- Uncomment the security-domain to enable security. You will need to edit the htmladaptor login configuration to setup the login modules used to authentication users. --> <security-domain>otp</security-domain> </jboss-web>
You will need a login-page.html in the jmx-console.war directory.
<HTML> <TITLE>Login</TITLE> <BODY> <FORM METHOD=POST ACTION=j_security_check> <CENTER> <TABLE BORDER=0> <TR><TD COLSPAN=2> <P ALIGN=center> Welcome! Please enter your Name<br> and Password to log in. </TD></TR> <TR><TD> <P ALIGN=right><B>Name:</B> </TD> <TD> <P><INPUT TYPE=TEXT NAME="j_username" VALUE="" SIZE=15> </TD></TR> <TR><TD> <P ALIGN=RIGHT><B>Password:</B> </TD> <TD> <P><INPUT TYPE=PASSWORD NAME="j_password" VALUE="" SIZE=15> </TD></TR> <TR><TD> <P ALIGN=RIGHT><B>Token:</B> </TD> <TD> <P><INPUT TYPE=PASSWORD NAME="totp" VALUE="" SIZE=15> </TD></TR> <TR><TD COLSPAN=2> <CENTER> <INPUT TYPE=submit VALUE=" OK "> </CENTER> </TD></TR> </TABLE> </FORM> </BODY></HTML>
You will need an error-page.html in the jmx-console.war directory.
<HTML> <TITLE>Login Denied</TITLE> <BODY> Sorry, your login was denied. Please hit the Back button to try again. </BODY></HTML>
Now in your conf directory, in the login-config.xml, at the end, add the following block:
<application-policy name="otp"> <authentication> <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required"> <module-option name="usersProperties">props/jmx-console-users.properties</module-option> <module-option name="rolesProperties">props/jmx-console-roles.properties</module-option> </login-module> <login-module code="org.jboss.security.auth.spi.otp.JBossTimeBasedOTPLoginModule" /> </authentication> </application-policy>
TOTP Mobile App Set Up
I got the TOTP iPhone app from the App Store.
http://code.google.com/p/oathtoken/
- I clicked the "+" button.
- Then in the token name, added "JBOSS".
- Clicked "Time Based".
- Generate Random Key (The key that was generated was transferred to the otp-users.properties file on the server side).
Android: I tested the free apps. None of them did what we want. Oh well! I will write one soon.
JBoss Application Server Setup
In the conf directory, I created a file "otp-users.properties". This file is where the user name and the shared secret is stored. The shared secret should be the same as the one in the TOTP mobile client.
My otp-users.properties looks as:
admin=35cae61d6d51a7b3af
Configuration Options for Login Module
- algorithm: either "HmacSHA1", "HmacSHA256" or "HmacSHA512" [Default: "HmacSHA1"]
- numOfDigits: Number of digits in the TOTP. Default is 6.
- additionalRoles: any additional roles that you want to add into the authenticated subject (on success). For multiple roles, separate with a comma
This login module requires the presence of "otp-users.properties" on the class path with the format: username=key
Configurable Options:
- algorithm: either "HmacSHA1", "HmacSHA256" or "HmacSHA512" [Default: "HmacSHA1"]
- numOfDigits: Number of digits in the TOTP. Default is 6.
- additionalRoles: any additional roles that you want to add into the authenticated subject (on success). For multiple roles, separate with a comma
This login module requires the presence of "otp-users.properties" on the class path with the format: username=key
GOTCHAS
- Remember the parameter for the token in the login page has to be "totp".
- The secret key on the handheld application and the otp-users.properties have to be the same. This is an out-of-band synchronization that can be done via a phone call with system admin.
Comments