【Swift】新規登録かログインか判定する(Firebase)
初めに
今回は Swift × FirebaseAuth × Google Sign In で実装した Google のサインインに関して、新規登録かログインのユーザーかを判定する必要があったので、その方法を共有したいと思います。
記事の対象者
- SwiftUI 学習者
- FirebaseAuth を用いて Google Sign In を実装したい方
- Google Sign In において新規登録とログインを明確に区別したい方
目的
改善前
Google Sign Inを利用したユーザーは、新規登録のユーザーなのか、すでに一度登録していて、ログインしているユーザーなのか判別できない
したがって、Google でサインインした後の遷移先を分けられない
新規登録の場合 | ログインの場合 |
---|---|
通常の createUser や signIn であれば遷移先は容易に指定可能でしたが、Google Sign In の場合は設定できていませんでした。
改善後
新規登録の場合はチュートリアル画面に、ログインの場合はホーム画面に遷移といったように遷移先を振り分けることができる
新規登録の場合 | ログインの場合 |
---|---|
実装
今回は Firebase プロジェクトとの連携や Google Sign In パッケージの導入は済んでいる状態を想定して実装を進めていきます。
詳しい実装に関しては Firebase の公式ページをご参照ください
改善前
func signInWithGoogle() async -> Bool {
guard let clientID = FirebaseApp.app()?.options.clientID else {
fatalError("No client ID found in Firebase configuration")
}
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
guard let windowScene = await UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = await windowScene.windows.first,
let rootViewController = await window.rootViewController else {
return false
}
do {
let userAuthentication = try await GIDSignIn.sharedInstance.signIn(withPresenting: rootViewController)
let user = userAuthentication.user
guard let idToken = user.idToken else {
print("error occured during google sign in")
return false
}
let accessToken = user.accessToken
let credential = GoogleAuthProvider.credential(
withIDToken: idToken.tokenString,
accessToken: accessToken.tokenString
)
let result = try await Auth.auth().signIn(with: credential)
return true
}
catch {
print(error.localizedDescription)
return false
}
}
改善後
func signInWithGoogle() async -> Bool {
guard let clientID = FirebaseApp.app()?.options.clientID else {
fatalError("No client ID found in Firebase configuration")
}
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.configuration = config
guard let windowScene = await UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = await windowScene.windows.first,
let rootViewController = await window.rootViewController else {
return false
}
do {
let userAuthentication = try await GIDSignIn.sharedInstance.signIn(withPresenting: rootViewController)
let user = userAuthentication.user
guard let idToken = user.idToken else {
print("error occured during google sign in")
return false
}
let accessToken = user.accessToken
let credential = GoogleAuthProvider.credential(
withIDToken: idToken.tokenString,
accessToken: accessToken.tokenString
)
let result = try await Auth.auth().signIn(with: credential)
+ if let isNewUser = result.additionalUserInfo?.isNewUser, isNewUser {
+ print("This is a new user.")
+ self.isRegisterSuccess = true
+ } else {
+ print("This is an existing user")
+ self.isLoginSuccess = true
+ }
return true
}
catch {
print(error.localizedDescription)
return false
}
}
AuthResult
型の result
として、Auth.auth().signIn(with: credential)
の返り値を指定しています。
そして、AuthResult
は additionalUserInfo
を持っています。
additionalUserInfo
の中には、今回使用したい isNewUser
が含まれています。
この isNewUser
は公式ドキュメントの説明の「Returns whether the user is new or existing」にある通り、Google を使ってサインインしたユーザーが新しいユーザーなのか、既に一度登録したことがあるユーザーなのかを Boolean 形式で返します。
また、コードにあった isRegisterSuccess
isLoginSuccess
に関して、新規登録またはログインが成功した際に true にすることで、View側にそれを伝播することができます。
この二つの変数に関しては、外部から参照できるように @Published として指定しておきます。
@Published var isRegisterSuccess: Bool = false
@Published var isLoginSuccess: Bool = false
View側で使用する
まずは以下のように ObservedObject
として AuthViewModel
を受け取ります。
@ObservedObject var authViewModel: AuthViewModel = AuthViewModel()
次にボタンのアクションで signInWithGoogle
を指定します。
なお、非同期処理で行うため、Task
内に処理を記述します。
Button(action: {
Task {
do {
await authViewModel.signInWithGoogle()
}
}
}) {
Text("Googleでサインイン")
}
最後に AuthViewModel
で Published として指定していた isRegisterSuccess
と isLoginSuccess
をそれぞれチュートリアル画面、ホーム画面への遷移のトリガーとして指定します。
.fullScreenCover(isPresented: $authViewModel.isRegisterSuccess) {
IntroView()
}
.fullScreenCover(isPresented: $authViewModel.isLoginSuccess) {
HomeView()
}
これで、新規登録のユーザーとログインのユーザーで表示させる画面を切り替えることができるようになったかと思います。
まとめ
最後まで読んでいただいてありがとうございました。
Google Sign In に関しては新規登録とログインの切り分けができておらず、すぐに変更しました。
今回紹介した isNewUser
以外にも getProfile
や getUsername
などもあったので、機会があれば触れてみたいと思います。
誤っている点等あればご指摘いただければ幸いです。
参考
Discussion