navigation

How to avoid basic authentication when session has expired in JasperServer 5.5.0

How to avoid basic authentication when session has expired in JasperServer 5.5.0

by
November 6, 2014
BI, frontpage, Java, Web and others
One Comment

Recently I had an issue with our clients in which they complained about showing a basic authentication popup window when the session is timeout and the user changes the values of the input controls in order to execute a report. I have decided to implement a solution in which when this event occurs the user will be redirected to the login page avoiding the basic authentication.

First I needed to find out where in the project is used basic authentication. The easiest way is to search for string “WWW-Authenticate” which according to the standard must be included in the HTTP request header. The result after the search was one – ForbiddenEntryPoint.java. The definition of the class is:

public class ForbiddenEntryPoint implements AuthenticationEntryPoint {
 public final String SUPPRESS_BASIC_HEADER = “X-Suppress-Basic”;
 public final String HTTP_WWW_AUTHENTICATE_HEADER = “WWW-Authenticate”;
 
public void commence(ServletRequest request, ServletResponse response, AuthenticationException authException) 
throws IOException, ServletException {
       HttpServletRequest httpRequest = (HttpServletRequest) request;
       HttpServletResponse httpResponse = (HttpServletResponse) response;
 
       if (!”true”.equalsIgnoreCase(httpRequest.getHeader(SUPPRESS_BASIC_HEADER))){
           httpResponse.setHeader(HTTP_WWW_AUTHENTICATE_HEADER, “Basic realm=\”Protected area\””);
       }
 
       httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());
   }
}

The basic authentication popup window will appear if in the header of the request the value of “X-Suppress-Basic” is NOT “true”, otherwise the response will be with status code 401(httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage());) which means the authorization has been denied. Now we have to find out where in the project is generated the request from the input controls of the report. After debugging a couple of hours with the help of the “Developer tools” in Chrome I found out that the file which I need is controls.datatransfer.js

First we need to add “X-Supress-Basic” with value “true” so we will modify the sendRequest function to look like this:

sendRequest : function(url, data, settings) {
               var defaultSettings = {
                   url : url,
                   type : “GET”,
                   dataType : “json”,
                   cache : false,
        headers : {‘X-Suppress-Basic': ‘true’}
               };
               if (!_.isEmpty(data)) {
                   _.extend(defaultSettings, {
                       type : “POST”,
                       processData : false,
                       data : JSON.stringify(data),
                       contentType : “application/json”
                   });
               }
               return jQuery.ajax(_.defaults(settings || {}, defaultSettings)).
                   fail(commonErrorHandler);
           }

Only the red line is the modification.

Now we need to handle the response which will be with status code 401. The modification is in the commonErrorHandler function.

function commonErrorHandler(err) {
       try {
           try {
               var errorObject = jQuery.parseJSON(err.responseText);
           } catch (e) {}
 
           if (errorObject && errorObject.error) {
               _.each(errorObject.error, function (error) {
                   //TODO: try to avoid it
                   var viewModel = Controls.getViewModel();
                   var controlUri = error.inputControlUri.replace(“repo:”, “”);
                   var control = viewModel.find({uri:controlUri});
                   if (error.errorCode) {
                       control.set({error:error.errorCode});
                   } else if (error.defaultMessage) {
                       control.set({error:error.defaultMessage});
                   }
               });
           } else {
if (err.getResponseHeader(“LoginRequested”) || err.status == 401) {
                   document.location.href = ‘login.html';
               } else if (err.status == 500 || (err.getResponseHeader(“JasperServerError”)
                   && !err.getResponseHeader(“SuppressError”))) {
 
                   var message = “”;
                   if (errorObject) {
                       message = Mustache.to_html(“<div><b>{{message}}</b></div><p>{{#parameters}}<div>{{.}}</div>{{/parameters}}</p>”, errorObject);
                   } else {
                       message = statusText;
                   }
 
                   dialogs.errorPopup.show(message);
               }
           }
       } catch (e) {
           // In this scenario security error is handled earlier, in errorHandler, so we can ignore exception here.
           // Comment this because it will not work in IE, but can be uncommented for debug purpose.
           // console.error(“Can’t parse server response: %s”, “controls.core”, err.responseText);
       }
   }

Again the modification is red. So if we receive status code 401 the user will be redirected to the login page.

Leave your comments below

Boyko Dimitrov

Java Developer at Dreamix

More Posts - Website

Follow Me:
TwitterLinkedInGoogle Plus

Do you want more great blogs like this?

Subscribe for Dreamix Blog now!

  • Great article Boyko…I was looking for such a fix in my JRS 5.5.0 install. Worked perfectly.

    Looking for two more fixes if you have the time to post solutions.

    1) how to redirect Access Denied page error (org.springframework.security.AccessDeniedException) to more user friendly version (custom HTML error page)

    2) what the javascript function looks like for dynamic key encryption. given the RSA public key (from JRS) in json format, execute a javascript function to encrypt a string per the Jasper Server Encryption requirements (encryption.type=RSA, encryption.key.length=1024, algorithm = RSA/NONE/NoPadding). the JRS examples do not work.

    Thank You!