From 539bdb7f3157b45926df9d97ee332171f391bc80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krystian=20Kie=C5=82basa?= Date: Mon, 18 Nov 2024 15:26:57 +0100 Subject: [PATCH] fix: #185 simplification of authorization --- .../configuration/WebConfiguration.java | 30 +++++++++++------ .../module/oauth2/OAuth2ProviderService.java | 2 +- .../module/oauth2/OAuth2Service.java | 12 +++---- .../OAuth2Processor.java} | 19 +++++------ .../OAuth2ProcessorResult.java} | 4 +-- .../OAuth2Provider.java | 4 +-- .../github/GithubOAuth2Processor.java} | 31 ++++-------------- .../github/GithubOAuth2ProcessorResult.java} | 8 ++--- .../github/GithubOAuth2Provider.java | 32 +++++++++++++++++++ .../oauth2/util/OAuth2RestTemplate.java | 1 - .../infrastructure/store/UserStore.java | 16 +++++----- 11 files changed, 92 insertions(+), 67 deletions(-) rename kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/{provider/OAuth2ProviderSuperclass.java => processor/OAuth2Processor.java} (51%) rename kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/{provider/OAuth2ProviderResult.java => processor/OAuth2ProcessorResult.java} (76%) rename kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/{provider => processor}/OAuth2Provider.java (58%) rename kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/{provider/github/GithubOAuth2Provider.java => processor/github/GithubOAuth2Processor.java} (57%) rename kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/{provider/github/GithubOAuth2ProviderResult.java => processor/github/GithubOAuth2ProcessorResult.java} (65%) create mode 100644 kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Provider.java diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/configuration/WebConfiguration.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/configuration/WebConfiguration.java index fdd0b109..2f562107 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/configuration/WebConfiguration.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/configuration/WebConfiguration.java @@ -1,18 +1,13 @@ package pl.sknikod.kodemyauth.configuration; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; -import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.BufferingClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; -import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; import org.zalando.logbook.spring.LogbookClientHttpRequestInterceptor; import pl.sknikod.kodemyauth.infrastructure.module.oauth2.util.OAuth2RestTemplate; @@ -22,16 +17,31 @@ @Configuration @Slf4j public class WebConfiguration { + + @Bean + public BufferingClientHttpRequestFactory bufferingClientHttpRequestFactory() { + var requestFactory = new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build()); + return new BufferingClientHttpRequestFactory(requestFactory); + } + @Bean @LoadBalanced public RestTemplate restTemplate( - RestTemplateBuilder restTemplateBuilder, LogbookClientHttpRequestInterceptor logbookInterceptor + RestTemplateBuilder restTemplateBuilder, + LogbookClientHttpRequestInterceptor logbookInterceptor ) { - restTemplateBuilder.requestFactory(() -> { - var requestFactory = new HttpComponentsClientHttpRequestFactory(HttpClientBuilder.create().build()); - return new BufferingClientHttpRequestFactory(requestFactory); - }); + restTemplateBuilder.requestFactory(this::bufferingClientHttpRequestFactory); restTemplateBuilder.additionalInterceptors(Collections.singletonList(logbookInterceptor)); return restTemplateBuilder.build(); } + + @Bean + public OAuth2RestTemplate oAuth2RestTemplate( + RestTemplateBuilder restTemplateBuilder, + LogbookClientHttpRequestInterceptor logbookInterceptor + ) { + restTemplateBuilder.requestFactory(this::bufferingClientHttpRequestFactory); + restTemplateBuilder.additionalInterceptors(Collections.singletonList(logbookInterceptor)); + return new OAuth2RestTemplate(restTemplateBuilder.build()); + } } diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2ProviderService.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2ProviderService.java index 03da10a6..c2a1b75b 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2ProviderService.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2ProviderService.java @@ -2,7 +2,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2Provider; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2Provider; import java.util.List; diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2Service.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2Service.java index 3a5dbf10..5fd8a0f6 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2Service.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/OAuth2Service.java @@ -15,8 +15,8 @@ import pl.sknikod.kodemyauth.infrastructure.database.Role; import pl.sknikod.kodemyauth.infrastructure.database.RoleRepository; import pl.sknikod.kodemyauth.infrastructure.database.User; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2Provider; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2ProviderResult; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2Provider; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2ProcessorResult; import pl.sknikod.kodemyauth.infrastructure.module.oauth2.util.OAuth2UserPrincipal; import pl.sknikod.kodemyauth.infrastructure.store.UserStore; @@ -38,7 +38,7 @@ public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2Authentic .orElse(null); } - private Optional retrieveUser(OAuth2UserRequest userRequest, Iterator iterator) { + private Optional retrieveUser(OAuth2UserRequest userRequest, Iterator iterator) { if (!iterator.hasNext()) { log.info("No processable provider for registration ID: {}", userRequest.getClientRegistration().getRegistrationId()); return Optional.empty(); @@ -51,17 +51,17 @@ private Optional retrieveUser(OAuth2UserRequest userReques return retrieveUser(userRequest, iterator); // check another one } - private Tuple2 createOrLoadUser(OAuth2ProviderResult providerUser) { + private Tuple2 createOrLoadUser(OAuth2ProcessorResult providerUser) { return userStore.findByProviderUser(providerUser) .fold(unused -> Tuple.of(this.createNewUser(providerUser), providerUser), user -> Tuple.of(user, providerUser)); } - private User createNewUser(OAuth2ProviderResult providerUser) { + private User createNewUser(OAuth2ProcessorResult providerUser) { return userStore.save(providerUser) .orElse(null); } - private OAuth2UserPrincipal toUserPrincipal(Tuple2 userTuple2) { + private OAuth2UserPrincipal toUserPrincipal(Tuple2 userTuple2) { return Try.of(() -> roleRepository.findById(userTuple2._1.getRole().getId())) .filter(Optional::isPresent) .map(Optional::get) diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2ProviderSuperclass.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2Processor.java similarity index 51% rename from kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2ProviderSuperclass.java rename to kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2Processor.java index 7948f031..48d66fed 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2ProviderSuperclass.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2Processor.java @@ -1,4 +1,4 @@ -package pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider; +package pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor; import io.vavr.control.Try; import lombok.NonNull; @@ -12,18 +12,19 @@ @RequiredArgsConstructor @Slf4j -public abstract class OAuth2ProviderSuperclass { +public abstract class OAuth2Processor { protected final OAuth2RestTemplate oAuth2RestTemplate; private final Map attributes = new HashMap<>(); - private boolean isInitialized = false; + + public abstract OAuth2ProcessorResult process(OAuth2UserRequest userRequest); protected Map getAttributes(@NonNull OAuth2UserRequest userRequest) { - if (!isInitialized) { - Try.of(() -> this.oAuth2RestTemplate.exchange(userRequest).getBody()) - .onSuccess(attrs -> log.info("Successfully retrieved {} user attributes", attrs.size())) - .peek(this.attributes::putAll); - this.isInitialized = true; - } + Try.of(() -> this.oAuth2RestTemplate.exchange(userRequest).getBody()) + .onSuccess(attrs -> log.info("Successfully retrieved {} user attributes", attrs.size())) + .peek(m -> { + this.attributes.put("registration_id", userRequest.getClientRegistration().getRegistrationId()); + this.attributes.putAll(m); + }); return attributes; } } diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2ProviderResult.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2ProcessorResult.java similarity index 76% rename from kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2ProviderResult.java rename to kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2ProcessorResult.java index 149f81ae..0b78f220 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2ProviderResult.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2ProcessorResult.java @@ -1,4 +1,4 @@ -package pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider; +package pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor; import lombok.AllArgsConstructor; import lombok.Getter; @@ -7,7 +7,7 @@ @Getter @AllArgsConstructor -public abstract class OAuth2ProviderResult { +public abstract class OAuth2ProcessorResult { protected final Map attributes; public abstract String getRegistrationId(); diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2Provider.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2Provider.java similarity index 58% rename from kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2Provider.java rename to kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2Provider.java index 69364087..7c735979 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/OAuth2Provider.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/OAuth2Provider.java @@ -1,9 +1,9 @@ -package pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider; +package pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; public interface OAuth2Provider { String getRegistrationId(); boolean isApply(String registrationId); - OAuth2ProviderResult retrieve(OAuth2UserRequest userRequest); + OAuth2ProcessorResult retrieve(OAuth2UserRequest userRequest); } diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/github/GithubOAuth2Provider.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Processor.java similarity index 57% rename from kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/github/GithubOAuth2Provider.java rename to kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Processor.java index 8523fda5..80e859e6 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/github/GithubOAuth2Provider.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Processor.java @@ -1,45 +1,28 @@ -package pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.github; +package pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.github; import io.vavr.control.Try; import lombok.Data; -import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.springframework.core.ParameterizedTypeReference; import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; -import org.springframework.stereotype.Component; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2Provider; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2ProviderResult; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2ProviderSuperclass; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2Processor; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2ProcessorResult; import pl.sknikod.kodemyauth.infrastructure.module.oauth2.util.OAuth2RestTemplate; import java.util.List; import java.util.Map; -@Component @Slf4j -public class GithubOAuth2Provider extends OAuth2ProviderSuperclass implements OAuth2Provider { - private static final String REGISTRATION_ID = "github"; - - public GithubOAuth2Provider(OAuth2RestTemplate oAuth2RestTemplate) { +public class GithubOAuth2Processor extends OAuth2Processor { + public GithubOAuth2Processor(OAuth2RestTemplate oAuth2RestTemplate) { super(oAuth2RestTemplate); } @Override - public String getRegistrationId() { - return REGISTRATION_ID; - } - - @Override - public boolean isApply(String registrationId) { - return getRegistrationId().equals(registrationId); - } - - @Override - public OAuth2ProviderResult retrieve(OAuth2UserRequest userRequest) { + public OAuth2ProcessorResult process(OAuth2UserRequest userRequest) { Map attributes = super.getAttributes(userRequest); - attributes.put("registrationId", REGISTRATION_ID); fixEmailNull(attributes, userRequest); - return new GithubOAuth2ProviderResult(attributes); + return new GithubOAuth2ProcessorResult(attributes); } private void fixEmailNull(Map attributes, OAuth2UserRequest userRequest) { diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/github/GithubOAuth2ProviderResult.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2ProcessorResult.java similarity index 65% rename from kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/github/GithubOAuth2ProviderResult.java rename to kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2ProcessorResult.java index b7315497..47d2cef0 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/provider/github/GithubOAuth2ProviderResult.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2ProcessorResult.java @@ -1,11 +1,11 @@ -package pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.github; +package pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.github; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2ProviderResult; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2ProcessorResult; import java.util.Map; -public class GithubOAuth2ProviderResult extends OAuth2ProviderResult { - public GithubOAuth2ProviderResult(Map attributes) { +public class GithubOAuth2ProcessorResult extends OAuth2ProcessorResult { + public GithubOAuth2ProcessorResult(Map attributes) { super(attributes); } diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Provider.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Provider.java new file mode 100644 index 00000000..507562f2 --- /dev/null +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/processor/github/GithubOAuth2Provider.java @@ -0,0 +1,32 @@ +package pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.github; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest; +import org.springframework.stereotype.Component; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2Provider; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2ProcessorResult; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.util.OAuth2RestTemplate; + +@Component +@Slf4j +@RequiredArgsConstructor +public class GithubOAuth2Provider implements OAuth2Provider { + private static final String REGISTRATION_ID = "github"; + private final OAuth2RestTemplate oAuth2RestTemplate; + + @Override + public String getRegistrationId() { + return REGISTRATION_ID; + } + + @Override + public boolean isApply(String registrationId) { + return getRegistrationId().equals(registrationId); + } + + @Override + public OAuth2ProcessorResult retrieve(OAuth2UserRequest userRequest) { + return new GithubOAuth2Processor(oAuth2RestTemplate).process(userRequest); + } +} diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/util/OAuth2RestTemplate.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/util/OAuth2RestTemplate.java index 1389daf6..56a867e9 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/util/OAuth2RestTemplate.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/module/oauth2/util/OAuth2RestTemplate.java @@ -13,7 +13,6 @@ import java.util.Collections; import java.util.Map; -@Component @RequiredArgsConstructor public class OAuth2RestTemplate { private final RestTemplate restTemplate; diff --git a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/store/UserStore.java b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/store/UserStore.java index ff1d7561..c2a451b1 100644 --- a/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/store/UserStore.java +++ b/kodemy-auth/src/main/java/pl/sknikod/kodemyauth/infrastructure/store/UserStore.java @@ -9,7 +9,7 @@ import org.springframework.stereotype.Component; import pl.sknikod.kodemyauth.configuration.SecurityConfiguration; import pl.sknikod.kodemyauth.infrastructure.database.*; -import pl.sknikod.kodemyauth.infrastructure.module.oauth2.provider.OAuth2ProviderResult; +import pl.sknikod.kodemyauth.infrastructure.module.oauth2.processor.OAuth2ProcessorResult; import pl.sknikod.kodemycommons.exception.InternalError500Exception; import pl.sknikod.kodemycommons.exception.NotFound404Exception; import pl.sknikod.kodemycommons.exception.content.ExceptionMsgPattern; @@ -26,15 +26,15 @@ public class UserStore { private final RoleRepository roleRepository; private final SecurityConfiguration.RoleProperties roleProperties; - public Optional save(OAuth2ProviderResult providerUser) { + public Optional save(OAuth2ProcessorResult result) { return this.fetchRole(roleProperties.getPrimary()) .map(role -> new User( - providerUser.getUsername(), providerUser.getEmail(), - providerUser.getPhoto(), role)) + result.getUsername(), result.getEmail(), + result.getPhoto(), role)) .map(user -> { var provider = new Provider( - providerUser.getPrincipalId(), providerUser.getRegistrationId(), - providerUser.getEmail(), providerUser.getPhoto(), user + result.getPrincipalId(), result.getRegistrationId(), + result.getEmail(), result.getPhoto(), user ); user.setProviders(Set.of(provider)); return user; @@ -52,9 +52,9 @@ private Try fetchRole(String roleName) { .onFailure(th -> log.error(th.getMessage())); } - public Try findByProviderUser(OAuth2ProviderResult providerUser) { + public Try findByProviderUser(OAuth2ProcessorResult result) { return Option.of(userRepository.findUserByPrincipalIdAndAuthProvider( - providerUser.getPrincipalId(), providerUser.getRegistrationId() + result.getPrincipalId(), result.getRegistrationId() )) .toTry(() -> new NotFound404Exception(ExceptionMsgPattern.ENTITY_NOT_FOUND, User.class)); }