A Hybrid Approach to Spring Security in Vaadin Applications

In my previous blog post about Spring Security, I wrote about filter-based security and how to use that in your Vaadin applications. In this blog post, we are going to look at another way of utilizing Spring Security.

In addition to filters, Spring Security has other ways of protecting your application. In the backend layer, the most commonly used one is method level security. For every secure class, you declare what permissions or roles the current user must have to be able to invoke a method.

During runtime, the secured bean will actually be proxied and an interceptor will perform the authorization before letting the invocation proceed to the real object. This is important to remember when working with Vaadin.

In a Vaadin application, UI components can also be Spring managed beans. Technically, you can therefore apply method level security to your Vaadin components. This is not a good idea since Vaadin does not play nicely with proxied components. Although it might sometimes work, you might end up getting strange client side error notifications when a server-side component and its client-side widget fail to find each other because of the proxy.

On the other hand, method level security in the backend layer will work very well with your Vaadin application and that is something we are going to utilize in the hybrid approach to using Spring Security.

Introducing the hybrid approach

The general idea behind the hybrid approach is to handle the UI layer security yourself and let Spring Security worry about the security from the backend and onwards using method level security. This will give your users a better user experience since everything, including login and logout, will be handled inside your Vaadin application. There are no redirects or auto-generated error pages to deal with. In the next sections, we are going to look at all the things you have to handle yourself when Spring Security is no longer used in the UI layer.

As before, you can find working code samples on GitHub.

Configuration

The Spring Security configuration for the hybrid approach is a lot simpler than for the filter approach. Web security should be completely disabled for the application. Global method security should be enabled and the authentication manager should be properly configured. That’s basically it and it is demonstrated in the sample code.

Managing the security context

Since there is no filter that will manage the security context, you have to do it yourself. This is actually pretty easy. You have to implement your own SecurityContextHolderStrategy and plug it into the SecurityContextHolder when the application starts up. The strategy would then access the current VaadinSession to store and retrieve the security context.

By managing the security context in this way and storing it in the Vaadin session as opposed to the HTTP session, you can use any supported Vaadin transport protocol including websockets.  The security context will also be available inside all UI.access() calls, even when initiated from a background thread.

However, this is also the biggest security risk since the security context is the key to your backend. You have to be careful you are not accidentally leaking the security context to other sessions - or other threads, for that matter.

Authentication

Performing the actual authentication is still done by Spring Security, but your application will have to implement the login form and the logic for showing or hiding it. You can do this in the following way:

  1. In the init(...) method of your UI, you need to check whether the current user is authenticated or not. You can do this by examining the current SecurityContext.
  2. If authentication is required, you set the content of your UI to your login form. If not, you set the content to your main screen.
  3. When the user attempts to login, you send an authentication token (e.g. a UsernamePasswordAuthenticationToken) to the AuthenticationManager. If an exception is thrown, the authentication has failed and you show an error message. Otherwise, you save the authentication token in the current SecurityContext and replace the content of your UI with your main screen.

This approach also makes it easy to write applications where some features do not require authentication and others do. You could just pop up your own login window whenever authentication is needed, without having to redirect to another URL and then back.

Please note, however, that Spring Security’s remember me authentication does not work with this approach since it relies heavily on HTTP requests. If you want to support remember me, you have to implement it more or less from scratch.

Session fixation protection

A common practice to protect against session fixation attacks is to create a new session immediately after a user has been authenticated and invalidate the old one. Vaadin has a method for doing just this that you can invoke after the user has been authenticated, but before you store the authentication token in the SecurityContext:

VaadinService.reinitializeSession(VaadinService.getCurrentRequest());

Unfortunately, there is a catch: this will most likely not work if you are using websockets. Fortunately, there are at least three different ways around this:

  1. If you are using Vaadin 7.6 or newer, you can use the new WEBSOCKET_XHR transport that was already mentioned earlier in this article.
  2. Disable push completely in the login page (i.e. don’t put @Push on your UI) and programmatically enable it after the user has logged on. This approach is demonstrated in the sample code.
  3. Use a push mechanism that uses basic HTTP.

Protecting your views

Protecting views and hiding or showing components based on the current user’s permissions have to be completely handled by the Vaadin application (but this was also the case when using filter-based security). How exactly this is done depends on the requirements. One way could be to query the granted authorities of the current user, for example in a helper method.

