diff --git a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java index d706c83256..7bc3dd56a2 100644 --- a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java +++ b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/SimpleUIApp.java @@ -58,8 +58,8 @@ public class SimpleUIApp implements AppShellConfigurator { private static final Function AUTHORIZATION = oAuth2TokenManager -> requestTemplate -> { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - if (oAuth2TokenManager != null && authentication instanceof OAuth2AuthenticationToken oAuth2AuthenticationToken) { - String bearerToken = oAuth2TokenManager.getToken(oAuth2AuthenticationToken); + if (authentication instanceof OAuth2AuthenticationToken authenticationToken) { + String bearerToken = oAuth2TokenManager.getToken(authenticationToken); requestTemplate.header("Authorization", "Bearer " + bearerToken); } else { requestTemplate.header( @@ -108,16 +108,14 @@ HawkbitMgmtClient hawkbitMgmtClient(final Tenant tenant, final HawkbitClient haw @Bean OAuth2UserService oidcUserService(final HawkbitMgmtClient hawkbitClient) { final OidcUserService delegate = new OidcUserService(); - return userRequest -> { + return (userRequest) -> { OidcUser oidcUser = delegate.loadUser(userRequest); - final OAuth2AuthenticationToken tempToken = new OAuth2AuthenticationToken( oidcUser, emptyList(), userRequest.getClientRegistration().getRegistrationId() ); - final List grantedAuthorities = - getGrantedAuthorities(hawkbitClient, tempToken); + final List grantedAuthorities = getGrantedAuthorities(hawkbitClient, tempToken); return new DefaultOidcUser( grantedAuthorities, oidcUser.getIdToken(), diff --git a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/OAuth2TokenManager.java b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/OAuth2TokenManager.java index d4d00f221d..96017133fe 100644 --- a/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/OAuth2TokenManager.java +++ b/hawkbit-simple-ui/src/main/java/org/eclipse/hawkbit/ui/simple/security/OAuth2TokenManager.java @@ -10,30 +10,22 @@ package org.eclipse.hawkbit.ui.simple.security; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; 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 @ConditionalOnProperty(prefix = "hawkbit.server.security.oauth2.client", name = "enabled") public class OAuth2TokenManager { private final OAuth2AuthorizedClientService clientService; private final OAuth2AuthorizedClientManager clientManager; - private final OAuth2AccessTokenResponseClient tokenResponseClient; OAuth2TokenManager( final OAuth2AuthorizedClientService clientService, @@ -41,42 +33,25 @@ public class OAuth2TokenManager { ) { 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) { + final String currentToken = ((DefaultOidcUser) authentication.getPrincipal()).getIdToken().getTokenValue(); 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; + if (authorizedClient == null) return currentToken; // 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; + OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest.withClientRegistrationId(registrationId).principal(authentication).build(); + // since Spring Security 6.5 this will trigger a refresh of the id token + authorizedClient = clientManager.authorize(request); + if (authorizedClient == null) return currentToken; - OAuth2RefreshTokenGrantRequest refreshTokenGrantRequest = new OAuth2RefreshTokenGrantRequest( - clientRegistration, accessToken, refreshToken); - OAuth2AccessTokenResponse response = tokenResponseClient.getTokenResponse(refreshTokenGrantRequest); - return (String) response.getAdditionalParameters().get("id_token"); + // we need to fetch the newly created context containing the matching token + SecurityContext securityContext = SecurityContextHolder.getContext(); + return ((DefaultOidcUser) securityContext.getAuthentication().getPrincipal()).getIdToken().getTokenValue(); } }