Q1. 아직 나아가지 못하는 중이다. Provider확인에 있어서 실패를 하는 것 같다.
OAuth2AuthorizationRequestRedirectFilter까지 동작하고 JwtAuthenticationFilter2필터에서 AbstractAuthenticationProcessingFilter를 동작하는 부분에서 실패한다고 확인하였다.
Debugging하면서 문제를 찾아보았다.
// attemptAuthentication Method
...
OAuth2LoginAuthenticationToken authenticationResult = (OAuth2LoginAuthenticationToken)this.getAuthenticationManager().authenticate(authenticationRequest);
...
OAuth2LoginAuthenticationFilter중 위 Method에서 Authentication이 정상적으로 발생하지 않아 OAuth2LoginAuthenticationToken이 완성되지 못해 그런것으로 생각되었다.
Q2. providers를 추가?구분?하는 부분은 어디인가?
Debugging을 하면서 request부분에서도 계속 provider가 있는데도 식별이 안된다고 하여 좀 더 코드를 들여다보기로 했다.
그러고 조금 더 자세히 보니 ProviderManager에서 customOAuth2UserService를 사용함에 있어 Provider가 누락되어 있는것을 발견했다.
Q3. 무한 굴레에 빠져... 난 무엇을 놓치고 있는 것일까?
flowchart를 그리면서 되짚어 보았다.
이런 느낌인데....
개념을 잘못잡은 것일까?
전체 흐름
1. 인증 요청: 사용자가 애플리케이션에 로그인을 시도하면, 인증 요청이 생성됩니다. 이 요청은 보통 Authentication 객체로 표현됩니다.
2. AuthenticationManager: 이 요청은 AuthenticationManager로 전달됩니다. 대부분의 경우, ProviderManager가 이 역할을 수행합니다.
3. ProviderManager: ProviderManager는 등록된 여러 AuthenticationProvider를 순차적으로 호출하여 인증을 시도합니다. 각 AuthenticationProvider는 주어진 Authentication 객체를 사용하여 인증을 시도합니다.
4. AuthenticationProvider: 각 AuthenticationProvider는 자신이 지원하는 인증 방식을 통해 인증을 시도합니다. 성공하면 인증된 Authentication 객체를 반환하고, 실패하면 다음 AuthenticationProvider로 넘어갑니다.
5. 결과 반환: ProviderManager는 첫 번째로 인증에 성공한 AuthenticationProvider로부터 인증된 Authentication 객체를 받아 이를 클라이언트에게 반환합니다. 모든 AuthenticationProvider가 실패하면 예외를 던집니다.
ChatGpt는 이런 흐름으로 동작한다고 얘기한다.
Q3. 커스텀 provider를 불러와서 인증을 하는 것 까지 시켰는데도 결과는 동일했다.
무슨 작업을 추가로 해야할까?
➡️ 그 동안 문제가 되었던 부분은 일단 해결이 되었다.
이슈사항은 Oauth2로그인 시 Provider로 token전달이 되지 않아 No Provider에러가 발생했는데 그것은 token을 해결해 줄 provider를 authenticationManager가 지정해주지 못해 발생했던 것이다.
그래서 커스텀으로 authenticationManager를 주입해주고 oauth2토큰을 provider가 처리 해줄수있도록 가이드를 만들어주었다.
그동안 삽질한 부분은 두가지 인데 흐름을 정리하지 못하고 중복 코드를 덕지덕지 발랐던 것, 두번째는 Provider가 지정되도록 수정해서 동작하는데 일종의 mapping역할을 해주는 support메서드 오버라이드를 제대로 하지 않아서 그랬다.
이전 버전에서는 resolver를 이용해 간편하게 처리했었는데 이번에는 이런 방법으로 해보았다.
// WebSecurityConfig파일
@Override
protected void configure(HttpSecurity http) throws IOException {
try {
...
.oauth2Login()
.authorizationEndpoint()
.authorizationRequestResolver(customAuthorizationRequestResolver)
...
;
} catch (Throwable e) {
log.error("WebSecurityConfig/configure(HttpSecurity http) -ExceptionError!");
}
}
// RequestResolver파일
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import java.util.LinkedHashMap;
import java.util.Map;
@Component
public class CustomAuthorizationRequestResolver implements OAuth2AuthorizationRequestResolver {
private final OAuth2AuthorizationRequestResolver defaultAuthorizationRequestResolver;
public CustomAuthorizationRequestResolver(
ClientRegistrationRepository clientRegistrationRepository) {
this.defaultAuthorizationRequestResolver =
new DefaultOAuth2AuthorizationRequestResolver(
clientRegistrationRepository, "/oauth2/authorization");
}
@Override
public OAuth2AuthorizationRequest resolve(HttpServletRequest request) {
OAuth2AuthorizationRequest authorizationRequest =
this.defaultAuthorizationRequestResolver.resolve(request);
return authorizationRequest != null ?
customAuthorizationRequest(authorizationRequest) :
null;
}
@Override
public OAuth2AuthorizationRequest resolve(
HttpServletRequest request, String clientRegistrationId) {
OAuth2AuthorizationRequest authorizationRequest =
this.defaultAuthorizationRequestResolver.resolve(
request, clientRegistrationId);
return authorizationRequest != null ?
customAuthorizationRequest(authorizationRequest) :
null;
}
private OAuth2AuthorizationRequest customAuthorizationRequest(
OAuth2AuthorizationRequest authorizationRequest) {
Map<String, Object> additionalParameters =
new LinkedHashMap<>(authorizationRequest.getAdditionalParameters());
String registrationId = authorizationRequest.getAttribute("registration_id");
String prompt = "";
if(registrationId.equals("naver")) {
prompt = "login";
} else if (registrationId.equals("google")) {
prompt = "select_account";
}
additionalParameters.put("prompt", prompt);
return OAuth2AuthorizationRequest.from(authorizationRequest)
.additionalParameters(additionalParameters)
.build();
}
}
'Backend > Spring | SpringBoot' 카테고리의 다른 글
[OAuth2] 회고4 (0) | 2024.06.18 |
---|---|
[TIL] 회고 1 (0) | 2024.06.17 |
[Oauth2] 회고2 (0) | 2024.06.12 |
[Oauth2] 회고 1 (0) | 2024.06.11 |
[egovFramework] spring message이용 (0) | 2024.05.17 |