Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OAuth 미션 2단계 리뷰 요청 드립니다. #14

Open
wants to merge 17 commits into
base: parkseryu
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 86 additions & 26 deletions src/main/java/nextstep/app/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package nextstep.app;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import nextstep.app.domain.Member;
import nextstep.app.domain.MemberRepository;
import nextstep.app.infrastructure.InmemoryMemberRepository;
Expand All @@ -9,19 +14,36 @@
import nextstep.security.access.hierarchicalroles.RoleHierarchy;
import nextstep.security.access.hierarchicalroles.RoleHierarchyImpl;
import nextstep.security.authentication.AuthenticationException;
import nextstep.security.authentication.AuthenticationManager;
import nextstep.security.authentication.BasicAuthenticationFilter;
import nextstep.security.authentication.OAuth2AccessTokenClient;
import nextstep.security.authentication.OAuth2AuthenticationFilter;
import nextstep.security.authentication.DaoAuthenticationProvider;
import nextstep.security.authentication.OAuth2ClientProperties;
import nextstep.security.authentication.OAuth2LoginRedirectFilter;
import nextstep.security.authentication.OAuth2UserInfoClient;
import nextstep.security.authentication.OAuth2ClientProperties.Provider;
import nextstep.security.authentication.OAuth2ClientProperties.Registration;
import nextstep.security.authentication.ProviderManager;
import nextstep.security.authentication.UsernamePasswordAuthenticationFilter;
import nextstep.security.authorization.*;
import nextstep.security.authorization.AuthorityAuthorizationManager;
import nextstep.security.authorization.AuthorizationFilter;
import nextstep.security.authorization.AuthorizationManager;
import nextstep.security.authorization.PermitAllAuthorizationManager;
import nextstep.security.authorization.RequestAuthorizationManager;
import nextstep.security.authorization.SecuredMethodInterceptor;
import nextstep.security.config.DefaultSecurityFilterChain;
import nextstep.security.config.DelegatingFilterProxy;
import nextstep.security.config.FilterChainProxy;
import nextstep.security.config.SecurityFilterChain;
import nextstep.security.context.SecurityContextHolderFilter;
import nextstep.security.oauth2.client.AuthorizationRequestRepository;
import nextstep.security.oauth2.client.HttpSessionOAuth2AuthorizationRequestRepository;
import nextstep.security.oauth2.client.OAuth2AuthorizationRequestRedirectFilter;
import nextstep.security.oauth2.client.authentication.OAuth2LoginAuthenticationProvider;
import nextstep.security.oauth2.client.registration.ClientRegistration;
import nextstep.security.oauth2.client.registration.ClientRegistrationRepository;
import nextstep.security.oauth2.client.registration.ClientRegistrationRepository.InMemoryClientRegistrationRepository;
import nextstep.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import nextstep.security.oauth2.client.userinfo.OAuth2UserService;
import nextstep.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository;
import nextstep.security.oauth2.client.web.OAuth2LoginAuthenticationFilter;
import nextstep.security.userdetails.UserDetails;
import nextstep.security.userdetails.UserDetailsService;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
Expand All @@ -30,34 +52,22 @@
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.http.HttpMethod;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

