diff --git a/server/pom.xml b/server/pom.xml
index 465200d..e360256 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -126,6 +126,40 @@
+
+ org.openapitools
+ openapi-generator-maven-plugin
+ 6.3.0
+
+
+
+ generate
+
+
+ ${project.basedir}/src/main/resources/withings.yaml
+ java
+
+ src/gen/java/main
+ java8
+ true
+ true
+ true
+ native
+ true
+ false
+ @lombok.Builder @lombok.AllArgsConstructor
+
+ false
+ false
+ false
+ false
+ false
+ false
+ mucsi96.traininglog.withings
+
+
+
+
diff --git a/server/src/main/java/mucsi96/traininglog/withings/WithingsConfiguration.java b/server/src/main/java/mucsi96/traininglog/withings/WithingsConfiguration.java
index 907e58c..135ebb9 100644
--- a/server/src/main/java/mucsi96/traininglog/withings/WithingsConfiguration.java
+++ b/server/src/main/java/mucsi96/traininglog/withings/WithingsConfiguration.java
@@ -1,16 +1,163 @@
package mucsi96.traininglog.withings;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Set;
+
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.http.converter.FormHttpMessageConverter;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
+import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient;
+import org.springframework.security.oauth2.client.endpoint.DefaultRefreshTokenTokenResponseClient;
+import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
+import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
+import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequestEntityConverter;
+import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequest;
+import org.springframework.security.oauth2.client.endpoint.OAuth2RefreshTokenGrantRequestEntityConverter;
+import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
+import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
+import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
+import org.springframework.security.oauth2.core.OAuth2AccessToken;
+import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
+import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
+import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.RestTemplate;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.github.mucsi96.kubetools.security.KubetoolsSecurityConfigurer;
import lombok.Data;
@Data
@Configuration
@ConfigurationProperties(prefix = "withings")
public class WithingsConfiguration {
+ public static final String registrationId = "withings-client";
+
private WithingsApiConfiguration api;
+ @Bean
+ SecurityFilterChain withingsSecurityFilterChain(
+ HttpSecurity http,
+ KubetoolsSecurityConfigurer kubetoolsSecurityConfigurer) throws Exception {
+ return kubetoolsSecurityConfigurer.configure(http)
+ .securityMatcher("/withings/**")
+ .oauth2Client(configurer -> configurer
+ .authorizationCodeGrant(customizer -> customizer
+ .accessTokenResponseClient(withingsAccessTokenResponseClient())))
+ .build();
+ }
+
+ @Bean
+ OAuth2AuthorizedClientManager withingsAuthorizedClientManager(
+ ClientRegistrationRepository clientRegistrationRepository,
+ OAuth2AuthorizedClientRepository authorizedClientRepository) {
+
+ DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
+ clientRegistrationRepository, authorizedClientRepository);
+
+ OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
+ .authorizationCode()
+ .refreshToken(configurer -> configurer.accessTokenResponseClient(withingsRefreshTokenResponseClient()))
+ .build();
+
+ authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
+
+ return authorizedClientManager;
+ }
+
+ OAuth2AccessTokenResponseClient withingsAccessTokenResponseClient() {
+ OAuth2AuthorizationCodeGrantRequestEntityConverter requestEntityConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter();
+ requestEntityConverter.addParametersConverter(withingsAccessTokenRequestParametersConverter());
+
+ OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
+ accessTokenResponseConverter.setAccessTokenResponseConverter(withingsAccessTokenResponseConverter());
+
+ RestTemplate restTemplate = new RestTemplate(Arrays.asList(
+ new FormHttpMessageConverter(),
+ accessTokenResponseConverter));
+
+ restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
+
+ DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
+ accessTokenResponseClient.setRequestEntityConverter(requestEntityConverter);
+ accessTokenResponseClient.setRestOperations(restTemplate);
+ return accessTokenResponseClient;
+ }
+
+ OAuth2AccessTokenResponseClient withingsRefreshTokenResponseClient() {
+ OAuth2RefreshTokenGrantRequestEntityConverter requestEntityConverter = new OAuth2RefreshTokenGrantRequestEntityConverter();
+ requestEntityConverter.addParametersConverter(withingsRefreshTokenRequestParametersConverter());
+
+ OAuth2AccessTokenResponseHttpMessageConverter accessTokenResponseConverter = new OAuth2AccessTokenResponseHttpMessageConverter();
+ accessTokenResponseConverter.setAccessTokenResponseConverter(withingsAccessTokenResponseConverter());
+
+ RestTemplate restTemplate = new RestTemplate(Arrays.asList(
+ new FormHttpMessageConverter(),
+ accessTokenResponseConverter));
+
+ restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
+
+ DefaultRefreshTokenTokenResponseClient tokenResponseClient = new DefaultRefreshTokenTokenResponseClient();
+ tokenResponseClient.setRequestEntityConverter(requestEntityConverter);
+ tokenResponseClient.setRestOperations(restTemplate);
+ return tokenResponseClient;
+ }
+
+ Converter> withingsAccessTokenRequestParametersConverter() {
+ return request -> {
+ MultiValueMap parameters = new LinkedMultiValueMap<>();
+ parameters.add("action", "requesttoken");
+ parameters.add(OAuth2ParameterNames.CLIENT_ID, request.getClientRegistration().getClientId());
+ parameters.add(OAuth2ParameterNames.CLIENT_SECRET, request.getClientRegistration().getClientSecret());
+ return parameters;
+ };
+ }
+
+ Converter