Link handler for a back door login

Hi,

We are using link handlers back from release 6 and still rely on them for some modified login sequences. We are currently on release 7.1.8 and planning to move on to release 7.2.

We do encounter some unexpected behavior currently and are not sure what is expected currently (release 7.1) and what is to be expected in the latest (release 7.2).

The behavior that we see is as follows:

  • The url handling mode has been set to none: cuba.web.urlHandlingMode = NONE
  • The default login has been adapted to a screen which dispatches the login request to a SAML IDP (so basically, this is a SAML authentication handler). This is done without user interaction. Configuration is set through the web-app.properties (cuba.web.loginScreenId).
  • We configured a separate link handler (cuba.web.linkHandlerActions) for /login which forms a back door to the original login screen (username+password) in case the SAML authentication fails or is unavailable for whatever reason.
  • Previously - that is before using release 7.1 - whenever the initial url would include the /login (back door), the first thing to be parsed was by the link handler and routed to the original login screen, otherwise the login was dispatched to the SAML IDP.
  • As of release 7.1, the first thing that happens is to load the adapted login screen, independent from the configured link handler which is called later on (after the adapted login screen). As a result, the user is always redirected to the SAML IDP and not to the back door login.

So we have a couple of questions:

  • Why has the order of events changed?
  • Is there any way to determine whether the initial url contains the /login from the adapted login screen? We have not been able to do so.
  • What would be the suggested solution for a ‘back door’ login in the given scenario?
  • The login screen has been changed in 7.2; does this imply a different solution? And what would that be?

Thanks for any help.

Regards,
-b

Hi,

Could you please send us a small demo project that reproduces the issue so I can debug the problem with the correct settings?

Regards,
Gleb

Hi Gleb,

Thanks for responding. Took me a bit of time to make a demo project but the attached zip file contains such a project.

It overrides the login screen and basically does a forward to https://google.com. There is however a ‘backdoor’ on /login that should prevent this from happening. However, as described in this topic, the normal login is triggered first before accessing the /login. Hence, the forward remains to take place.

backdoor.zip (84.5 KB)

I hope you can help me out here.

Regards,
-b

Thank you for the demo project.

First thing first, link handler is called after the initial app initialization, which means that setupUI() invoked before processExternalLink(...) in the init method of AppUI class. That why redirect is triggered. In fact, link handlers aren’t intended to replace which login screen which is shown. com.haulmont.cuba.web.DefaultApp#routeTopLevelWindowId returns top-level window id.

I propose extend Default app and override routeTopLevelWindowId, e.g.:

import com.haulmont.cuba.web.DefaultApp;
import com.vaadin.server.VaadinRequest;
import com.vaadin.server.VaadinService;
import com.vaadin.server.WrappedSession;

import java.util.Collections;
import java.util.Map;

import static com.haulmont.cuba.web.AppUI.LAST_REQUEST_ACTION_ATTR;
import static com.haulmont.cuba.web.AppUI.LAST_REQUEST_PARAMS_ATTR;

public class CustomApp extends DefaultApp {

    @Override
    protected String routeTopLevelWindowId() {
        if (connection.isAuthenticated()) {
            return webConfig.getMainScreenId();
        } else if (isBackdoorLogin()) {
            return "backdoorLoginWindow";
        } else {
            return super.routeTopLevelWindowId();
        }
    }

    private boolean isBackdoorLogin() {
        VaadinRequest request = VaadinService.getCurrentRequest();
        if (request == null) {
            return false;
        }

        WrappedSession wrappedSession = request.getWrappedSession();
        String action = (String) wrappedSession.getAttribute(LAST_REQUEST_ACTION_ATTR);

        //noinspection unchecked
        Map<String, String> params = (Map<String, String>) wrappedSession.getAttribute(LAST_REQUEST_PARAMS_ATTR);
        params = params != null ? params : Collections.emptyMap();

        return "login".equals(action);
    }
}

and register in web-spring.xml

<bean id="cuba_App"
          class="com.company.backdoor.web.core.CustomApp"
          scope="vaadin"/>

I’d suggest getting rid of legacy link handlers and using Routing API (see docs). In this case, you can either implement custom NavigationHandler or handle URL params changes in the single login screen and do some logic depending on params (e.g. sampler browse screen). It would be much easier and more reliable.

Gleb

1 Like

Hi @gorelov

Thanks for your reply, this helped me forward a great deal. I actually didn’t extend the default App but instead added a check on the normal login using the ‘isBackdoorLogin()’ logic. This enabled me to prevent the forwarding.

It is not the best solution but as we are to refactor the login screen anyway, this was a quick win.

We will see to implement a NavigationHandler when moving to release 7.2.

Regards,
-b