[Spring] redis를 저장소로 쓰면서 oauth2 인증도 세션으로?

김정연·2024년 12월 1일
0

oauth2 & redis

목록 보기
3/3
post-thumbnail

세션 저장소로 redis를 이용중인데 oauth2 로그인 구현 후 실행시켜보니.. 세션에 저장한 기존 회원 데이터가 null이였다.

어떤 상황이냐면 스피너 프로젝트는 소셜 로그인에서 sub 값만 받아오기 때문에 소셜 로그인을 연동할 때 이메일 값이 필수로 있어야한다.

회원가입 로직

기본적으로 세션은 레디스를 사용하기 때문에 세션에 이메일 등록시점에는 이메일 인증할 때 썻던 레디스 키 값을 그대로 사용하면서 만료시간만 10분으로 늘리게 작성했다.

 @Override
    public OAuth2User loadUser(OAuth2UserRequest oAuth2UserRequest){

        String clientId = oAuth2UserRequest.getClientRegistration().getRegistrationId();

        OAuth2User user = super.loadUser(oAuth2UserRequest);
        Map<String, Object> attributes = user.getAttributes();
        String sub = "";

        switch (clientId){
            case "google":
                sub = attributes.get("sub").toString();
                break;
            case "kakao" :
                sub = attributes.get("id").toString();
                break;
            case "naver" :
                @SuppressWarnings("unchecked")
                Map<String, Object> res = (Map<String, Object>) attributes.get("response");
                sub = res.get("id").toString();
                break;
            default:
                throw new IllegalArgumentException("지원되지 않는 소셜 로그인입니다: " + clientId);
        }


        // sub 가 있는지 없는지
        Social social = socialService.getSocial(sub);

        // 있으면 로그인 처리
        if (social != null)  {
            socialService.loginSocial(social);
        } else {
            // 자사 회원이면서 소셜 연동 하려면
            if(sessionInfo.getMemberEmail() != null){
                socialService.joinSocialMember(sub, sessionInfo.getMemberEmail(), clientId);
            } else {
                // 회원가입으로
                throw new ResponseStatusException(HttpStatus.NOT_FOUND, "가입된 회원이 아닙니다.");
            }
        }

        return user;
    }

redis sessionId

이렇게 oauthService까지 다 작성하고 테스트를 위해 코드를 돌렸는데
로그인 이후에 소셜로그인을 시도해봤지만 session에 이메일이 null 이라는 오류만 자꾸 떳다.
그래서 redis에서 직접 확인해봤다.

우선 로그인만 했을 때는 리프레쉬 토큰과 세션이 저장이 잘 되는 것을 확인했다.
이 상태에서는 세션에서 이메일 호출도 자유롭게 가능했다.

그리고 나서 oauth 로그인을 시도해보니 oauth 로그인 세션이 따로 생겨서 내가 아무리 세션에 있는 이메일을 조회해도 null로 나오고 있었다...

참고로 ci 값이 없어서 어느 소셜은 이메일을 주지만 안주는 소셜도 있어 이메일 값은 빼고 진행하고 있다.

소셜 로그인을 시도하는 시점에서는 내가 처음 세팅했던 세션을 같이 사용하도록 하고싶어서 시큐리티에서 설정도 직접 건드려봤다.

sessionFixation().none() 메서드

http
    .sessionManagement(session -> session
        .sessionFixation().none() // 세션 ID 고정 방지
    );

이 메서드는 인증 후에도 기존 세션 ID를 유지한다. 그리고 세션 고정 공격 방지가 비활성화 되어 보안상의 위험이 있다. 이렇게 해서 코드를 실행시켜보니 세션 ID는 1개이지만 기존 세션 데이터에 덮어져서 내가 원하는 결과가 나오지 않았다. 그래서 다른 방법으로 소셜 로그인이 완료되면 기존 세션 정보를 복사하는 핸들러를 작성했지만 이것도 결과가 만족스럽지 못했다.

인증 정보를 쿠키로 저장

그래서 다음으로 생각해낸 방법이 oauth 인증정보를 세션을 통하지 않고 쿠키로 저장하는 방식이다.
이 내용은 다음편에 작성할 계획이다!

profile
백엔드 개발자

0개의 댓글