인프런 커뮤니티 질문&답변
작성자 없음
작성자 정보가 삭제된 글입니다.
client-credentials 방식 accessToken null 이슈
작성
·
202
·
수정됨
0
Cannot invoke "org.springframework.security.oauth2.client.OAuth2AuthorizedClient.getAccessToken()" because "oAuth2AuthorizedClient" is null] with root cause
keycloak 버전은 : 21.1.2
@GetMapping("/oauth2Login")
public String oauth2Login(Model model, HttpServletRequest request, HttpServletResponse response) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
OAuth2AuthorizeRequest oAuth2AuthorizeRequest = OAuth2AuthorizeRequest
.withClientRegistrationId("keycloak")
.principal(authentication)
.attribute(HttpServletRequest.class.getName(), request)
.attribute(HttpServletResponse.class.getName(), response)
.build();
OAuth2AuthorizationSuccessHandler successHandler = (authorizedClient, principal, attributes) -> {
oAuth2AuthorizedClientRepository
.saveAuthorizedClient(authorizedClient, principal,
(HttpServletRequest) attributes.get(HttpServletRequest.class.getName()),
(HttpServletResponse) attributes.get(HttpServletResponse.class.getName()));
System.out.println("authorizedClient : " + authorizedClient);
System.out.println("principal : " + principal);
System.out.println("attributes : " + attributes);
};
auth2AuthorizedClientManager.setAuthorizationSuccessHandler(successHandler);
OAuth2AuthorizedClient oAuth2AuthorizedClient = auth2AuthorizedClientManager.authorize(oAuth2AuthorizeRequest);
model.addAttribute("oAuth2AuthorizedClient", oAuth2AuthorizedClient.getAccessToken().getTokenValue());
return "home";
}
keycloak:
clientId: oauath2-client-app
clientSecret: HPWAsKr9dEy9DPU1babedRmpstowiXOs
clientName: oauath2-client-app
authorizationGrantType: client-credentials
clientAuthenticationMethod: client_secret_basic
provider: keycloak
<form sec:authorize="isAnonymous()" action="#">
<p><input type="button" onclick="authorizationCode()" value="AuthorizationCode Grant"/></p>
<p><div sec:authorize="isAnonymous()"><a th:href="@{/oauth2Login(username='user',password='1234')}">Password flow</a></div></p>
<div sec:authorize="isAnonymous()"><a th:href="@{/oauth2Login}">Client Credentials Flow Login</a></div>
</form>
@Configuration
public class AppConfig {
@Bean
public DefaultOAuth2AuthorizedClientManager auth2AuthorizedClientManager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository) {
OAuth2AuthorizedClientProvider oAuth2AuthorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.password()
.clientCredentials()
.refreshToken()
.build();
DefaultOAuth2AuthorizedClientManager defaultOAuth2AuthorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, oAuth2AuthorizedClientRepository);
defaultOAuth2AuthorizedClientManager.setAuthorizedClientProvider(oAuth2AuthorizedClientProvider);
defaultOAuth2AuthorizedClientManager.setContextAttributesMapper(contextAttributeManager());
return defaultOAuth2AuthorizedClientManager;
}
private Function<OAuth2AuthorizeRequest, Map<String, Object>> contextAttributeManager() {
return oAuth2AuthorizeRequest -> {
Map<String, Object> contextAttributes = new HashMap<>();
HttpServletRequest httpServletRequest = oAuth2AuthorizeRequest.getAttribute(HttpServletRequest.class.getName());
String userName = httpServletRequest.getParameter(OAuth2ParameterNames.USERNAME);
String userPassword = httpServletRequest.getParameter(OAuth2ParameterNames.PASSWORD);
if(StringUtils.hasText(userName) && StringUtils.hasText(userPassword)) {
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, userName);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, userPassword);
}
return contextAttributes;
};
}
}
이렇게 됩니다. 현재 상황으로 문제가 되어 있는 부분이 없는 것 같습니다.
어디부터 다시 확인해야 될지 조언 부탁드립니다.
답변 1
0
안녕하세요, 인프런 AI 인턴입니다.
JUNI님의 코드와 설정을 검토해 본 결과, client-credentials 방식과 관련하여 문제를 겪고 계신 것으로 보입니다. client-credentials 그랜트 타입은 클라이언트가 서버에 직접 인증하는 상황에 사용되며, 일반적으로 사용자와 관련된 권한이 아닌 클라이언트 자체의 권한에 대해 적용됩니다. 하지만 주신 코드는 사용자 인증을 기반으로 하는 코드로 보입니다.
client-credentials 방식으로 액세스 토큰을 얻으려면, 먼저 OAuth2AuthorizedClientManager나 OAuth2AuthorizedClientProvider에서 client-credentials 방식을 지원하도록 설정되어 있어야 합니다. 또한, 사용자 인증 과정이 아니므로 Authentication 객체 없이 클라이언트 인증 정보만으로 액세스 토큰을 요청해야 합니다.
현재 제공하신 내용에는 OAuth2AuthorizedClientManager와 OAuth2AuthorizedClientProvider의 설정 관련 내용이 누락되어 있습니다. 따라서 다음을 확인해 주세요:
OAuth2AuthorizedClientManager와 어떻게 설정되어 있는지, 특히client-credentials를 처리할 수 있는OAuth2AuthorizedClientProvider가 포함되어 있는지 확인하세요.
client-credentials사용 시Authentication객체 대신 클라이언트의 인증 정보만을 사용하여 토큰을 요청하는 코드로 변경이 필요할 수 있습니다.
프로그램의 나머지 부분에 오류가 없다면 이 점을 검토하셔서 문제를 해결해 보시기 바랍니다.





