Vaadin Keycloak OAuth2 Integration

blog-post-img

Enhance security and simplify user management in your Vaadin application. This article shows how to configure Vaadin and Spring Security to use OAuth2 with Keycloak.

Setting Up Keycloak

First, we must start Keycloak and configure a realm. The easiest way is to start Keycloak with Docker.
Caution: This is just for development purposes. Don’t use the setup in production.

docker run -d -p 8180:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin \ 
       quay.io/keycloak/keycloak:20.0.1 start-dev

Now you can log in to the admin console: http://localhost:8180/admin (user: admin, password: admin)

Next we must create a realm and a user, add roles to the user, and finally, a client.

Create a realm

  1. Click on the drop-down in the upper left corner and select “Create realm”
  2. Enter the realm name “vaadin” and save

Create realm roles

  1. Select “Realm roles” in the menu
  2. Click “Create role”
  3. Enter the role name “admin” and save
  4. Repeat steps 1 to 3 with the role “user”

Create users

  1. Select “Users” in the menu
  2. Click on “Create new user”
  3. Enter the user name “admin”
  4. Click on “Create”
  5. Select the tab “Credentials” and set a password
  6. Disable “Temporary” to prevent having to update the password on the first login
  7. Click “Save”
  8. Select the tab “Role mapping”
  9. Click on “Assign role”
  10. Choose the previously created roles “admin” and “user”
  11. Do the same for the user with username “user” but add only the role “user”

Create a client

  1. Select “Client” in the menu
  2. Click on “Create client”
  3. Enter the client id “vaadin”
  4. Click next and the save
  5. In the “Access settings” set
    • “Valid redirect URIs” to http://localhost:8080/*
    • “Web origins” to http://localhost:8080

Important: Role Mapping

Now comes a crucial step. We must disable the role mapping to the ID token. When I created the example, the roles were missing in the application, but thanks to Thomas Vitale’s answer on StackOverflow, I found the solution.

  1. Select “Client scopes”
  2. Select the client scope “roles”
  3. Click on the tab “Mappers”
  4. Select “realm roles”
  5. Disable “Add to ID token”

The configuration must look like this:

Vaadin Application Security Configuration

The example application is available on GitHub: https://github.com/simasch/vaadin-keycloak

First, we need to extend VaadinWebSecurity to set up the Vaadin Spring security integration. There we override the configure method.

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll();

    http.oauth2Login()
            .and()
            .logout()
            .addLogoutHandler(keycloakLogoutHandler)
            .logoutSuccessUrl("/");

    super.configure(http);
}

Starting from line 5, the generic OAuth2 login is configured, and a special LogoutHandler for Keycloak is configured. The LogoutHandler uses the Keycloak REST API to log out.

As we configured to map the roles to the userinfo we now need to map these roles to GrantedAuthority. The roles will be in the claim “realm_access”.

@Bean
public GrantedAuthoritiesMapper userAuthoritiesMapperForKeycloak() {
    return authorities -> {
        Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
        var authority = authorities.iterator().next();

        if (authority instanceof OidcUserAuthority oidcUserAuthority) {
            var userInfo = oidcUserAuthority.getUserInfo();

            if (userInfo.hasClaim("realm_access")) {
                var realmAccess = userInfo.getClaimAsMap("realm_access");
                var roles = (Collection<String>) realmAccess.get("roles");
                mappedAuthorities.addAll(roles.stream()
                        .map(role -> new SimpleGrantedAuthority("ROLE_" + role.toUpperCase()))
                        .toList());
            }
        }
        return mappedAuthorities;
    };
}

Finally, we must add the OAuth2 configuration in the application.properties file:

spring.security.oauth2.client.registration.keycloak.client-id=vaadin
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8180/realms/vaadin
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username

Now you can start the application and open http://localhost:8080.

As you can see in the menu on the left, there is only one entry, “Index”.

Click on the “Sign in” button in the lower left corner. This will direct you to the Keycloak login screen.

Sign in with admin/admin and you’ll be redirected to the app:

Now you have access to all views.

Conclusion

Setting up Vaadin, Spring Security, and Keycloak is straight forwarded. The only tricky part was the role mapping to get the realm roles as GranteAuthority. If you encounter any difficulties, don’t hesitate to reach out – I’m here to help!

Related Posts

Simon Martinelli
Follow Me