스프링 시큐리티 OAuth2/OAuth 2.0 Client - oauth2Client()

DefaultOAuth2AuthorizedClientManager - Client Credentials 권한 부여 구현하기

webmaster 2023. 2. 21. 23:36
728x90

Client Credentials

  • OAuth2AuthorizeRequest에 요청 정보를 담아 OAuth2AuthoriedClientManager에 요청을 한다.
  • OAuth2AuthoriedClientManager는 OAuth2AuthoriedClient 가 존재 하지 않는지를 판단하고 존재하지 않는다면, OAuth2AuthoriedContext 정보를 토대로 인가를 받는다.
  • OAuth2AuthoriedContext가 ClientCredentialsOAuth2AuthorizedClientProvider에 전달이 되고, OAuth2AuthoriedClient와 token이 만료되었는지 확인한다 
  • 이후부터는 DefaultClientCredentialsTokenReponseClient, DefaultClientCredentialsGrantRequestEntityConverter에서 인증 서버로 인증 요청을 하게 되고, OAuth2AccessTokenResponse를 응답받는다(여기에는 RefreshToken이 존재하지 x)

Test

LoginController

@Controller
public class LoginController {

  @Autowired
  private DefaultOAuth2AuthorizedClientManager oAuth2AuthorizedClientManager;

  @Autowired
  private OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository;

  @GetMapping("/oauth2Login")
  public String oauth2Login(Model model, HttpServletRequest request, HttpServletResponse response) {

    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

    OAuth2AuthorizeRequest auth2AuthorizeRequest =
        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);
    };
    oAuth2AuthorizedClientManager.setAuthorizationSuccessHandler(successHandler);


    OAuth2AuthorizedClient authorizedClient = oAuth2AuthorizedClientManager.authorize(
        auth2AuthorizeRequest);

    model.addAttribute("authorizedClient", authorizedClient.getAccessToken().getTokenValue());
    //client 자체가 사용자 역할을 겸해서 하기 때문에 별도의 사용자 정보를 통해 인증처리하는 과정이 필요가 없다
    //해당 방식은 토큰은 발급 받았지만 실제 유저에 대한 인증은 받지 않은 것이기 때문에 해당 방식을 사용할 때는 클라이언트 끼리 통신할 때 많이 사용한다

    return "home";
  }

  @GetMapping("/logout")
  public String logout(Authentication authentication, HttpServletRequest request,
      HttpServletResponse response) {
    SecurityContextLogoutHandler logoutHandler = new SecurityContextLogoutHandler();
    logoutHandler.logout(request, response, authentication);
    return "redirect:/";
  }
}
  • Client Credentials 방식 같은 경우, 별도의 사용자 정보를 인증처리하는 과정이 필요하지 않다 
    • client 자체가 사용자 역할을 겸하기 때문에
  • Token 은 발급 받았지만, 실제 유저에 대한 인증 여부를 확인하면, "익명 사용자"로 인증이 된다(인증 처리 하는 과정이 없었기 때문)
    • 따라서 해당 방식은 대게 client끼리 통신을 할 때 주로 사용이 된다.
728x90