If the Navigation API is used, a custom ViewAccessControl can be used to grant or deny access to individual views. The SpringViewProvider will automatically pick up and use a Spring bean that implements this interface. It will be queried before any view is created and returned by the view provider. If access to a view is denied, you can choose to either act like the view did not exist in the first place (the default behavior) or you can plug in an access denied view that is shown to the user. This is demonstrated in the sample code.

As mentioned before, you should not use method level security on your UI components because of the proxies. If you are reusing any of the Spring security annotations on your views, make sure that the method level security configuration ignores your UI classes.

Handling errors

Ideally, your application’s UI should be designed in such a way that any forbidden actions are not even available to the user. However, there may still be cases where a forbidden operation is performed and your application will need to handle these appropriately. The easiest way of doing this is to override the default error handler in your UI. Depending on how you set up your application, you should at least be able to recognize and react to the AccessDeniedException, possible also to the AuthenticationException. This is demonstrated in the sample code.

Logging out

Finally, when the user is done, you have to handle logging out. This is also one of the more critical parts of the application since it should be absolutely impossible to get back into the application without authenticating after logout. There can not be any references to the security context laying around.

How you handle logout depends on your requirements. The simplest way is to just kill the session and reload the page, as demonstrated in the sample code. However, if you have an application where the user can continue to use some features unauthenticated, you have to handle this in some other way. Also think about how you are going to deal with multiple UI instances being open at the same time. What will happen with the other browser windows when you log out? The sample application will simply reload the page, showing the login form again in all the browser windows.

 

Using Polymer components in Angular 2

Angular and Polymer working together

We have some great news for all Angular 2 users out there! While working on providing a seamless Angular 2 integration to Vaadin Elements, we ended up building a universal Polymer to Angular 2 adapter that allows you to use any Polymer Element in your Angular 2 application. This means that in addition to all Vaadin Elements, you are able to use any Polymer Element or other Polymer based web component out there in Angular 2.

The @vaadin/angular2-polymer directive takes care of defining the needed inputs and outputs as well as adding support for ngControl and ngForm, allowing Polymer components to behave like any other Angular 2 component. The directive will also handle all shadow DOM operations within templates.

Using the @vaadin/angular2-polymer directive

After installing the directive and any Polymer elements you want to use, you can include the components in your app by including PolymerElement('element-name') in your component's directives.

demo.component.ts

import { Component } from '@angular/core';
import { PolymerElement } from '@vaadin/angular2-polymer';

@Component({
  moduleId: module.id,
  selector: 'demo-app',
  templateUrl: 'demo.component.html',
  directives: [
    PolymerElement('vaadin-grid')
  ]
})
export class DemoAppComponent {
  people: Person[] = [
    {
      firstName: 'John',
      lastName: 'Doe',
      email: 'john@company.com'
    },{
      firstName: 'Jane',
      lastName: 'Doe',
      email: 'jane@company.com'
    }];
}

demo.component.html

  <vaadin-grid [items]="people">
    <table>
      <colgroup>
        <col name="firstName">
        <col name="lastName">
        <col name="email">
      </colgroup>
    </table>
  </vaadin-grid>

Getting started

Excited to try out the beta? Check out our Angular 2 and Polymer quickstart tutorial and tutorial video, then head over to the Vaadin Elements catalog to explore all the new components available to you.

If you find something that doesn't seem right, help us out by filing a ticket on the angular2-polymer GitHub page.

Browse all Vaadin Elements and code examples.

Building a web UI for an Azure SQL Server in plain Java

Azure is one of the leading PaaS and IaaS providers, and, despite being a Microsoft service, it is an excellent choice to host Java web applications. I had a chance to host a webinar with Microsoft’s OSS folks about running Java web apps in Azure and during that, I also figured out that Azure is probably the easiest way to get an access to SQL Server, which is essential for many web developers. SQL Server is a proven basis for many busines apps, but you cannot install it that easily on your workstation, especially if you have a Mac or Linux as your development machine.

Using Azure you can easily create SQL Server instances and databases for your projects and also use them remotely during development. Let’s see how you can create an Azure SQL database, load it with a demo data-set and build a modern HTML5 UI for it - using nothing but Java.

Create the database and load it with test data

To start up, you’ll need an Azure account and head to portal.azure.com. From the left menu, choose SQL databases and hit “+” button. The wizard will take you through creating a database server and a database.

Whether you are developing or learning, you might also wish to populate your database with some demo data. For this tutorial I chose the “Sample” dataset as a basis.

Open up the firewall for your workstation

As you most probably want to run a development version of your application locally on your workstation, you also need to let Azure know it should accept connections from it. This is defined per database, so you must choose “All resources” from the main menu and locate the SQL Server which is hosting your database. The “Essentials” panel for your server contains a shortcut to firewall settings, from there click “Add client IP” button and the server will automatically create a rule that allows connections from your current IP address.

