> Markdown version of [OAuth2 Authentication](https://vaadin.com/docs/next/flow/security/spring/oauth2). Section index: [llms.txt](https://vaadin.com/docs/next/flow/llms.txt)

# OAuth2 Authentication

Vaadin applications can be configured to authenticate users using an existing account at an OAuth 2.0 Provider (e.g., GitHub) or at an OpenID Connect 1.0 Provider (e.g., Google).

This page focuses on how to configure a Spring Boot project to integrate OAuth2 authentication in Vaadin. It assumes you’re familiar with setting up [Spring Security with Vaadin](https://vaadin.com/docs/next/flow/security/spring/setup.md). For detailed information about Spring Security and OAuth2, consult the [Spring documentation](https://docs.spring.io/spring-security/reference/servlet/oauth2/index.html).

## <a id="application-configuration"></a>Application Configuration

OAuth2 login needs the OAuth2 client of Spring Security, and a client registration for the provider in the application configuration. For a step-by-step guide with Keycloak as the provider, including how to register the application at Keycloak, see [Connect an Identity Provider](https://vaadin.com/docs/next/building-apps/security/connect-identity-provider.md).

### <a id="dependency"></a>Dependency

With Spring Boot, add the OAuth2 client starter. It includes the Spring Security starter:

`Maven`

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

`Gradle`

```groovy
implementation 'org.springframework.boot:spring-boot-starter-security-oauth2-client'
```

### <a id="client-registration"></a>Client Registration

Configure the provider and the credentials of the application with the `spring.security.oauth2.client` properties. The following example registers the application at a Keycloak realm:

`application.properties`

```properties
spring.security.oauth2.client.registration.keycloak.client-id=my-app
spring.security.oauth2.client.registration.keycloak.client-secret=${KEYCLOAK_CLIENT_SECRET}
spring.security.oauth2.client.registration.keycloak.scope=openid,profile,email

spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost:8180/realms/my-realm
```

`application.yaml`

```yaml
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: my-app
            client-secret: ${KEYCLOAK_CLIENT_SECRET}
            scope: openid,profile,email
        provider:
          keycloak:
            issuer-uri: http://localhost:8180/realms/my-realm
```

- `keycloak`

  The *registration ID*. You choose it, and it appears in the URLs that Spring Security uses for the login, such as `/oauth2/authorization/keycloak`, which [Enable OAuth2 Login in Vaadin](#enable-oauth2-login-in-vaadin) uses as the login page.

- `client-id` and `client-secret`

  The credentials of the application at the provider. Read the secret from an environment variable, so that it doesn’t end up in version control.

- `scope`

  The `openid` scope makes the login an OpenID Connect login. The `profile` and `email` scopes give the application the name and email address of the user.

- `issuer-uri`

  The URL of the provider. Spring Security reads the endpoints and signing keys of the provider from its discovery document.

For other providers, and for providers that have no discovery document, see the [Spring Security documentation](https://docs.spring.io/spring-security/reference/servlet/oauth2/login/core.html#oauth2login-common-oauth2-provider).

## <a id="enable-oauth2-login-in-vaadin"></a>Enable OAuth2 Login in Vaadin

To enable OAuth2 login in a Vaadin application, use the `VaadinSecurityConfigurer` class and configure the login page and post-logout redirect URI using the `oauth2LoginPage` method.

The method takes two parameters:

- Login Page: The URI capable of initiating the authentication request. Usually, it’s `/oauth2/authorization/{registrationId}`, where `registrationId` refers to the client registered in the application configuration file.

- Post Logout Redirect URI: The location where the user is redirected after logout.

The overload with only the login page defaults the post-logout redirect URL to `{baseUrl}`.

The post logout redirect URI can be expressed as a relative or absolute URI, or as a template. The supported URI template variables are `{baseScheme}`, `{baseHost}`, `{basePort}`, `{basePath}`, and `{baseUrl}` — which is the same as `{baseScheme}://{baseHost}{basePort}{basePath}`.

Enable OAuth Login in VaadinSecurityConfigurer

**VaadinSecurityConfigurer**

```java
@Configuration
class SecurityConfiguration {
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
            configurer.oauth2LoginPage(
                        "/oauth2/authorization/keycloak", // (1)
                        "{baseUrl}/session-ended"         // (2)
            );
        });
        return http.build();
    }
}
```

1. Login page for initiating OAuth2 login with the Keycloak client.

2. Post logout redirect URI uses a template to resolve dynamically the URL.

## <a id="keycloak-role-mapping"></a>Keycloak Role Mapping (V25.4 pre-release)

By default, Keycloak puts the roles of a user into the access token rather than into the ID token, and it does so in the `realm_access` and `resource_access` claims, which aren’t part of the OpenID Connect specification. Spring Security maps neither of them, so `@RolesAllowed("admin")` and `hasRole("admin")` never match a Keycloak role named `admin`, and access to the views and methods that they protect is denied.

Mapping those roles is opt-in per security filter chain. Enable it by calling the `keycloakRoleMapping()` method of `VaadinSecurityConfigurer`:

Enable Keycloak Role Mapping

**VaadinSecurityConfigurer**

```java
@Configuration
class SecurityConfiguration {
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.with(VaadinSecurityConfigurer.vaadin(), configurer -> {
            configurer.oauth2LoginPage("/oauth2/authorization/keycloak")
                    .keycloakRoleMapping(); // (1)
        });
        return http.build();
    }
}
```

1. Decodes the access token of the authenticated user and maps its roles to granted authorities.

Views and services can then be guarded with the plain Keycloak role name:

```java
@Route("admin")
@RolesAllowed("admin") // Matches the Keycloak realm role "admin"
public class AdminView extends VerticalLayout {
}
```

The mapping grants the following authorities:

- The realm roles from the `realm_access` claim of the access token.

- The roles that the `resource_access` claim grants for the client ID of the current client registration. Roles that it grants for other clients are ignored.

- The scopes of the access token, prefixed with `SCOPE_`, as the default user service grants them.

- The `OidcUserAuthority` of the authenticated user, built from the ID token and the userinfo claims, as the default user service grants it.

Realm roles and client roles both become role authorities that use the role prefix of the application, which is `ROLE_` unless a `GrantedAuthorityDefaults` bean or the `servletApi()` configuration of the filter chain sets another prefix.

> **Note:** The `keycloakRoleMapping()` method works only together with `oauth2LoginPage()` and its overloads. Without a login page for OAuth2 authentication, it logs a warning and has no effect.

Verifying the access token requires the JSON Web Key Set (JWKS) of the provider, which a client registration either resolves from its `issuer-uri` or takes from an explicitly configured `jwk-set-uri`. If the registration has no JWKS URI, or if the access token isn’t a JWT that the application can decode, the login still succeeds, but the user is mapped without any roles. Both cases are logged at debug level.

When the mapping is enabled, the configurer builds an `OidcUserService` for the OAuth2 login and shares it with the `HttpSecurity` instance, so it can be retrieved with `http.getSharedObject(OidcUserService.class)`.

### <a id="mapping-roles-on-a-custom-user-service"></a>Mapping Roles on a Custom User Service

Enabling the mapping replaces the `OidcUserService` of the filter chain. An application that builds its own user service should therefore leave `keycloakRoleMapping()` off and install the `KeycloakOidcUserMapper` converter on that service instead:

```java
var oidcUserService = new OidcUserService();
oidcUserService.setOidcUserConverter(new KeycloakOidcUserMapper());
```

The mapper prefixes roles with `ROLE_`. To apply another prefix — for example, to match a `GrantedAuthorityDefaults` bean — pass it to the constructor:

```java
new KeycloakOidcUserMapper("AUTHORITY_");
```

Configure the resulting user service on the OAuth2 login as described in the [Spring Security documentation](https://docs.spring.io/spring-security/reference/servlet/oauth2/login/advanced.html).

`EF8F6AC3-BE67-4BE2-9A78-C371C1D4B9FD`
