Blog

OAuth 2 and Google Sign-in for a Vaadin Application

By  
Tarek Oraby
Tarek Oraby
·
On Mar 30, 2022 3:39:41 PM
·

login screen on a purple background

In this guide, we learn how to provide users with the ability to sign in to a Vaadin application using their Google account. While it’s fine to use the traditional username-password mechanism, using OAuth 2 tends to enhance security and simplify the sign-in process for the end users. Taking advantage of Vaadin Spring Security helpers, we’ll see how easy it is to create a minimal application that uses Google for authentication.

You can explore the full source code of this guide on GitHub. For plain Java projects, you can check this example implementation of Google OAuth 2-based login.

Google sign in screen on a purple background

What you need

  • About 15 minutes
  • JDK 17 or later
  • A Gmail email address

Step 1: Create Google OAuth 2.0 Client ID

To create a client ID, you will first need to create a Google Cloud project, and add an OAuth consent screen to that project. To do this, go to the OAuth consent screen at Google Cloud Platform. There you can create a new project and create its OAuth consent screen (select “External” when prompted for the “User Type” of the consent screen).

Once the project with a consent screen is created, go to the credentials page and do the following:

  1. Select “Create credentials”, followed by “OAuth client ID”. 
  2. When prompted for the application type, select “Web application”.
  3. In the “Authorized redirect URIs” field, add a new redirect for http://localhost:8080/login/oauth2/code/google.

Once the OAuth client is created, take a note of the generated client ID and client secret.

Step 2: Import a Started Project

Click here to download an empty project starter. Unpack the downloaded zip into a folder on your computer, and import the project in the IDE of your choice.

Step 3: Add Spring Security OAuth 2.0 Client

Add the following dependency to the pom.xml file:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

Then, to make the link to Google, add the following to your application.properties file (replacing the client ID and secret with the actual values that you obtained from the credentials page of the Google Cloud project):

Spring.security.oauth2.client.registration.google.client-id= 
<your client id>
spring.security.oauth2.client.registration.google.client-secret=
<your client secret>

Step 4: Add SecurityConfiguration Class

Next we configure Spring Security using the VaadinWebSecurity helper. VaadinWebSecurity provides basic Vaadin security configuration for the project out of the box. It sets up security rules for a Vaadin application and restricts all URLs to authenticated users, except for public resources and internal Vaadin URLs.

Add the following SecurityConfiguration class to your application. Note that in this class, we only need to alter the HttpSecurity configuration in order to add authentication support using OAuth 2.0. Other security configurations will be handled automatically by VaadinWebSecurity.

import com.vaadin.flow.spring.security.VaadinWebSecurity;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends VaadinWebSecurity {
   
   private static final String LOGIN_URL = "/login";
   
   @Override
   protected void configure(HttpSecurity http) throws Exception {
       super.configure(http);
       http.oauth2Login().loginPage(LOGIN_URL).permitAll();
   }
}

Step 5: Add Login View

After completing the previous step, any unauthenticated attempt to access a URL in the application will be redirected to the /login path. Now we need to create the actual login view. 

Add the following LoginView class, which is a standard Vaadin view with a link connecting to Google login services. Note that this view is annotated with @AnonymousAllowed in order to make the view publicly accessible for non-authenticated users.

import com.vaadin.flow.server.auth.AnonymousAllowed;
import com.vaadin.flow.component.html.Anchor;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;

@Route("login")
@AnonymousAllowed
public class LoginView extends VerticalLayout {
   /**
    * URL that Spring uses to connect to Google services
    */
   private static final String OAUTH_URL = "/oauth2/authorization/google";
   
   public LoginView() {
       Anchor loginLink = new Anchor(OAUTH_URL, "Login with Google");
       // Set router-ignore attribute so that Vaadin router doesn't handle the login request
       loginLink.getElement().setAttribute("router-ignore", true);
       add(loginLink);
       getStyle().set("padding", "200px");
       setAlignItems(FlexComponent.Alignment.CENTER);
   }
} 

Step 6: Add a Secure View

To verify that the sign-in mechanism is working as intended, let us now add a view that would be accessible to authenticated users only. The following MainView is annotated with @PermitAll to allow authenticated users to navigate to this view. The view also contains a logout button that users can use to explicitly log out. Note also that the view renders the user’s first name, last name, email, and picture as they appear in their Google account, using the OAuth2AuthenticatedPrincipal object. 

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.H2;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.VaadinServletRequest;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.core.OAuth2AuthenticatedPrincipal;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import javax.annotation.security.PermitAll;

@Route("")
@PermitAll
public class MainView extends VerticalLayout {

   private static final String LOGOUT_SUCCESS_URL = "/";

   public MainView() {
       Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
       OAuth2AuthenticatedPrincipal principal = (OAuth2AuthenticatedPrincipal) authentication.getPrincipal();

       String givenName = principal.getAttribute("given_name");
       String familyName = principal.getAttribute("family_name");
       String email = principal.getAttribute("email");
       String picture = principal.getAttribute("picture");

       H2 header = new H2("Hello " + givenName + " " + familyName + " (" + email + ")");
       Image image = new Image(picture, "User Image");

       Button logoutButton = new Button("Logout", click -> {
           UI.getCurrent().getPage().setLocation(LOGOUT_SUCCESS_URL);
           SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
           logoutHandler.logout(
                   VaadinServletRequest.getCurrent().getHttpServletRequest(), null,
                   null);
       });

       setAlignItems(Alignment.CENTER);
       add(header, image, logoutButton);
   }
}

Step 7: Run the Application

To run the project from the command line, type mvnw spring-boot:run (on Windows), or ./mvnw spring-boot:run (on macOS or Linux).

Then, in your browser, open http://localhost:8080/.

Go further

We have seen how to use Vaadin security helpers and Spring Security to build an application with Google sign-in. The approach described here can also be used to enable authentication using other OAuth 2.0 providers, such as GitHub for example. You can learn more about configuring security using Vaadin helpers in the documentation.

You can explore the full source code of this guide on GitHub.

Tarek Oraby
Tarek Oraby
Tarek is a Product Manager at Vaadin. His daily work is a blend of talking to users, planning, and overseeing the evolution of Vaadin Flow and Hilla, ensuring they consistently delight our developer community.
Other posts by Tarek Oraby