프로젝트에서 비밀번호 변경 페이지를 맡아 개발하고 있었다. firebase를 사용해 이메일/비밀번호로 인증관리를 했는데, firebase에서는 보안상의 이유로 직접 유저의 비밀번호를 가져올 수 없기 때문에 updatePassword()
로 비밀번호를 바꿔주었다.
FirebaseAuth.instance.currentUser
?.updatePassword(_newPasswordController.text);
TextField에 입력한 값을 메소드에 전달하면 끝인 줄 알았다. 하지만 변경이 될 때도 있고 안될 때도 있었다. 그리고 콘솔에는 아래와 같은 에러 메세지가 떴다 😭😭😭
updatePassword의 설명은 위와 같다. 읽다보면 중요한 부분이 있는데, 이 함수는 보안의 이유로 재인증을 먼저 해줘야 한다. 즉, reauthenticateWithCredential()을 사용해서 재인증을 한 후 비밀번호를 변경해야 하는 것이다.
- 현재 credential 저장
현재 비밀번호를 입력하는 TextField를 만들어 유저로부터 현재 비밀번호를 입력받았다. 이 입력값을 credential의 password 필드에 넣어주었다.
final cred = await EmailAuthProvider.credential(
email: currentUser.email!,
password: _currentPasswordController.text);
- reauthenticateWithCredential 함수 호출
currentUser에 reauthenticateWithCredential()을 호출한다. 인자로는 위에서 저장해둔 credential을 사용한다.
final currentUser = FirebaseAuth.instance.currentUser!;
currentUser.reauthenticateWithCredential(cred);
- then() 안에 updatePassword() 호출
재인증이 끝난 후 비밀번호를 변경하기 위해 then() 안에서 updatePassword()를 호출한다.
currentUser.reauthenticateWithCredential(cred)
.then((value) async {
await currentUser
.updatePassword(_newPasswordController.text);
// 비밀번호 변경 후 해야하는 작업 추가
// ex. 로그아웃, 로그인 페이지 이동
})
- reauthenticateWithCredential() 에러 처리
reauthenticateWithCredential()에 대한 설명인데, 무려 예외 케이스가 7개나 있다 😭 내 코드에서는 유저가 입력한 현재 비밀번호가 실제 비밀번호와 다른 경우 invalid-credential 에러가 발생했다. 그래서 catchError()로 예외 처리를 했다.
아래는 예외처리까지 적용한 코드이다.
currentUser.reauthenticateWithCredential(cred)
.then((value) async {
await currentUser
.updatePassword(_newPasswordController.text);
}).catchError((error) {
if (error is FirebaseAuthException) {
if (error.code == 'invalid-credential') {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('입력하신 현재 비밀번호가 틀렸습니다.'),
),
);
}
// 다른 예외 경우에 대한 처리 추가하면 좋음
else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('인증 오류가 발생했습니다. 잠시후 다시 시도해주세요.'),
),
);
}
}
// FirebaseAuth와 관련되지 않은 예외 처리
else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('오류가 발생했습니다. 잠시후 다시 시도해주세요.'),
),
);
}
});
FirebaseAuthException인 경우와 그 외의 예외를 구분했고, FirebaseAuthException 중에서 특정 케이스 (나의 경우 invalid-credential)에 대한 예외 처리를 할 수 있도록 구현해봤다.
역시 인증 관련 로직 구현은 복잡하다. firebase로 간단하게 했음에도 신경써야할게 많다는걸 알게 되었다. firebase에서도 나름 보안을 신경쓴 것 같아 안심이다!