SimpleUI: add oauth2 support (#2400)
* simple-ui: add oauth2 support This uses a trick to ensure that the id token is refreshed; it needs to be revisited after Spring Security 6.5 is released * fixed style and added a way to enable / disable oauth2 client
This commit is contained in:
@@ -81,6 +81,10 @@
|
|||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-security</artifactId>
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-oauth2-client</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@@ -9,13 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.ui.simple;
|
package org.eclipse.hawkbit.ui.simple;
|
||||||
|
|
||||||
import static feign.Util.ISO_8859_1;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import com.vaadin.flow.component.page.AppShellConfigurator;
|
import com.vaadin.flow.component.page.AppShellConfigurator;
|
||||||
import com.vaadin.flow.server.PWA;
|
import com.vaadin.flow.server.PWA;
|
||||||
import com.vaadin.flow.theme.Theme;
|
import com.vaadin.flow.theme.Theme;
|
||||||
@@ -28,7 +21,9 @@ import feign.codec.ErrorDecoder;
|
|||||||
import org.eclipse.hawkbit.sdk.HawkbitClient;
|
import org.eclipse.hawkbit.sdk.HawkbitClient;
|
||||||
import org.eclipse.hawkbit.sdk.HawkbitServer;
|
import org.eclipse.hawkbit.sdk.HawkbitServer;
|
||||||
import org.eclipse.hawkbit.sdk.Tenant;
|
import org.eclipse.hawkbit.sdk.Tenant;
|
||||||
|
import org.eclipse.hawkbit.ui.simple.security.OAuth2TokenManager;
|
||||||
import org.eclipse.hawkbit.ui.simple.view.util.Utils;
|
import org.eclipse.hawkbit.ui.simple.view.util.Utils;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
|
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
|
||||||
@@ -40,6 +35,21 @@ import org.springframework.security.core.Authentication;
|
|||||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
|
||||||
|
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
||||||
|
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
import static feign.Util.ISO_8859_1;
|
||||||
|
import static java.util.Collections.emptyList;
|
||||||
|
|
||||||
@Theme(themeClass = Lumo.class)
|
@Theme(themeClass = Lumo.class)
|
||||||
@PWA(name = "hawkBit UI", shortName = "hawkBit UI")
|
@PWA(name = "hawkBit UI", shortName = "hawkBit UI")
|
||||||
@@ -47,11 +57,18 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
|||||||
@Import(FeignClientsConfiguration.class)
|
@Import(FeignClientsConfiguration.class)
|
||||||
public class SimpleUIApp implements AppShellConfigurator {
|
public class SimpleUIApp implements AppShellConfigurator {
|
||||||
|
|
||||||
private static final RequestInterceptor AUTHORIZATION = requestTemplate -> {
|
private static final Function<OAuth2TokenManager, RequestInterceptor> AUTHORIZATION = (oAuth2TokenManager) -> requestTemplate -> {
|
||||||
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
requestTemplate.header("Authorization", "Basic " + Base64.getEncoder().encodeToString(
|
if (oAuth2TokenManager != null && authentication instanceof OAuth2AuthenticationToken oAuth2AuthenticationToken) {
|
||||||
(Objects.requireNonNull(authentication.getPrincipal(), "User is null!") + ":" + Objects.requireNonNull(
|
String bearerToken = oAuth2TokenManager.getToken(oAuth2AuthenticationToken);
|
||||||
authentication.getCredentials(), "Password is not available!")).getBytes(ISO_8859_1)));
|
requestTemplate.header("Authorization", "Bearer " + bearerToken);
|
||||||
|
} else {
|
||||||
|
requestTemplate.header(
|
||||||
|
"Authorization", "Basic " + Base64.getEncoder().encodeToString(
|
||||||
|
(Objects.requireNonNull(authentication.getPrincipal(), "User is null!") + ":" + Objects.requireNonNull(
|
||||||
|
authentication.getCredentials(), "Password is not available!")).getBytes(ISO_8859_1))
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final ErrorDecoder DEFAULT_ERROR_DECODER = new ErrorDecoder.Default();
|
private static final ErrorDecoder DEFAULT_ERROR_DECODER = new ErrorDecoder.Default();
|
||||||
@@ -67,13 +84,21 @@ public class SimpleUIApp implements AppShellConfigurator {
|
|||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
HawkbitClient hawkbitClient(
|
HawkbitClient hawkbitClient(
|
||||||
final HawkbitServer hawkBitServer, final Encoder encoder, final Decoder decoder, final Contract contract) {
|
final HawkbitServer hawkBitServer,
|
||||||
|
final Encoder encoder,
|
||||||
|
final Decoder decoder,
|
||||||
|
final Contract contract,
|
||||||
|
@Autowired(required = false)
|
||||||
|
final OAuth2TokenManager oAuth2TokenManager
|
||||||
|
) {
|
||||||
return new HawkbitClient(
|
return new HawkbitClient(
|
||||||
hawkBitServer, encoder, decoder, contract,
|
hawkBitServer, encoder, decoder, contract,
|
||||||
ERROR_DECODER,
|
ERROR_DECODER,
|
||||||
(tenant, controller) ->
|
(tenant, controller) ->
|
||||||
controller == null ?
|
controller == null
|
||||||
AUTHORIZATION : HawkbitClient.DEFAULT_REQUEST_INTERCEPTOR_FN.apply(tenant, controller));
|
? AUTHORIZATION.apply(oAuth2TokenManager)
|
||||||
|
: HawkbitClient.DEFAULT_REQUEST_INTERCEPTOR_FN.apply(tenant, controller)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
@@ -81,6 +106,27 @@ public class SimpleUIApp implements AppShellConfigurator {
|
|||||||
return new HawkbitMgmtClient(tenant, hawkbitClient);
|
return new HawkbitMgmtClient(tenant, hawkbitClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService(final HawkbitMgmtClient hawkbitClient) {
|
||||||
|
final OidcUserService delegate = new OidcUserService();
|
||||||
|
return (userRequest) -> {
|
||||||
|
OidcUser oidcUser = delegate.loadUser(userRequest);
|
||||||
|
|
||||||
|
final OAuth2AuthenticationToken tempToken = new OAuth2AuthenticationToken(
|
||||||
|
oidcUser,
|
||||||
|
emptyList(),
|
||||||
|
userRequest.getClientRegistration().getRegistrationId()
|
||||||
|
);
|
||||||
|
final List<SimpleGrantedAuthority> grantedAuthorities =
|
||||||
|
getGrantedAuthorities(hawkbitClient, tempToken);
|
||||||
|
return new DefaultOidcUser(
|
||||||
|
grantedAuthorities,
|
||||||
|
oidcUser.getIdToken(),
|
||||||
|
oidcUser.getUserInfo()
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// accepts all user / pass, just delegating them to the feign client
|
// accepts all user / pass, just delegating them to the feign client
|
||||||
@Bean
|
@Bean
|
||||||
AuthenticationManager authenticationManager(final HawkbitMgmtClient hawkbitClient) {
|
AuthenticationManager authenticationManager(final HawkbitMgmtClient hawkbitClient) {
|
||||||
@@ -88,35 +134,9 @@ public class SimpleUIApp implements AppShellConfigurator {
|
|||||||
final String username = authentication.getName();
|
final String username = authentication.getName();
|
||||||
final String password = authentication.getCredentials().toString();
|
final String password = authentication.getCredentials().toString();
|
||||||
|
|
||||||
final List<String> roles = new LinkedList<>();
|
final List<SimpleGrantedAuthority> grantedAuthorities = getGrantedAuthorities(
|
||||||
roles.add("ANONYMOUS");
|
hawkbitClient, new UsernamePasswordAuthenticationToken(username, password));
|
||||||
final SecurityContext unauthorizedContext = SecurityContextHolder.createEmptyContext();
|
return new UsernamePasswordAuthenticationToken(username, password, grantedAuthorities) {
|
||||||
unauthorizedContext.setAuthentication(
|
|
||||||
new UsernamePasswordAuthenticationToken(username, password));
|
|
||||||
final SecurityContext currentContext = SecurityContextHolder.getContext();
|
|
||||||
try {
|
|
||||||
SecurityContextHolder.setContext(unauthorizedContext);
|
|
||||||
if (hawkbitClient.hasSoftwareModulesRead()) {
|
|
||||||
roles.add("SOFTWARE_MODULE_READ");
|
|
||||||
}
|
|
||||||
if (hawkbitClient.hasRolloutRead()) {
|
|
||||||
roles.add("ROLLOUT_READ");
|
|
||||||
}
|
|
||||||
if (hawkbitClient.hasDistributionSetRead()) {
|
|
||||||
roles.add("DISTRIBUTION_SET_READ");
|
|
||||||
}
|
|
||||||
if (hawkbitClient.hasTargetRead()) {
|
|
||||||
roles.add("TARGET_READ");
|
|
||||||
}
|
|
||||||
if (hawkbitClient.hasConfigRead()) {
|
|
||||||
roles.add("CONFIG_READ");
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
SecurityContextHolder.setContext(currentContext);
|
|
||||||
}
|
|
||||||
return new UsernamePasswordAuthenticationToken(
|
|
||||||
username, password,
|
|
||||||
roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).toList()) {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eraseCredentials() {
|
public void eraseCredentials() {
|
||||||
@@ -126,4 +146,33 @@ public class SimpleUIApp implements AppShellConfigurator {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<SimpleGrantedAuthority> getGrantedAuthorities(final HawkbitMgmtClient hawkbitClient, Authentication authentication) {
|
||||||
|
final List<String> roles = new LinkedList<>();
|
||||||
|
roles.add("ANONYMOUS");
|
||||||
|
final SecurityContext unauthorizedContext = SecurityContextHolder.createEmptyContext();
|
||||||
|
unauthorizedContext.setAuthentication(authentication);
|
||||||
|
final SecurityContext currentContext = SecurityContextHolder.getContext();
|
||||||
|
try {
|
||||||
|
SecurityContextHolder.setContext(unauthorizedContext);
|
||||||
|
if (hawkbitClient.hasSoftwareModulesRead()) {
|
||||||
|
roles.add("SOFTWARE_MODULE_READ");
|
||||||
|
}
|
||||||
|
if (hawkbitClient.hasRolloutRead()) {
|
||||||
|
roles.add("ROLLOUT_READ");
|
||||||
|
}
|
||||||
|
if (hawkbitClient.hasDistributionSetRead()) {
|
||||||
|
roles.add("DISTRIBUTION_SET_READ");
|
||||||
|
}
|
||||||
|
if (hawkbitClient.hasTargetRead()) {
|
||||||
|
roles.add("TARGET_READ");
|
||||||
|
}
|
||||||
|
if (hawkbitClient.hasConfigRead()) {
|
||||||
|
roles.add("CONFIG_READ");
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
SecurityContextHolder.setContext(currentContext);
|
||||||
|
}
|
||||||
|
return roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).toList();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.simple.security;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
|
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
|
||||||
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||||
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
||||||
|
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||||
|
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||||
|
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||||
|
import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
|
||||||
|
import org.springframework.security.oauth2.client.endpoint.RestClientRefreshTokenTokenResponseClient;
|
||||||
|
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||||
|
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||||
|
import org.springframework.security.oauth2.core.OAuth2RefreshToken;
|
||||||
|
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||||
|
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@ConditionalOnBean(name = "hawkbitOAuth2ClientCustomizer")
|
||||||
|
public class OAuth2TokenManager {
|
||||||
|
|
||||||
|
private final OAuth2AuthorizedClientService clientService;
|
||||||
|
private final OAuth2AuthorizedClientManager clientManager;
|
||||||
|
private final OAuth2AccessTokenResponseClient<OAuth2RefreshTokenGrantRequest> tokenResponseClient;
|
||||||
|
|
||||||
|
OAuth2TokenManager(
|
||||||
|
final OAuth2AuthorizedClientService clientService,
|
||||||
|
final OAuth2AuthorizedClientManager clientManager
|
||||||
|
) {
|
||||||
|
this.clientService = clientService;
|
||||||
|
this.clientManager = clientManager;
|
||||||
|
this.tokenResponseClient = new RestClientRefreshTokenTokenResponseClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken(final OAuth2AuthenticationToken authentication) {
|
||||||
|
return Optional.ofNullable(authorizedToken(authentication)).orElse(
|
||||||
|
((DefaultOidcUser) authentication.getPrincipal()).getIdToken().getTokenValue()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to refresh the id token if it is expired and adds it to the request.
|
||||||
|
*/
|
||||||
|
private String authorizedToken(final OAuth2AuthenticationToken authentication) {
|
||||||
|
String registrationId = authentication.getAuthorizedClientRegistrationId();
|
||||||
|
OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest.withClientRegistrationId(registrationId).principal(authentication).build();
|
||||||
|
|
||||||
|
// This ensures that there is a client already, otherwise we won't be able to call the manager for authorization
|
||||||
|
OAuth2AuthorizedClient authorizedClient = clientService.loadAuthorizedClient(registrationId, authentication.getName());
|
||||||
|
if (authorizedClient == null) return null;
|
||||||
|
|
||||||
|
// Will ensure that the token is refreshed if needed; do not rely on it being not null as it won't be available
|
||||||
|
// during the first calls made to get the rights and generate the authorities
|
||||||
|
OAuth2AuthorizedClient refreshClient = clientManager.authorize(request);
|
||||||
|
if (refreshClient == null) return null;
|
||||||
|
|
||||||
|
// A small trick to refresh the token if it is expired; the current spring version does not refresh the ID Token when the Access Token is refreshed
|
||||||
|
// This won't be necessary after Spring Security 6.5; cf. https://github.com/spring-projects/spring-security/pull/16589
|
||||||
|
OAuth2AccessToken accessToken = refreshClient.getAccessToken();
|
||||||
|
OAuth2RefreshToken refreshToken = refreshClient.getRefreshToken();
|
||||||
|
ClientRegistration clientRegistration = refreshClient.getClientRegistration();
|
||||||
|
// if this is null, please request it via the scopes
|
||||||
|
if (refreshToken == null) return null;
|
||||||
|
|
||||||
|
OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest(
|
||||||
|
clientRegistration, accessToken, refreshToken);
|
||||||
|
OAuth2AccessTokenResponse response = tokenResponseClient.getTokenResponse(refreshTokenGrantRequest);
|
||||||
|
return (String) response.getAdditionalParameters().get("id_token");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2023 Contributors to the Eclipse Foundation
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.simple.security;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class Oauth2ClientConfig {
|
||||||
|
@Bean(name = "hawkbitOAuth2ClientCustomizer")
|
||||||
|
@ConditionalOnProperty(prefix = "hawkbit.server.security.oauth2.client", name = "enabled")
|
||||||
|
@ConditionalOnMissingBean(name = "hawkbitOAuth2ClientCustomizer")
|
||||||
|
Customizer<OAuth2LoginConfigurer<HttpSecurity>> defaultOAuth2ClientCustomizer() {
|
||||||
|
return Customizer.withDefaults();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||||
|
*
|
||||||
|
* This program and the accompanying materials are made
|
||||||
|
* available under the terms of the Eclipse Public License 2.0
|
||||||
|
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: EPL-2.0
|
||||||
|
*/
|
||||||
|
package org.eclipse.hawkbit.ui.simple.security;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.ToString;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ToString
|
||||||
|
@ConfigurationProperties("hawkbit.server.security")
|
||||||
|
public class OidcClientProperties {
|
||||||
|
|
||||||
|
private final OidcClientProperties.Oauth2 oauth2 = new OidcClientProperties.Oauth2();
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Oauth2 {
|
||||||
|
|
||||||
|
private final OidcClientProperties.Oauth2.Client client = new OidcClientProperties.Oauth2.Client();
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public static class Client {
|
||||||
|
|
||||||
|
private boolean enabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,18 +11,33 @@ package org.eclipse.hawkbit.ui.simple.security;
|
|||||||
|
|
||||||
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
import com.vaadin.flow.spring.security.VaadinWebSecurity;
|
||||||
import org.eclipse.hawkbit.ui.simple.view.LoginView;
|
import org.eclipse.hawkbit.ui.simple.view.LoginView;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
|
||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({ OidcClientProperties.class })
|
||||||
public class SecurityConfiguration extends VaadinWebSecurity {
|
public class SecurityConfiguration extends VaadinWebSecurity {
|
||||||
|
|
||||||
|
private Customizer<OAuth2LoginConfigurer<HttpSecurity>> oAuth2LoginConfigurerCustomizer;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
public void setOAuth2LoginConfigurerCustomizer(
|
||||||
|
@Qualifier("hawkbitOAuth2ClientCustomizer") final Customizer<OAuth2LoginConfigurer<HttpSecurity>> oauth2LoginConfigurerCustomizer
|
||||||
|
) {
|
||||||
|
this.oAuth2LoginConfigurerCustomizer = oauth2LoginConfigurerCustomizer;
|
||||||
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
return new BCryptPasswordEncoder();
|
return new BCryptPasswordEncoder();
|
||||||
@@ -34,6 +49,11 @@ public class SecurityConfiguration extends VaadinWebSecurity {
|
|||||||
authorize -> authorize.requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll());
|
authorize -> authorize.requestMatchers(new AntPathRequestMatcher("/images/*.png")).permitAll());
|
||||||
|
|
||||||
super.configure(http);
|
super.configure(http);
|
||||||
setLoginView(http, LoginView.class);
|
|
||||||
|
if (oAuth2LoginConfigurerCustomizer != null) {
|
||||||
|
http.oauth2Login(oAuth2LoginConfigurerCustomizer);
|
||||||
|
} else {
|
||||||
|
setLoginView(http, LoginView.class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user