DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Because the DevOps movement has redefined engineering responsibilities, SREs now have to become stewards of observability strategy.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Related

  • Authentication With Remote LDAP Server in Spring Web MVC
  • Spring Security Oauth2: Google Login
  • How To Implement OAuth2 Security in Microservices
  • Enterprise RIA With Spring 3, Flex 4 and GraniteDS

Trending

  • How to Create a Successful API Ecosystem
  • Event-Driven Microservices: How Kafka and RabbitMQ Power Scalable Systems
  • Apple and Anthropic Partner on AI-Powered Vibe-Coding Tool – Public Release TBD
  • Efficient API Communication With Spring WebClient
  1. DZone
  2. Coding
  3. Java
  4. Implementing Authentication and Authorization With Vaadin

Implementing Authentication and Authorization With Vaadin

Learn how to implement a login screen and control access to the application based on user roles

By 
Alejandro Duarte user avatar
Alejandro Duarte
DZone Core CORE ·
Mar. 04, 21 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
9.2K Views

Join the DZone community and get the full member experience.

Join For Free

This article shows how to implement authentication and authorization in Spring Boot Vaadin Flow applications without using Spring Security.


Why Without Spring Security?

Spring Security is a powerful framework designed for web applications based on the request/response paradigm. Vaadin hides this paradigm so you can focus on the application and UI logic without having to deeply understand the underlying web technologies. Although it's possible to use Spring Security with Vaadin, doing so requires more work than the approach shown in this article.

Creating a New Project

Start by creating a new Vaadin application with three views:

  • Login (/login)
  • Home (/home)
  • Admin (/admin)

Use Java-only views and select the template you want for each view.

The Data Model

Create a Role enum to encapsulate the different roles that users can have in the application as follows:

Java
 




x


 
1
public enum Role {
2

          
3
    USER, ADMIN
4

          
5
}


Create a User class to encapsulate the login data:

Java
 




x


 
1
@Entity
2
public class User extends AbstractEntity {
3

          
4
    private String username;
5
    private String passwordSalt;
6
    private String passwordHash;
7
    private Role role;
8

          
9
    public User() {
10
    }
11

          
12
    public User(String username, String password, Role role) {
13
        this.username = username;
14
        this.role = role;
15
        this.passwordSalt = RandomStringUtils.random(32);
16
        this.passwordHash = DigestUtils.sha1Hex(password + passwordSalt);
17
    }
18

          
19
    public boolean checkPassword(String password) {
20
        return DigestUtils.sha1Hex(password + passwordSalt).equals(passwordHash);
21
    }
22

          
23
    ... getters and setters ...
24
}


This implementation uses Apache Commons Codec to encrypt the password and Apache Commons Lang to generate a random salt string. This makes it harder to hack passwords using "dictionary attacks" and avoids compromising users with the same password. The implementation also uses the AbstractEntity class included in the generated project. This class contains an id field and equals and hashCode implementations suitable for a JPA entity.

To gain access to the database, add the following Spring Data repository interface:

Java
 




xxxxxxxxxx
1


 
1
public interface UserRepository extends JpaRepository<User, Integer> {
2

          
3
    User getByUsername(String username);
4

          
5
}


Notice that you don't have to implement this interface since Spring Data will create an implementation at runtime. The interface offers many other useful methods that you should get familiar with.

Implementing the Authentication Service

Create a new AuthService class to encapsulate the authentication and authorization logic:

Java
 




xxxxxxxxxx
1
50


 
1
@Service
2
public class AuthService {
3

          
4
    public record AuthorizedRoute(String route, String name, Class<? extends Component> view) {
5
    }
6

          
7
    public class AuthException extends Exception {
8
    }
9

          
10

          
11
    private final UserRepository userRepository;
12

          
13
    public AuthService(UserRepository userRepository) {
14
        this.userRepository = userRepository;
15
    }
16

          
17
    public void authenticate(String username, String password) throws AuthException {
18
        User user = userRepository.getByUsername(username);
19
        if (user != null && user.checkPassword(password)) {
20
            VaadinSession.getCurrent().setAttribute(User.class, user);
21
            createRoutes(user.getRole());
22
        } else {
23
            throw new AuthException();
24
        }
25
    }
26

          
27
    private void createRoutes(Role role) {
28
        getAuthorizedRoutes(role).stream()
29
                .forEach(route ->
30
                        RouteConfiguration.forSessionScope().setRoute(
31
                                route.route, route.view, MainView.class));
32
    }
33

          
34
    public List<AuthorizedRoute> getAuthorizedRoutes(Role role) {
35
        var routes = new ArrayList<AuthorizedRoute>();
36

          
37
        if (role.equals(Role.USER)) {
38
            routes.add(new AuthorizedRoute("home", "Home", HomeView.class));
39
            routes.add(new AuthorizedRoute("logout", "Logout", LogoutView.class));
40

          
41
        } else if (role.equals(Role.ADMIN)) {
42
            routes.add(new AuthorizedRoute("home", "Home", HomeView.class));
43
            routes.add(new AuthorizedRoute("admin", "Admin", AdminView.class));
44
            routes.add(new AuthorizedRoute("logout", "Logout", LogoutView.class));
45
        }
46

          
47
        return routes;
48
    }
49

          
50
}


The authenticate method tries to find a user in the database with the given credentials and if it succeeds, a reference to the user is stored in the session and the available routes (links to views in the application) are created for the corresponding user role. If no user is found, an exception is thrown so that the view can show a suitable message.

The createRoutes method takes the routes available to the specified role and adds them to the route configuration of Vaadin, making them accessible. The getAuthorizedRoutes method in this example builds a list with the routes for a role in a "hard-coded" fashion. Other implementations may build this list from an external source like a database, for example.

Implementing the Login View

You can use any available components to implement a login form. For example, you can use the LoginForm class or alternatively create a custom implementation like the following:

Java
 




x


 
1
@Route(value = "login")
2
@PageTitle("Login")
3
@CssImport("./styles/views/login/login-view.css")
4
public class LoginView extends Div {
5

          
6
    public LoginView(AuthService authService) {
7
        setId("login-view");
8
        var username = new TextField("Username");
9
        var password = new PasswordField("Password");
10
        add(
11
                new H1("Welcome"),
12
                username,
13
                password,
14
                new Button("Login", event -> {
15
                    try {
16
                        authService.authenticate(username.getValue(), password.getValue());
17
                        UI.getCurrent().navigate("home");
18
                    } catch (AuthService.AuthException e) {
19
                        Notification.show("Wrong credentials.");
20
                    }
21
                })
22
        );
23
    }
24

          
25
}


The view calls the service to perform the actual authentication and authorization setup logic (registering the routes available to the user).

Summary

You can find the complete source code at https://github.com/alejandro-du/vaadin-auth-example. Keep in mind that this code is intended to be an example of how you can use the RouteConfiguration class to register routes at runtime for authorization reasons and might not be production-ready. For instance, a known issue with the example is that users can't use the log-in view to authenticate again (or with a different user) if they are already logged in. I hope this example serves as a starting point for implementing the authentication and authorization logic in your Vaadin Flow applications.

authentication Vaadin Spring Framework Spring Security application

Opinions expressed by DZone contributors are their own.

Related

  • Authentication With Remote LDAP Server in Spring Web MVC
  • Spring Security Oauth2: Google Login
  • How To Implement OAuth2 Security in Microservices
  • Enterprise RIA With Spring 3, Flex 4 and GraniteDS

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!