ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Oauth2 + JWT
    카테고리 없음 2024. 2. 11. 01:43

     

    OAuth2 동작원리

    출처: 유튜브 (개발자 유미)

     

    OAuth2 변수 설정 

    #registration
    spring.security.oauth2.client.registration.naver.client-name=naver
    spring.security.oauth2.client.registration.naver.client-id=발급아이디
    spring.security.oauth2.client.registration.naver.client-secret=발급비밀번호
    spring.security.oauth2.client.registration.naver.redirect-uri=http://localhost:8080/login/oauth2/code/naver
    spring.security.oauth2.client.registration.naver.authorization-grant-type=authorization_code
    spring.security.oauth2.client.registration.naver.scope=name,email
    
    #provider
    spring.security.oauth2.client.provider.naver.authorization-uri=https://nid.naver.com/oauth2.0/authorize
    spring.security.oauth2.client.provider.naver.token-uri=https://nid.naver.com/oauth2.0/token
    spring.security.oauth2.client.provider.naver.user-info-uri=https://openapi.naver.com/v1/nid/me
    spring.security.oauth2.client.provider.naver.user-name-attribute=response

     

    -> redirect-uri : 로그인 성공 후 로그인 완료시 -> From 인증서버 to 어플리케이션 서버 

       보통 /login/oauth2/code/서비스명으로 고정 (커스텀 설정 가능) 

     

    @Service
    @Slf4j
    public class CustomOAuth2UserService implements OAuth2UserService<OAuth2UserRequest, OAuth2User> {
    
        @Override
        public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
            //기본 OAuth2UserService 객체 생성 (기본으로 등록된 Service와 Custom을 동시에 사용할 것이다)
            OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService = new DefaultOAuth2UserService();
    
            //OAuth2USerService를 사용하여 OAuth2User정보를 가져오기
            OAuth2User oAuth2User = oAuth2UserService.loadUser(userRequest);
            log.info("oauth2User  = {}",oAuth2User);
    
            
    
            //클라이언트 등록아이디인 Naver,google,kakao 같은 정보를 가져움
            String registrationId = userRequest.getClientRegistration().getRegistrationId();
            OAuth2Response oAuth2Response = null;
    
            return null;
        }
    }

     

    -> OAuth 인증을 진행 -> 외부 인증서버에서 인증에 성공하면,

       OAuth2UserRequest 객체에 제공자에 대한 정보, 엑세스 토큰 등과 같은 정보를 넣어서

       CustomOAuth2UserService로 넘어옴! 

     

    	private final ClientRegistration clientRegistration;
    
    	private final OAuth2AccessToken accessToken;
    
    	private final Map<String, Object> additionalParameters;
    User Attributes: [{resultcode=00, message=success, response={id=ZvmRu4IZEdjDsvi-GBdpqim75HhBUQPmsdE-8sORKRs, email=이메일, name=사용자명}}]

     

     

     

    - 처음에 변수에 설정한 

     /oauth2/authorization/kakao로 요청

    -> OAuth2AuthorizationRequestRedirectFilter의  doFilter발동

    -> DefaultOAuth2AuthorizationRequestResolver의 resolve메서드 내부호출 -> 요청이 필요로 하는 페이지로 redirect시켜줌 (redirect로 설정한 페이지) 

       -> resolve메서드 내부에서 resolveRegistationId를 request에서 뽑고 null인지 아닌지 확인

        -> resolveRegistrationId는 요청 uri가 해당 pattern과 일치하면 uri에서 REGISTRATION_ID_URI_VARIABLE_NAME를 꺼내서 값을 반환

    autorizationRequestBaseUri + / + {registrationId} (매칭되는 값)

     

    -> OAuth2ClientConfigurer파일에 BaseUri가 등록되어있음 (/oauth2/authorization)

    ->resolve메서드는 redirect-uri를 만들고 가공  (application.yml에 registraionId(naver,kakao)를 가져옴

     

    1. 사용자가 /oauth2/authorization/kakao로 요청

    2. ReqeustResolver가  uri패턴 검사 (/oauth2/authorization/{registrationId} 패턴이 맞으면 registraionId변수에 바인딩된 변수를 가져옴 

    3. 변수값을 바탕으로 ClientRegistraion조회

    4. 해당 값으로 redirect-uri가공

    5. 사용자에게 가공된 redicrect-rui로 해당 페이지 redirect함  

    //

    요청보내면, 여기까지 오는 흐름 인 것 같다
    https://nid.naver.com/oauth2.0/authorize

     

    -> 해당 페이지에서 이메일 비밀번호 입력후 로그인 완료 

    -> 우리 애플리케이션 측에 redirect-uri로 인증코드, access토큰 발급 해줄 것이다.

     

    1. OAuth2LoginAuthenticationFilter에 attemptAuthentication 메서드 호출 -> Provider Manager의 authenticate메서드 호출

    2. OAuth2LoginAuthenticationProvider의 authenticate 한번 더 호출 -> 인가받은 코드로  Access Token API 호출

    3. Access Token을 받아오면, OAuth2User에 LoadUser메서드 호출 -> userService에 loadUser 메서드 호출되고 ->

    Oaut2UserDetail을 반환 (UserService내부에서 load.user를 통해 Access Token의 사용자 정보 읽음)

    -> 일단 여기까지 흐름이 오면, 소셜 로그인은 완료한 것이다. 따라서 해당 웹어플리케이션에 user가 있는지 없는지 검사하고 -> 새로운 회원가입 혹은 AccessToken을 발급해주자

     

     

     

    *Session create policy stateless

    ->한 요청의 응답이 나갈때 까지만, 유지된다. 따라서 oauth2로 로그인이 완료될 때까진 유지됨

    -> oauth2로 로그인이 완료되면,

     Authentication auth = getAuthentication(Oauth2User);
     SecurityContextHolder.getContext().setAuthentication(auth);

     

    -> 위와 같은 메서드를 따라 SecurityContext에 Oauth2User를 한번 저장함 

    -> Security Context란 스프링 시큐리티 내부에 세션저장소와 비슷한 개념으로, 여기에 저장할 수 있는 값은 

    -> Authentication 객체 뿐이다. 

     -> 값을 꺼낼 때는 어노테이션을 사용하던, SecurityContextHolder.getContext.getAuthentication()을 호출하면된다.

Designed by Tistory.