@Configuration
@EnableAspectJAutoProxy
@EnableConfigurationProperties(OAuth2ClientProperties.class)
public class SecurityConfig {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

자고로 state는 구현하지 않았는데요
역할은 CSRF 공격을 방지하고, 인증 후 클라이언트의 상태를 유지하는 역할을 한다고 이해했는데, 맞을까요?

state는 CSRF 공격을 방지하는 것이 맞지만 로그인 상태를 유지하는 역할은 하고 있지 않습니다! 로그인 상태를 유지하는 역할은 토큰의 역할이라고 보시면 됩니다 ㅎㅎ


private final MemberRepository memberRepository;
private final OAuth2ClientProperties oAuth2ClientProperties;
private final MemberRepository memberRepository;
private final OAuth2UserService oAuth2UserService;
private final OAuth2ClientProperties oAuth2ClientProperties;

public SecurityConfig(MemberRepository memberRepository,
OAuth2ClientProperties oAuth2ClientProperties) {
this.memberRepository = memberRepository;
this.oAuth2UserService = new DefaultOAuth2UserService(memberRepository);
this.oAuth2ClientProperties = oAuth2ClientProperties;
}

@Bean
public OAuth2AccessTokenClient oAuth2AccessTokenClient() {
return new OAuth2AccessTokenClient();
}

@Bean
public OAuth2UserInfoClient oAuth2UserInfoClient() {
return new OAuth2UserInfoClient();
}

@Bean
public MemberRepository memberRepository() {
return new InmemoryMemberRepository();
Expand All @@ -73,20 +83,39 @@ public FilterChainProxy filterChainProxy(List<SecurityFilterChain> securityFilte
return new FilterChainProxy(securityFilterChains);
}

@Bean
public ClientRegistrationRepository clientRegistrationRepository() {
Map<String, ClientRegistration> registrations = getClientRegistrations(oAuth2ClientProperties);
return new InMemoryClientRegistrationRepository(registrations);
}

@Bean
public SecuredMethodInterceptor securedMethodInterceptor() {
return new SecuredMethodInterceptor();
}

@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(List.of(
new DaoAuthenticationProvider(userDetailsService()),
new OAuth2LoginAuthenticationProvider(oAuth2UserService)));
}

@Bean
public AuthorizationRequestRepository authorizationRequestRepository() {
return new HttpSessionOAuth2AuthorizationRequestRepository();
}

@Bean
public SecurityFilterChain securityFilterChain() {
return new DefaultSecurityFilterChain(
List.of(
new SecurityContextHolderFilter(),
new UsernamePasswordAuthenticationFilter(userDetailsService()),
new BasicAuthenticationFilter(userDetailsService()),
new OAuth2LoginRedirectFilter(oAuth2ClientProperties),
new OAuth2AuthenticationFilter(oAuth2ClientProperties, memberRepository, oAuth2AccessTokenClient(), oAuth2UserInfoClient()),
new OAuth2AuthorizationRequestRedirectFilter(clientRegistrationRepository(), authorizationRequestRepository()),
new OAuth2LoginAuthenticationFilter(clientRegistrationRepository(),
new HttpSessionOAuth2AuthorizedClientRepository(), authenticationManager()),
new AuthorizationFilter(requestAuthorizationManager())
)
);
Expand All @@ -102,9 +131,12 @@ public RoleHierarchy roleHierarchy() {
@Bean
public RequestAuthorizationManager requestAuthorizationManager() {
List<RequestMatcherEntry<AuthorizationManager>> mappings = new ArrayList<>();
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/members"), new AuthorityAuthorizationManager(roleHierarchy(), "ADMIN")));
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/members/me"), new AuthorityAuthorizationManager(roleHierarchy(), "USER")));
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/search"), new PermitAllAuthorizationManager()));
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/members"),
new AuthorityAuthorizationManager(roleHierarchy(), "ADMIN")));
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/members/me"),
new AuthorityAuthorizationManager(roleHierarchy(), "USER")));
mappings.add(new RequestMatcherEntry<>(new MvcRequestMatcher(HttpMethod.GET, "/search"),
new PermitAllAuthorizationManager()));
mappings.add(new RequestMatcherEntry<>(AnyRequestMatcher.INSTANCE, new PermitAllAuthorizationManager()));
return new RequestAuthorizationManager(mappings);
}
Expand Down Expand Up @@ -133,4 +165,32 @@ public Set<String> getAuthorities() {
};
};
}

private Map<String, ClientRegistration> getClientRegistrations(OAuth2ClientProperties oAuth2ClientProperties) {
return oAuth2ClientProperties.getRegistrations().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getKey,
entry -> toClientRegistration(entry.getKey(), entry.getValue())));
}

private ClientRegistration toClientRegistration(String registrationId,
Registration registration) {
Provider provider = oAuth2ClientProperties.getProviders().get(registration.provider());
return new ClientRegistration(
registrationId,
registration.clientId(),
registration.clientSecret(),
registration.redirectUri(),
Set.copyOf(registration.scope()),
registration.authorizationGrantType(),
provider.name(),
new ClientRegistration.ProviderDetails(
provider.authorizationUri(),
provider.tokenUri(),
new ClientRegistration.UserInfoEndpoint(
provider.userInfoUri(),
provider.userNameAttributeName()
)
)
);
}
}
11 changes: 6 additions & 5 deletions src/main/java/nextstep/app/ui/LoginController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.servlet.http.HttpSession;
import nextstep.security.authentication.Authentication;
import nextstep.security.context.SecurityContextHolder;
import nextstep.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -32,10 +33,10 @@ private String extractUsername(Authentication authentication) {
if (authentication.getPrincipal() instanceof String) {
return (String) authentication.getPrincipal();
}
// if (authentication.getPrincipal() instanceof OAuth2User) {
// String userNameAttributeName = ((OAuth2User) authentication.getPrincipal()).getUserNameAttributeName();
// return (String) ((OAuth2User) authentication.getPrincipal()).getAttributes().get(userNameAttributeName);
// }
if (authentication.getPrincipal() instanceof OAuth2User) {
String userNameAttributeName = ((OAuth2User) authentication.getPrincipal()).getUserNameAttributeName();
return (String) ((OAuth2User) authentication.getPrincipal()).getAttributes().get(userNameAttributeName);
}
return "";
}

Expand All @@ -54,4 +55,4 @@ public String logout(HttpServletRequest request, HttpServletResponse response) {

return "redirect:/";
}
}
}
36 changes: 0 additions & 36 deletions src/main/java/nextstep/security/authentication/GitHubUserInfo.java

This file was deleted.

35 changes: 0 additions & 35 deletions src/main/java/nextstep/security/authentication/GoogleUserInfo.java

This file was deleted.

This file was deleted.

Loading