Servlet Security

Hi Team,

I am new to servlets. I have followed this quide in setting one up Registration of Servlets and Filters - CUBA Platform. Developer’s Manual

I am wondering if it is possible to protect the servlet routes with user authentication?

e.g. i would like to protect the following so that only an admin user can access the route.

Ideally I would also like to embed the route in a browserframe.

@Component
public class WebInitializer {

    @Inject
    private ServletRegistrationManager servletRegistrationManager;

    @EventListener
    public void initializeHttpServlet(ServletContextInitializedEvent e) {
        Servlet myServlet = servletRegistrationManager.createServlet(
                e.getApplicationContext(), "com.demo.comp.MyHttpServlet");

        e.getSource().addServlet("my_servlet", myServlet)
                .addMapping("/myservlet/*");
    }
}

Am basically trying to figure out how to do the Xero authentication as described here:

I can get the servlet to generate the tokens but not sure how to protect the servlet route and also how to get the returned tokens back into the cuba app. i.e. not sure how to do the authentication on a servlet (if it is possible?)

Hi,
You should create this servlet in the web module of your project. Then register it and its mapping in the web.xml of the web module.

Regarding user authentication - I doubt that it is necessary.
If these endpoints are going to be called automatically by external system - then the protocol is fixed by the Xero, it’s low probably that they will be able to send more parameters to your system. The necessary authentication protection options should already be built into communication protocol.

Anyway, you can use:

  • filtering by IP address (of the external system that is going to send requests)
  • protection by basic auth (user and password).
  • or check IP address / user / password / token manually in the servlet itself, by reading request.getRemoteAddr() or one of request headers.

If you use Tomcat, both ways can be configured.
E.g.
Access with user/password - Secure Tomcat Hosting: Restrict Access to Your Web Application | Virtuozzo
Access by IP address - Apache Tomcat 7 Configuration Reference (7.0.109) - Container Provided Filters

Thanks Alex,

I guess the security is not too much of an issue now. And yes they would have to create an app with my servers address within xero anyway.
I implemented the GlobalEvents and have a call back to an admin screen with a popup to accept the generated token from Xero. Works like a charm and was rather simple to implement.

However, I do have one issue. Cuba seems to intercept the servlet address. e.g. localhost:8080/app/myservlet keeps getting redirected to localhost:8080/app/. The only way around this is to use a browser with history deleted. Not sure if you have any suggestions on how to resolve this? What I was trying to do was have a button inside of my cuba app that opens the servlet page to do the auth process.

My code i have tried (also tried just using a link)

@Subscribe("xeroAuthButton")
protected void onXeroAuthButtonClick(Button.ClickEvent event) {
    webBrowserTools.showWebPage(globalConfig.getWebAppUrl()+"/xero/auth/authorize", ParamsMap.of("_target", "blank"));
}

I create the servlets programmatically but it still does the same if I build them in web.xml.

You should declare your own /app/xero/ servlet mapping in the web.xml before the main servlet (app_servlet).

like adviced here:

Thanks Alex,

I had tried that. But it seems the browser history needed to be deleted to get it to work.

The only other issue is that I am trying to build an add-on app component and I think the settings in web.xml of the app-component get overridden by the main parent app. Is there any way to set the precedence programmatically?

e.g. with

@EventListener
public void initXeroAuthServlet(ServletContextInitializedEvent e) {
    Servlet authorizationServlet = servletRegistrationManager.createServlet(
            e.getApplicationContext(), "com.daryn.xeroapi.xero.XeroAuthorization");
    e.getSource().addServlet("xero_auth", authorizationServlet)
            .addMapping("/xero/auth/authorize");
}

Have it programatically load before /* in web.xml?

Seem to have gotten it working!

  @EventListener
    @Order(Events.LOWEST_PLATFORM_PRECEDENCE)
    public void initXeroAuthServlet(ServletContextInitializedEvent e) {
        Servlet authorizationServlet = servletRegistrationManager.createServlet(
                e.getApplicationContext(), "com.daryn.xeroapi.xero.XeroAuthorization");
        e.getSource().addServlet("xero_auth", authorizationServlet)
                .addMapping("/xero/auth/authorize");