현재 프로젝트에서 카카오 로그인 API를 사용 중이다.
이는 소셜 간편 로그인을 이용하기 위함인데,
그 과정에서 BadCredentialException
을 마주하게 됐다.
해당 예외는 기본적으로 AuthenticationException
의 하위 예외이다.
아래와 같은 상황에 예외가 발생한다.
- 찾을 수 없는 User일 때
- User의 아이디가 틀렸을 때
- User의 비밀번호가 틀렸을 때
어떤 상황에서 발생한 오류인지는 알려주지 않는다.
그 이유는 보안을 위해 BadCredential
로만 퉁친다고 한다.
아래와 같이 Exception
이 발생함을 확인할 수 있다.
예외의 원인으로 의심되는 상황은 2가지였다.
- 회원가입과 로그인을 하나의 Logic에 넣어놓아 문제가 발생했다.
- 함수는 따로 만들어 놓았기 때문에 가능성은 낮지만 확인해봐야 한다.
- Transaction 단위의 범위에 대해 생각을 해보아야 할 것 같다.
loadByUserName()
에서 가져오는 UserDetail에 문제가 있다.authentication
은loadByUserName()
을 통해 정보를 가져온다.- 나는 해당 함수를 Custom 해놓았기 때문에 확인이 필요할 것 같다.
저장이 잘 되었는가?
1번 원인을 조사해보기 위해서, 과정에서 저장이 되는지 확인 해보았다.
아래와 같이 해당 email
로 찾았을 때, Member
값이 비었는지 확인한다.
결과는 아래와 같이 false
.
isEmpty()
method를 통해 검증했으니, 이는 저장이 되었다는 의미이다.
그렇다면 1번 원인은 아님이 확정되었다!
UserDetail의 문제
2번 원인을 조사하기 위해서, 일반 로그인 Service
를 확인해보았다.
일반 로그인의 검증 과정에서 아래와 같이 문제를 찾을 수 있었다.
일반 로그인의 검증에서는 loginDto
의 Password를 그대로 넘겨주고 있었다.
그 말인 즉슨, passwordEncoder
에 의해 암호화 되기 전의 상태라는 의미이다.
하지만 내가 구현한 카카오 로그인 서비스는 아래와 같이 구현해 놓았다.
암호화해서 저장을 한 뒤, 그대로 암호화 한 Password를 넘겨주었다.
그러면 당연히 검증을 암호화 된 상태로 진행하니, 예외가 발생할 수 밖에 없는 것이다.
따라서 아래와 같이 kakaoPassword
라는 암호화 이전 값으로 바꾸어주었다.
아래와 같이 카카오 회원으로 회원가입이 잘 되었음을 볼 수 있다.
해당 문제는 더 자세히 확인 해볼것이지만,
UserDetail
객체를 생성할 때 암호화 이전의 패스워드가 저장이 되는 듯하다.
그럼 당연히 해당 값과 암호화 된 패스워드는 일치하지 않을 것이다.
따라서 자격 증명에 실패했다는 오류가 뜨는 것 같다.