Search code examples
javaauthenticationstrutspentaho

How do I redirect to Pentaho User Console with Java?


I have Pentaho running on a server. On a different server, I have a Struts 1 app running.

What I want to do is provide a link to the User Console of Pentaho (http://myserver/pentaho/Home). However, this requires authentication.

I can pass the user/pass in the URL string and it works just fine. But obviously, this exposes the password in the URL.

Any clues on how to do this? The following code show how I was able to do it and dump the output (via an PrintWriter) but it requires the pentaho source to be local.

Thanks for any help.

public ActionForward execute(ActionMapping mapping, ActionForm form,
       HttpServletRequest request, HttpServletResponse response) throws Exception {

    HttpClient client = new HttpClient();
    PostMethod method = new PostMethod("http://myserver/pentaho/Home");
    method.addParameter("userid", "moe.howard");
    method.addParameter("password", "password");

    int status = client.executeMethod(method);

    PrintWriter out = response.getWriter();
    out.print(method.getResponseBodyAsString());
    out.flush();
    out.close();

    return mapping.findForward(SUCCESS);
}

Solution

  • Finally found a solution. I ended up creating a redirect.jsp file on the Pentaho server. Then, I passed an encrypted http auth token to it, decrypted it, and then redirected to the login. Works great.

    EDIT

    Really old question but I was asked to provide more information on my solution. So here goes.

    First, the default install of Pentaho used HTTP Basic Authentication (BA). If you're using a single sign-on or LDAP solution this might not work for you.

    So what I did was put a JSP file in the ROOT folder under ..tomcat\webapps\ROOT. That JSP takes the passed in login information and de-crypts it. That login information is just a BASE64 authenticated request.

    This isn't super secure, by any means. But what it allowed me to do was send an encrypted user/pass from one server and pass it to another server. Of course, if you're SSL all the way then this probably isn't needed but we had a situation where the information was being passed in clear text INTERNALLY. So, it was never exposed to the outside but I still wanted to make sure our internal servers are as secure as possible.

    The JSP:

    <%@page contentType="text/html; charset=iso-8859-1" language="java" 
    import="java.security.*"
    import="javax.crypto.Cipher"
    import="javax.crypto.spec.SecretKeySpec"
    import="sun.misc.*"
    %>
    
    <%
      // Decrypt authenticated hash
      String ALGORITHM = "AES";
      byte[] keyValue = "MY-SECRET-PASSWORD".getBytes();
    
      Key key = new SecretKeySpec(keyValue, ALGORITHM);
      Cipher c = Cipher.getInstance(ALGORITHM);
      c.init(Cipher.DECRYPT_MODE, key);
      byte[] decodedValue = new BASE64Decoder().decodeBuffer(new String(request.getParameter("auth")));
      byte[] decValue = c.doFinal(decodedValue);
      String decryptedValue = new String(decValue);
    %>
    
    <script type="text/javascript">
       var auth = '<%= decryptedValue%>';
    
       function AJAX(url, callback) {
    
          var req = init();
          req.onreadystatechange = processRequest;
    
          function init() {
             if (window.XMLHttpRequest) {
                return new XMLHttpRequest();
             } else if (window.ActiveXObject) {
                return new ActiveXObject("Microsoft.XMLHTTP");
             }
          }
    
          function processRequest () {
             // readyState of 4 signifies request is complete
             if (req.readyState == 4) {
                // status of 200 signifies sucessful HTTP call
                if (req.status == 200) {
                   if (callback) callback(req.responseXML);
                }
             }
          }
    
          this.doGet = function() {
             req.open("GET", url, true);
             req.setRequestHeader("Authorization", "Basic " + auth);
             req.send(null);
          }
       }
    
       var url = "/pentaho/Home";
       var querystr = "";
       var ajax = new AJAX(url, function(){
          window.location = url;
       });
    
       ajax.doGet(querystr);
    
    </script>
    

    So, my login server authenticates the user against the same MySQL database Pentaho uses, creates the authenticated (BA) request, BASE64's it, encrypts it using the same MY-SECRET-PASSWORD and sends that to the JSP. The JSP then de-crypts it and reads the BA header and passes that on to Pentaho.

    Works great for us.

    Hope it helps someone out.