지난번 SupaBase Storage에 이미지 업로드하기에 이어 이번에는 SupaBase를 사용하여 비밀번호 초기화 + 변경 기능을 구현해보자!
비밀번호를 잊었을 때 일반적으로 비밀번호 찾기 버튼을 누르면 메일을 발송 + 메일을 클릭해 본인 인증을 하면 기존의 비밀번호가 초기화 되고 새 비밀번호를 설정하는 로직
1. 비밀번호 찾기/초기화 뷰 구현
- 로그인 화면에 비밀번호 찾기/리셋 버튼을 넣는다.
- 해당 버튼을 클릭하면 비밀번호를 변경할 이메일을 입력 받는 뷰로 이동시킨다.
- 이메일을 입력 받으면 SupaBase sdk를 불러와서 해당 이메일로 PasswordReset 메일을 발송한다.
2. 딥링크 설정
- 뷰 구현을 하고 SupaBase 코드를 사용하기 전에 우선 SupaBase 홈페이지에서 URL 설정 + 프로젝트에서 딥링크 Scheme 을 설정해야한다.
- Project - Targets - Info - URL Types에 + 버튼을 눌러 URL Scheme을 설정한다
- SupaBase 홈페이지에 가서 해당되는 프로젝트 클릭 - Authentication - URL Configuration - Site URL에 앞서 적은 URL Schemes + host를 적는다. 예를 들어, example://reset 이런식으로!
- 이제 사용자가 받은 메일에 있는 링크를 클릭하면 우리가 설정한 딥링크로 인해 앱이 실행된다.
3. 이메일 발송 코드 구현
func resetPasswordForEmail(email: String) async -> Result<Void, MyError> {
do {
try await SupaClient.shared.auth.resetPasswordForEmail(email, redirectTo: URL(string: "example://reset")!)
return .success(())
} catch {
return .failure(.supabaseResetPasswordFailed(error: error))
}
}
- 사용자가 이메일을 입력하고 인증하기 버튼을 클릭하면 이 함수가 실행되어 본인 인증을 할 수 있는 메일이 발송되도록 한다.
- redirectTo에 앞서 정한 Site URL을 넣는다.
4. 비밀번호 변경 뷰로 연결
- 위와 같은 비빌번호를 새롭게 변경할 수 있도록 하는 뷰를 구현한다.
- 앞서 사용자가 받은 이메일의 링크를 클릭하면 우리가 만든 앱이 실행되고 진입하는 화면이 지금 만든 비밀번호 변경 뷰가 되도록 해야한다.
- UIKit을 사용하는 경우에는 AppDelegate.swift에서 해당 처리를 한다
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if url.host == "reset" {
// 비밀번호 찾기 뷰로 이동
}
return true
}
- 현재 진행중인 프로젝트는 SwiftUI 기반이기 때문에 ContentView에 onOpenURL 를 지정하여 딥링크로 열었을 때를 핸들링한다.
var body: some View {
ZStack {
// 생략
}
.onOpenURL { url in
AsyncTask {
await viewModel.updateSession(with: url)
}
}
}
- 여기서 받은 url(SupBase가 발급해준)을 잘 살펴보면 url에 accessToken가 refreshToken이 담겨 있는 것을 확인할 수 있다.
- 이것을 이용해 새로운 Session을 생성하고 사용자를 임시 로그인을 시킨 후 비밀번호를 재설정 + SupBase에 변경한 비밀번호로 사용자 정보 update를 진행한다.
- 이 부분에서 시간이 꽤 걸렸는데, 왜냐하면 이메일에서 링크를 클릭하여 앱이 받은 URL에 token들이 있는줄 몰랐기 때문이다.. 사용자 정보(비밀번호)를 업데이트 하려면 로그인이 되어 있어야하는데 이를 위해 세션이 필요하다. 사용자가 현재 비밀번호를 몰라서 로그인을 못하고 있는 상황인데 이 세션을 어떻게 만들지.. 이런 고민을 하다가 삽질 끝에 URL에 토큰이 담겨 오는 것을 발견했다..!!!
- 이 토큰들로 세션을 생성하고 비밀번호 업데이트를 진행하면 된다.
func updateSession(with url: URL) async -> Result<Session, MyError> {
guard let session = try? await SupaClient.shared.auth.session(from: url) else {
return .failure(.supabaseNoSession)
}
do {
let session = try await SupaClient.shared.auth.setSession(accessToken: session.accessToken, refreshToken: session.refreshToken)
return .success(session)
} catch {
return .failure(.supabaseUpdateSessionFailed(error: error))
}
}
5. 비밀번호 업데이트
- 비밀 번호 변경 뷰에서 비밀번호 변경 버튼을 클릭하면 사용자가 새로 지정한 비밀번호로 DB 정보를 업데이트한다.
func updatePassword(password: String) async -> Result<GoTrue.User, MyError> {
do {
let user = try await SupaClient.shared.auth.update(user: UserAttributes(password: password))
await signOut()
return .success(user)
} catch {
return .failure(.supabaseResetPasswordFailed(error: error))
}
}
- 비밀번호를 성공적으로 업데이트하면 사용자를 다시 로그인 뷰로 보내기 위해 SignOut()을 진행한다.
func signOut() async -> Result<String, MyError> {
do {
try await SupaClient.shared.auth.signOut()
return .success("로그아웃 성공")
} catch {
return .failure(.supabaseSignOutFailed(message: "로그아웃 try 실패함"))
}
}
정리
우리의 목표는 사용자가 비빌번호를 까먹어 로그인을 못할 때를 위해 비밀번호를 재설정할 수 있도록 기능을 제공하는 것이었다.
구현의 흐름을 요약하면 다음과 같다!
- 필요한 뷰들 구현 (이메일 입력, 새 비밀번호 입력 뷰)
- Targets info에 딥링크를 위한 설정
- SupaBase 홈페이지 URL Configuration 설정
- 이메일을 입력받으면 resetPasswordForEmail 실행
- 딥링크로 앱이 실행되면 이를 체크(ContentView에서 onOpenURL에서)하여 비밀번호 변경 뷰로 이동시키기
- 5에서 받은 url로 임시 Session 생성
- 사용자가 새로 입력한 비밀번호로 유저 정보를 update 하기 (임시 세션 상태에서)
- 성공하면 사용자를 다시 SignOut 시키고 로그인 뷰로 이동시키기
- 새로 만든 비밀번호로 로그인
'iOS > 개발' 카테고리의 다른 글
[iOS] 프로젝트 개발 환경 세팅 자동화 with fastlane, Makefile (0) | 2023.08.07 |
---|---|
[Swift] iOS 네이버 지도 SDK - 지도 뷰 커스텀 (3) | 2023.07.12 |
Fastlane으로 Versioning 하기 (+ 트러블 슈팅) (0) | 2023.07.03 |
Swift Moya에 Interceptor 적용하여 자동로그인(토큰 갱신) 구현하기 (5) | 2023.04.08 |
Swift SupaBase SDK로 Storage에 이미지 업로드 (0) | 2023.03.14 |
댓글