1 2 Previous Next 22 Replies Latest reply on Jan 9, 2015 7:43 PM by tsobis

    picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()

    tsobis

      We are using picketlink for authentication and authorization and decided to update to a newer version (2.7.0). Up until now we used a custom filter to protect a folder “/pages/*” and a custom authentication by extending the BaseAuthenticator. However, the filter does not only checks if the user is authenticated, but also saves the original request of the user into a session variable, so that we can redirect them to their original request after the authentication.

      e.g.

      //capture the original request in the filter

      StringBuffer requestURL = httpRequest.getRequestURL();

      if (httpRequest.getQueryString() != null) {requestURL.append("?").append(httpRequest.getQueryString());}

      sessionUI.setCaptureCurrentView(requestURL.toString());

       

      In the newer version we tried to use the SecurityConfigurationBuilder to protect the folder, which works perfectly. However, we needed the user to be redirected to his/hers original request after a correct authentication. We were very happy when we found out that this can be achieved very easy by adding the method restoreOriginalRequest(). So the question is: can the

      SecurityConfigurationBuilder restoreOriginalRequest() be used with combination of a custom class that extends the BaseAuthenticator?

      e.g

      SecurityConfigurationBuilder builder = event.getBuilder();

      builder.http().forPath("/pages/*").authenticateWith().form().loginPage("/login.jsf").errorPage("/login.jsf");

      builder.http().forPath("/pages/*").authenticateWith().form().loginPage("/login.jsf").errorPage("/login.jsf"). restoreOriginalRequest();

        • 1. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
          pcraveiro

          Hi George,

           

              I think this is possible, yes. Did you try this out ?

           

          Regards.

          • 2. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
            tsobis

            Sorry for the late reply, I tried it but it does not work. Can you tell me if we can retrieve the original request (similar to the restoreOriginalRequest()) and use it inside a custom AuthenticationController that extends BaseAuthenticator and implements Authenticator?

             

            To be more specific, a file called login.jsf has a jsf form. This form is submitted from an action button #{identity.login} which has an override method inside the file AuthenticationController.

            In the old version there was a Filter(1) that caught the requested url if the user is not authorized and tried to access a locked page, so that afterwards at the login page, a redirect will be performed after a correct login (2) to the requested url.

            1) AuthFilter.java

            @WebFilter(urlPatterns = "/pages*",dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD})
            public class AuthFilter implements javax.servlet.Filter
            {
                @Inject Logger logger;
                @Inject Identity identity;
                @Inject SessionData sessionUI;
                @Inject ApplicationData applicationUI;
                public static final String REALM_BASE_URI = "/pages";
            
                @Override
                public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
                {
                    HttpServletRequest httpRequest = (HttpServletRequest) request;
                    HttpServletResponse httpResponse = (HttpServletResponse) response;
                    boolean isAuthorized = this.identity.isLoggedIn();
                    if (identity.isLoggedIn()){isAuthorized = isUserBaseRealmURI(httpRequest); }
                    if (isAuthorized) {if (chain != null){chain.doFilter(httpRequest, httpResponse);} }
                    else
                    {
                        StringBuffer requestURL = httpRequest.getRequestURL();
                        if (httpRequest.getQueryString() != null) {requestURL.append("?").append(httpRequest.getQueryString());}
                        if(applicationUI.getDebugModeOn()){logger.info("forwardAccessDeniedPage --> store requestURL.toString():"+requestURL.toString());}
                        sessionUI.setCaptureCurrentView(requestURL.toString());
                        forwardAccessDeniedPage(httpRequest, httpResponse);
                    }
                }
            
                @Override
                public void init(FilterConfig filterConfig) throws ServletException{}
                @Override
                 public void destroy(){}
            
                private void forwardAccessDeniedPage(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException
                {
                  httpRequest.getServletContext().getRequestDispatcher("/login.jsf").forward(httpRequest, httpResponse);
                }
                private boolean isUserBaseRealmURI(HttpServletRequest httpRequest)
                {
                    Partition partition = identity.getAccount().getPartition();
                    String allowedRealmBaseURI = getRealmBaseURI(httpRequest) + "/" + partition.getName();
                    return httpRequest.getRequestURI().startsWith(allowedRealmBaseURI);
                }
                private String getRealmBaseURI(HttpServletRequest httpRequest) {return httpRequest.getContextPath() + REALM_BASE_URI;}
                private boolean isProtectedResource(HttpServletRequest request) {return !request.getRequestURI().equals(getRealmBaseURI(request) + "/dashboard.jsf");}
            }
            
            

            2) AuthenticationController.java

            @Named("auth")
            @PicketLink
            public class AuthenticationController extends BaseAuthenticator implements Authenticator
            {
                 @Override
                public void authenticate()
                {
                            /*check user here */
                            this.setAccount(user);
                            this.setStatus(AuthenticationStatus.SUCCESS);
                           /*after correct login redirect*/
            String redirectUrl="";
                            if(!sessionUI.getCaptureCurrentView().equals("") && sessionUI.getCaptureCurrentView()!=null)
                            {
                                 redirectUrl=sessionUI.getCaptureCurrentView();
                                 sessionUI.setCaptureCurrentView("");
                            }
                            else{redirectUrl=applicationUI.getRestrictedHomePage();}
                            if(applicationUI.getDebugModeOn()){logger.info("redirectUrl:"+redirectUrl);}
            
                            try {Faces.redirect(redirectUrl);}
                            catch (IOException e)
                            {
                                 logger.info(e.toString());
                                 Messages.add(FacesMessage.SEVERITY_ERROR, null,   resourceBundle.getString("errors_00004"),redirectUrl);
                            }
                        }
                        else
                        {
                            logger.info(resourceBundle.getString("errors_00003"));
                            this.setStatus(AuthenticationStatus.FAILURE);
                            Messages.add(FacesMessage.SEVERITY_ERROR, null, resourceBundle.getString("errors_00003"),credentials.getUserId());
                        }
                 }
            }
            

             

            At the new version the filter will be removed and a SecurityConfigurationBuilder (3) will be implemented, with combination of the custom AuthenticationController without the redirect.

            3) PicketlinkHttpSecurityConfiguration.java

            public class PicketlinkHttpSecurityConfiguration
            {
                public void configureHttpSecurity(@Observes SecurityConfigurationEvent event)
                {
                    SecurityConfigurationBuilder builder = event.getBuilder();
                    builder.http()
             .forPath("/pages/*").authenticateWith().form().loginPage("/login.jsf").errorPage("/login.jsf").restoreOriginalRequest() 
            .forPath("/members/*").authenticateWith().form().loginPage("/login.jsf").errorPage("/login.jsf").restoreOriginalRequest();
                }
            }
            
            • 3. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
              tsobis

              So, after a lot of testing we could not combine restoreOriginalRequest() of the SecurityConfigurationBuilder with a custom BaseAuthenticator. Therefore, we will keep using our custom AuthFilter. The weird part is that there is no error logged at the files, the only part that does not work is the redirection to the original url. 

              Can anyone point me at the problem or how to start debugging it?

              We use log4j and log4j.logger.org.picketlink=debug for the configuration on jboss-eap-6.2

              • 4. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                pcraveiro

                Hey George,

                 

                   I've found an issue in the form authentication scheme. Can you please take a look at [1] ?

                 

                   Wondering if you can test and see if works for you now.

                 

                Regards.

                 

                [1] [PLINK-646] FormAuthenticationScheme restore original URL not working - JBoss Issue Tracker

                • 5. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                  tsobis

                  Unfortunately, the result is the same, no error messages just no redirection.

                  Let me start with a simple question, can the following code be used with a custom AuthenticationController that will extend the BaseAuthenticator?

                  SecurityConfigurationBuilder builder = event.getBuilder();

                  builder.http().forPath("/pages/*").authenticateWith().form().loginPage("/login.jsf").errorPage("/login.jsf").restoreOriginalRequest();

                   

                  Secondly, if for the first question is yes, the authenticate() requires only to set the following values and the redirection will be performed?

                  setStatus(AuthenticationStatus.SUCCESS);

                  setAccount(user);

                   

                  Greatly Appreciated

                  • 6. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                    pcraveiro

                    Hey George,

                     

                        The answer is yes for both questions. I suggest you to take a look at the following quickstart [1], it will help you to see a working custom authenticator example.

                     

                        Now, regarding the restore original request thing. I've deployed a SNAPSHOT version to Nexus. Can you check it out ?

                     

                    [1] jboss-picketlink-quickstarts/CustomAuthenticator.java at master · jboss-developer/jboss-picketlink-quickstarts · GitHub

                     

                    Regards.
                    Pedro Igor

                    • 7. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                      tsobis

                      Thanks for the suggestion for the quickstart. I have already a testing project that uses jsf, cdi, picketlink and ocpsoft.rewrite with custom a Authentication controller that works, however, the problem arises when I try to combine the restoreOriginalRequest().

                      The SecurityConfigurationBuilder is working as it should for restricting access to the folders, however, when I request a page like

                      http://<mydomain>/directory-panel/members/configuration/member/view=2

                      the redirection to the login page is performed but the restore to the original request after a correct login is not.

                      Currently testing with

                      <dependency>

                      <groupId>org.picketlink</groupId>

                      <artifactId>picketlink</artifactId>

                      <version>2.7.0.CR3</version>

                      </dependency>

                       

                      Greatly Appreciated

                      • 8. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                        pcraveiro

                        Really weird. Going to take a look on that, again ...

                        • 9. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                          pcraveiro

                          Is this url correct ?

                           

                          http://<mydomain>/directory-panel/members/configuration/member/view=2

                           

                          Or do you meant (using a query parameter)

                           

                          http://<mydomain>/directory-panel/members/configuration/member?view=2

                           

                          I've noticed that PicketLink is not properly considering the query string when restoring the original request. Maybe this can be the issue.

                          • 10. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                            tsobis

                            Yes the url is correct, i am using ocpsoft.rewrite for url rewriting

                            @Join(path="/members/configuration/member/view={requestedID}",to="/pages/members/member-view.jsf")

                            So, you think that the url rewrite might causing the problem?

                            • 11. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                              pcraveiro

                              Probably. WHat I just did was change picketlink-authentication-form quickstart to restore a request as follows

                               

                              1) http://localhost:8080/picketlink-authentication-form/protected/savedRequest=2

                               

                              And it works fine. Right after a successful login I'm redirect to that URI.

                               

                              But, if you send something like:

                               

                              2) http://localhost:8080/picketlink-authentication-form/protected/savedRequest?param=value

                               

                              The query parameter (param) is not being restored, but just the URI itself.

                               

                              Considering that you are not using query parameters and your case is similar to #1, I think it might be something with the url rewriting. Do you have a simple project with rewrite that I can use to test this stuff ?

                               

                              Thanks.

                              • 12. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                                tsobis

                                Simple project no, i will create a simple one, tomorrow or the day after tomorrow and send the link. Futhermore, i will test our main project without url rewrite

                                Greatly Appreciated

                                • 13. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                                  pcraveiro

                                  That would help me a lot. So I can make sure to properly test things considering you environment.

                                   

                                  Thanks.

                                  • 14. Re: picketlink BaseAuthenticator with SecurityConfigurationBuilder restoreOriginalRequest()
                                    tsobis

                                    I generated a small project at https://github.com/tsobis/example

                                    for you to chek the problem, however, i did not have the time to test it.

                                    The project uses  URL rewriting and picketlink.

                                    http://<mydomain>/example/members/configuration/member/view=2

                                    should redirect you to the login page login.jsf an after a correct login with (username=tsobis  password=password)

                                    should redirect you to the original url.

                                    Currently our working code is using pickeling 2.6.1 with a AuthFilter for testing the protected urls. This code will be used to migrate to the newer version of the pickelink and drop the AuthFilter.

                                    Thanks for the help

                                    1 2 Previous Next