You can now try to connect to the server with some SQL client to verify everything works. I configured the JDBC driver to NetBeans and it was an easy to access database with the IDEs built-in SQL server tooling. Setting up some basic SQL client may be handy later when debugging some SQL queries, but it is not necessary in this tutorial.

Connecting from Java web apps

The first thing we need with Java apps is the JDBC driver for SQL Server. You can download it from Microsoft for free. Most Java developers nowadays use a dependency management system, but the driver is not available from any public Maven repository. Thus, you should probably install it to your company’s Maven proxy or to your local maven repository. I used Maven coordinates com.microsoft.sqlserver:sqljdbc42:4.2, but use the convention you are used to.

One could now go with low level JDBC API and make queries to the database, but that seldom really makes sense. Pretty much always you should choose either a Java EE server and use its data sources or go with the Spring stack. This way you’ll get e.g. a proper connection pooling for serious deployment and it is actually also easier to connect to the database this way. Let’s use Spring Boot, Spring Data and JPA repositories in this exercise.

To create a project stub for this exercise, go to start.spring.io. Add  JPA and Vaadin modules to your application.

Next we’ll need to add the JDBC driver dependency to the project. If you installed it with the same “Maven coordinates”  as I did, just add the following dependency to the pom.xml file:

 <dependency>
    <groupId>com.microsoft.sqlserver</groupId>
    <artifactId>sqljdbc42</artifactId>
    <version>4.2</version>
</dependency>

Azure makes it really easy to create the JDBC connection. You can just go to the console, find your database and copy the JDBC connection string to your clipboard. With Spring Data, you can just place the JDBC connection string to your application.properties file, which start.spring.io by default created to src/main/resources/. Also, you can explicitly specify the JDBC driver and hibernate dialect to be used. After this step my application.properties file looked like this:

spring.datasource.url=jdbc:sqlserver://vaadin-demo.database.windows.net:1433;database=vaadin-demo;user=vaadin-demo@vaadin-demo;password=******;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect

As we chose to use JPA to map the database data into Java classes, we now need JPA entity objects. I used the reverse engineering tools in NetBeans to automatically create a domain model from the example dataset. But let’s not concentrate on using reverse engineering tools in this tutorial and you can just copy my Customer JPA entity class to your application.

Also note that by default Spring Data uses a naming strategy that doesn’t respect the @Column annotations in the entity class created by NetBeans. Thus, you need to replace that with e.g. hibernates default naming strategy by adding the following configuration to your application.properties file:

spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy

We could now use the EntityManager API to access the database, but with Spring Data it makes more sense to create a repository for the Customer entities. Create the following interface to your application:

package com.example;

import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository {
}

Based on that interface alone, Spring Data will generate a repository instance via which we can make all basic CRUD operations. Naturally, you’ll add your domain specific query methods to that later.

Now we are ready to actually start building the UI to access your data. Vaadin core is basically just a set of core components you use to build your application. The UI class is the “root” of your component tree and its init method is called when a user opens the mapped webpage. You can also extend Vaadin really easily or use some of the numerous add-on libraries.

To create a really simple listing from the database running in Azure, create a VaadinUI class with the following implementation:

package com.example;

import com.vaadin.annotations.Theme;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.server.VaadinRequest;
import com.vaadin.spring.annotation.SpringUI;
import com.vaadin.ui.Table;
import com.vaadin.ui.UI;
import java.util.Arrays;
import org.springframework.beans.factory.annotation.Autowired;

@SpringUI
@Theme("valo")
public class VaadinUI extends UI {

   @Autowired
   CustomerRepository repo;

   @Override
   protected void init(VaadinRequest vaadinRequest) {
       Table table = new Table();
       table.setContainerDataSource(
               new BeanItemContainer(Customer.class, repo.findAll()),
               Arrays.asList("firstName", "lastName", "emailAddress")
       );
       setContent(table);
   }
}

Now if you run the main method of the Application class or execute “mvn spring-boot:run” from the project root, you’ll get a web server running at http://localhost:8080 with the following UI:

I’d call this a dead simple way for Java developers to build a web UI for SQL Server. The full example we built in the webinar is available via GitHub, but more than that, if you want to extend this example, I suggest you should refer to Vaadin tutorials and look into my Spring Data + Vaadin example.

Watch the Building Web Apps In 100% Java webinar by Microsoft

(Register to see the recorded webinar)